Compare commits

...

4 commits

20 changed files with 324 additions and 259 deletions

View file

@ -62,8 +62,8 @@
#
# Features of found Corrade library are exposed in these variables:
#
# CORRADE_MSVC2019_COMPATIBILITY - Defined if compiled with compatibility
# mode for MSVC 2019
# CORRADE_MSVC_COMPATIBILITY - Defined if compiled with compatibility
# mode for MSVC 2019+ without the /permissive- flag set
# 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 targetting Xcode
# CORRADE_TESTSUITE_TARGET_XCTEST - Defined if TestSuite is targeting 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
# 2017, 2018, 2019, 2020, 2021, 2022
# 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
MSVC2019_COMPATIBILITY
MSVC_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)
# Directory::libraryLocation() needs this
# Path::libraryLocation() needs this
if(CORRADE_TARGET_UNIX)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})

View file

@ -36,7 +36,7 @@
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
# 2020, 2021, 2022 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,11 +59,18 @@
#
# In 1.71 ImGui depends on the ApplicationServices framework for macOS
# clipboard support. It's removed again in 1.72. TODO: remove once obsolete
# 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.
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 --
@ -75,7 +82,6 @@ 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})
@ -104,7 +110,6 @@ 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})

View file

@ -60,6 +60,7 @@
# MeshTools - MeshTools library
# Primitives - Primitives library
# SceneGraph - SceneGraph library
# SceneTools - SceneTools library
# Shaders - Shaders library
# ShaderTools - ShaderTools library
# Text - Text library
@ -201,7 +202,7 @@
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
# 2020, 2021, 2022 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"),
@ -229,7 +230,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|ShaderTools|Text|TextureTools|Trade|.+Importer|.+ImageConverter|.+Font|.+ShaderConverter)$")
if(_component MATCHES "^(Audio|DebugTools|MeshTools|Primitives|SceneTools|ShaderTools|Text|TextureTools|Trade|.+Importer|.+ImageConverter|.+Font|.+ShaderConverter)$")
set(_MAGNUM_${_COMPONENT}_CORRADE_DEPENDENCIES PluginManager)
endif()
@ -354,8 +355,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 Shaders ShaderTools
Text TextureTools Trade
Audio DebugTools GL MeshTools Primitives SceneGraph SceneTools Shaders
ShaderTools Text TextureTools Trade
WindowlessEglApplication EglContext OpenGLTester)
set(_MAGNUM_PLUGIN_COMPONENTS
AnyAudioImporter AnyImageConverter AnyImageImporter AnySceneConverter
@ -387,8 +388,7 @@ if(CORRADE_TARGET_EMSCRIPTEN)
endif()
if(CORRADE_TARGET_IOS)
list(APPEND _MAGNUM_LIBRARY_COMPONENTS WindowlessIosApplication)
endif()
if(CORRADE_TARGET_APPLE AND NOT CORRADE_TARGET_IOS)
elseif(CORRADE_TARGET_APPLE AND NOT MAGNUM_TARGET_GLES)
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)
elseif(CORRADE_TARGET_APPLE AND NOT MAGNUM_TARGET_GLES)
list(APPEND _MAGNUM_OpenGLTester_DEPENDENCIES WindowlessCglApplication)
elseif(CORRADE_TARGET_UNIX)
if(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_DESKTOP_GLES)
@ -451,8 +451,11 @@ 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)
@ -466,6 +469,7 @@ 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)
@ -608,7 +612,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
# accidentaly break something else
# accidentally break something else
set(_tmp_prefixes "${CMAKE_FIND_LIBRARY_PREFIXES}")
set(CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES};")

View file

@ -48,7 +48,7 @@
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
# 2020, 2021, 2022 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

View file

@ -20,7 +20,7 @@
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
# 2020, 2021, 2022 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,37 +168,38 @@ find_path(SDL2_INCLUDE_DIR
if(CORRADE_TARGET_WINDOWS)
find_file(SDL2_DLL_RELEASE
NAMES SDL2.dll
PATH_SUFFIXES ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
PATH_SUFFIXES bin ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
find_file(SDL2_DLL_DEBUG
NAMES SDL2d.dll # not sure?
PATH_SUFFIXES ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
PATH_SUFFIXES bin ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
endif()
# (Static) macOS / iOS dependencies
if(CORRADE_TARGET_APPLE AND SDL2_LIBRARY MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$")
# (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
if(CORRADE_TARGET_IOS)
set(_SDL2_FRAMEWORKS
AudioToolbox
AVFoundation
list(APPEND _SDL2_FRAMEWORKS
CoreBluetooth # needed since 2.0.10
CoreGraphics
CoreMotion
Foundation
GameController
Metal # needed since 2.0.8
QuartzCore
UIKit)
else()
# Those are needed when building SDL statically using its CMake project
set(_SDL2_FRAMEWORKS
iconv # should be in the system
AudioToolbox
AVFoundation
list(APPEND _SDL2_FRAMEWORKS
Carbon
Cocoa
CoreAudio
CoreVideo
ForceFeedback
Foundation
IOKit)
endif()
set(_SDL2_FRAMEWORK_LIBRARIES )
@ -247,7 +248,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 MATCHES ".*libSDL2.a$")
if(CORRADE_TARGET_APPLE AND (SDL2_LIBRARY_DEBUG MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$" OR SDL2_LIBRARY_RELEASE MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$"))
set_property(TARGET SDL2::SDL2 APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${_SDL2_FRAMEWORK_LIBRARIES})
endif()

View file

@ -15,11 +15,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <algorithm>
#include <string>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/Path.h>
#include "../UESaveFile/Types/ArrayProperty.h"
#include "../UESaveFile/Types/BoolProperty.h"
@ -37,9 +36,10 @@
using namespace Containers::Literals;
Mass::Mass(const std::string& path) {
_folder = Utility::Directory::path(path);
_filename = Utility::Directory::filename(path);
Mass::Mass(Containers::StringView path) {
auto split = Utility::Path::split(path);
_folder = split.first();
_filename = split.second();
refreshValues();
}
@ -49,7 +49,7 @@ auto Mass::lastError() -> Containers::StringView {
}
auto Mass::getNameFromFile(Containers::StringView path) -> Containers::Optional<Containers::String> {
if(!Utility::Directory::exists(path)) {
if(!Utility::Path::exists(path)) {
Utility::Error{} << path << "couldn't be found."_s;
return Containers::NullOpt;
}
@ -79,13 +79,13 @@ auto Mass::getNameFromFile(Containers::StringView path) -> Containers::Optional<
}
void Mass::refreshValues() {
if(!Utility::Directory::exists(Utility::Directory::join(_folder, _filename))) {
if(!Utility::Path::exists(Utility::Path::join(_folder, _filename))) {
_state = State::Empty;
return;
}
if(!_mass) {
_mass.emplace(Utility::Directory::join(_folder, _filename));
_mass.emplace(Utility::Path::join(_folder, _filename));
if(!_mass->valid()) {
_state = State::Invalid;
return;

View file

@ -48,7 +48,7 @@ class Mass {
Empty, Invalid, Valid
};
explicit Mass(const std::string& path);
explicit Mass(Containers::StringView path);
Mass(const Mass&) = delete;
Mass& operator=(const Mass&) = delete;

View file

@ -16,10 +16,8 @@
#include <algorithm>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/String.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/Path.h>
#include "MassManager.h"
@ -35,12 +33,12 @@ MassManager::MassManager(Containers::StringView save_path, Containers::StringVie
Containers::String mass_filename = "";
for(int i = 0; i < 32; i++) {
mass_filename = Utility::Directory::join(_saveDirectory, Utility::formatString("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
mass_filename = Utility::Path::join(_saveDirectory, Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
Containers::arrayAppend(_hangars, Mass{mass_filename});
}
if(!Utility::Directory::exists(_stagingAreaDirectory)) {
Utility::Directory::mkpath(_stagingAreaDirectory);
if(!Utility::Path::exists(_stagingAreaDirectory)) {
Utility::Path::make(_stagingAreaDirectory);
}
refreshStagedMasses();
@ -60,7 +58,8 @@ void MassManager::refreshHangar(Int hangar) {
}
Containers::String mass_filename =
Utility::Directory::join(_saveDirectory, Utility::formatString("{}Unit{:.2d}{}.sav", _demo ? "Demo" : "", hangar, _account));
Utility::Path::join(_saveDirectory,
Utility::format("{}Unit{:.2d}{}.sav", _demo ? "Demo" : "", hangar, _account));
_hangars[hangar] = Mass{mass_filename};
}
@ -77,26 +76,26 @@ auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bo
return false;
}
Containers::String source = Utility::Directory::join(_stagingAreaDirectory, staged_fn);
Utility::Directory::copy(source, source + ".tmp"_s);
Containers::String source = Utility::Path::join(_stagingAreaDirectory, staged_fn);
Utility::Path::copy(source, source + ".tmp"_s);
{
Mass mass{source + ".tmp"_s};
if(!mass.updateAccount(_account)) {
_lastError = mass.lastError();
Utility::Directory::rm(source + ".tmp"_s);
Utility::Path::remove(source + ".tmp"_s);
return false;
}
}
Containers::String dest = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
Containers::String dest = Utility::Path::join(_saveDirectory, _hangars[hangar].filename());
if(Utility::Directory::exists(dest)) {
Utility::Directory::rm(dest);
if(Utility::Path::exists(dest)) {
Utility::Path::remove(dest);
}
if(!Utility::Directory::move(source + ".tmp"_s, dest)) {
_lastError = Utility::formatString("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
if(!Utility::Path::move(source + ".tmp"_s, dest)) {
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
return false;
}
@ -110,16 +109,16 @@ auto MassManager::exportMass(Int hangar) -> bool {
}
if(_hangars[hangar].state() != Mass::State::Valid) {
_lastError = Utility::formatString("There is no valid data to export in hangar {:.2d}", hangar + 1);
_lastError = Utility::format("There is no valid data to export in hangar {:.2d}", hangar + 1);
return false;
}
Containers::String source = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
Containers::String dest = Utility::Directory::join(_stagingAreaDirectory,
Utility::formatString("{}_{}.sav", _hangars[hangar].name(), _account));
Containers::String source = Utility::Path::join(_saveDirectory, _hangars[hangar].filename());
Containers::String dest = Utility::Path::join(_stagingAreaDirectory,
Utility::format("{}_{}.sav", _hangars[hangar].name(), _account));
if(!Utility::Directory::copy(source, dest)) {
_lastError = Utility::formatString("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
if(!Utility::Path::copy(source, dest)) {
_lastError = Utility::format("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
return false;
}
@ -137,25 +136,25 @@ auto MassManager::moveMass(Int source, Int destination) -> bool {
return false;
}
Containers::String source_file = Utility::Directory::join(_saveDirectory, _hangars[source].filename());
Containers::String dest_file = Utility::Directory::join(_saveDirectory, _hangars[destination].filename());
Containers::String source_file = Utility::Path::join(_saveDirectory, _hangars[source].filename());
Containers::String dest_file = Utility::Path::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::Directory::rm(dest_file);
Utility::Path::remove(dest_file);
break;
case Mass::State::Valid:
Utility::Directory::move(dest_file, dest_file + ".tmp"_s);
Utility::Path::move(dest_file, dest_file + ".tmp"_s);
break;
}
Utility::Directory::move(source_file, dest_file);
Utility::Path::move(source_file, dest_file);
if(dest_state == Mass::State::Valid) {
Utility::Directory::move(dest_file + ".tmp"_s, source_file);
Utility::Path::move(dest_file + ".tmp"_s, source_file);
}
return true;
@ -167,8 +166,8 @@ auto MassManager::deleteMass(Int hangar) -> bool {
return false;
}
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _hangars[hangar].filename()))) {
_lastError = Utility::formatString("Deletion failed: {}", std::strerror(errno));
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _hangars[hangar].filename()))) {
_lastError = Utility::format("Deletion failed: {}", std::strerror(errno));
return false;
}
@ -182,17 +181,22 @@ auto MassManager::stagedMasses() -> std::map<Containers::String, Containers::Str
void MassManager::refreshStagedMasses() {
_stagedMasses.clear();
using Utility::Directory::Flag;
auto file_list = Utility::Directory::list(_stagingAreaDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
using Utility::Path::ListFlag;
auto file_list = Utility::Path::list(_stagingAreaDirectory, ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
auto iter = std::remove_if(file_list.begin(), file_list.end(), [](std::string& file){
return !Utility::String::endsWith(file, ".sav"_s);
if(!file_list) {
_lastError = _stagingAreaDirectory + " couldn't be opened"_s;
return;
}
auto iter = std::remove_if(file_list->begin(), file_list->end(), [](Containers::StringView file){
return file.hasSuffix(".sav"_s);
});
file_list.erase(iter, file_list.end());
auto list_view = file_list->except(file_list->end() - iter);
for(auto& file : file_list) {
auto name = Mass::getNameFromFile(Utility::Directory::join(_stagingAreaDirectory, file));
for(Containers::StringView file : list_view) {
auto name = Mass::getNameFromFile(Utility::Path::join(_stagingAreaDirectory, file));
if(name) {
_stagedMasses[file] = *name;
@ -206,7 +210,7 @@ auto MassManager::deleteStagedMass(Containers::StringView filename) -> bool {
return false;
}
if(!Utility::Directory::rm(Utility::Directory::join(_stagingAreaDirectory, filename))) {
if(!Utility::Path::remove(Utility::Path::join(_stagingAreaDirectory, filename))) {
_lastError = filename + " couldn't be deleted: " + std::strerror(errno);
return false;
}

View file

@ -17,11 +17,10 @@
#include <algorithm>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/String.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/Format.h>
#include "../UESaveFile/Types/ArrayProperty.h"
#include "../UESaveFile/Types/ResourceItemValue.h"
@ -41,7 +40,7 @@ Profile::Profile(Containers::StringView path):
return;
}
_filename = Utility::Directory::filename(path);
_filename = Utility::Path::split(path).second();
if(_filename.hasPrefix("Demo"_s)) {
_type = ProfileType::Demo;
@ -84,10 +83,18 @@ 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::isLegacy() const -> bool {
return _version == ProfileVersion::Legacy;
}
auto Profile::account() const -> Containers::StringView {
return _account;
}

View file

@ -49,8 +49,10 @@ class Profile {
auto filename() const -> Containers::StringView;
auto type() const -> ProfileType;
auto isDemo() const -> bool;
auto version() const -> ProfileVersion;
auto isLegacy() const -> bool;
auto account() const -> Containers::StringView;

View file

@ -23,9 +23,8 @@
#include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/String.h>
#include <zip.h>
@ -56,8 +55,14 @@ auto ProfileManager::profiles() -> Containers::ArrayView<Profile> {
auto ProfileManager::refreshProfiles() -> bool {
_profiles = Containers::Array<Profile>{};
using Utility::Directory::Flag;
auto files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
using Utility::Path::ListFlag;
auto files = Utility::Path::list(_saveDirectory,
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
if(!files) {
_lastError = _saveDirectory + " can't be opened.";
return false;
}
auto predicate = [](Containers::StringView file)->bool{
std::regex legacy_regex("(Demo)?Profile[0-9]{17}\\.sav", std::regex::nosubs);
@ -66,13 +71,13 @@ auto ProfileManager::refreshProfiles() -> bool {
return !std::regex_match(file.data(), m, legacy_regex) && !std::regex_match(file.data(), m, new_regex);
};
files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end());
auto files_view = files->except(files->end() - std::remove_if(files->begin(), files->end(), predicate));
for(const auto& file : files) {
Profile profile{Utility::Directory::join(_saveDirectory, file)};
for(const auto& file : files_view) {
Profile profile{Utility::Path::join(_saveDirectory, file)};
if(!profile.valid()) {
Utility::Warning{} << "Profile"_s << file.c_str() << "is invalid:"_s << profile.lastError();
Utility::Warning{} << "Profile"_s << file << "is invalid:"_s << profile.lastError();
continue;
}
@ -92,7 +97,7 @@ auto ProfileManager::getProfile(std::size_t index) -> Profile* {
}
auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> bool {
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _profiles[index].filename()))) {
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _profiles[index].filename()))) {
_lastError = Utility::format("Couldn't delete {} (filename: {}).",
_profiles[index].companyName(),
_profiles[index].filename());
@ -105,7 +110,7 @@ auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> boo
auto filename = Utility::format("{}Unit{:.2d}{}.sav",
_profiles[index].type() == ProfileType::Demo ? "Demo": "",
i, _profiles[index].account());
Utility::Directory::rm(Utility::Directory::join(_saveDirectory, filename));
Utility::Path::remove(Utility::Path::join(_saveDirectory, filename));
}
}
@ -124,20 +129,20 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
std::tm* time = std::localtime(&timestamp);
auto filename = Utility::format("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.mbprofbackup",
Utility::String::replaceAll(_profiles[index].companyName(), " ", "_"),
Utility::String::replaceAll(_profiles[index].companyName().data(), " ", "_").c_str(),
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::Directory::join(_backupsDirectory, filename).c_str(), ZIP_CREATE|ZIP_TRUNCATE, &error_code);
zip_t* zip = zip_open(Utility::Path::join(_backupsDirectory, filename).data(), ZIP_CREATE|ZIP_TRUNCATE, &error_code);
if(zip == nullptr) {
zip_error_init_with_code(&error, error_code);
_lastError = zip_error_strerror(&error);
return false;
}
zip_source_t* profile_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, _profiles[index].filename())).c_str(), 0, 0);
zip_source_t* profile_source = zip_source_file(zip, Utility::Path::toNativeSeparators(Utility::Path::join(_saveDirectory, _profiles[index].filename())).data(), 0, 0);
if(profile_source == nullptr) {
_lastError = zip_strerror(zip);
zip_source_free(profile_source);
@ -163,11 +168,11 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
_profiles[index].type() == ProfileType::Demo ? "Demo"_s : ""_s, i,
_profiles[index].account());
if(!Utility::Directory::exists(Utility::Directory::join(_saveDirectory, build_filename))) {
if(!Utility::Path::exists(Utility::Path::join(_saveDirectory, build_filename))) {
continue;
}
zip_source_t* build_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, build_filename)).c_str(), 0, 0);
zip_source_t* build_source = zip_source_file(zip, Utility::Path::toNativeSeparators(Utility::Path::join(_saveDirectory, build_filename)).data(), 0, 0);
if(build_source == nullptr) {
zip_source_free(build_source);
continue;
@ -197,28 +202,40 @@ auto ProfileManager::backups() -> Containers::ArrayView<Backup> {
void ProfileManager::refreshBackups() {
_backups = Containers::Array<Backup>{};
using Utility::Directory::Flag;
std::vector<std::string> files = Utility::Directory::list(_backupsDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
using Utility::Path::ListFlag;
auto files = Utility::Path::list(_backupsDirectory,
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
if(!files) {
_lastError = _backupsDirectory + " can't be opened.";
return;
}
auto predicate = [](Containers::StringView file)->bool{
return !file.hasSuffix(".mbprofbackup"_s);
};
files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end());
auto files_view = files->except(files->end() - std::remove_if(files->begin(), files->end(), predicate));
int error_code = 0;
zip_t* zip = nullptr;
for(const std::string& file : files) {
for(Containers::StringView file : files_view) {
Backup backup;
backup.filename = file;
zip = zip_open(Utility::Directory::join(_backupsDirectory, file).c_str(), ZIP_RDONLY, &error_code);
zip = zip_open(Utility::Path::join(_backupsDirectory, file).data(), 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);
if(comment == nullptr) {
@ -248,18 +265,12 @@ void ProfileManager::refreshBackups() {
continue;
}
backup.timestamp.year = std::stoi(ts[0]);
backup.timestamp.month = std::stoi(ts[1]);
backup.timestamp.day = std::stoi(ts[2]);
backup.timestamp.hour = std::stoi(ts[3]);
backup.timestamp.minute = std::stoi(ts[4]);
backup.timestamp.second = std::stoi(ts[5]);
Long num_entries = zip_get_num_entries(zip, ZIP_FL_UNCHANGED);
if(num_entries == 0) {
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);
arrayReserve(backup.includedFiles, num_entries);
@ -272,7 +283,7 @@ void ProfileManager::refreshBackups() {
}
auto ProfileManager::deleteBackup(std::size_t index) -> bool {
if(!Utility::Directory::rm(Utility::Directory::join(_backupsDirectory, _backups[index].filename))) {
if(!Utility::Path::remove(Utility::Path::join(_backupsDirectory, _backups[index].filename))) {
_lastError = "Couldn't delete " + _backups[index].filename;
return false;
}
@ -295,7 +306,7 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
int error_code = 0;
zip_t* zip = nullptr;
zip = zip_open(Utility::Directory::join(_backupsDirectory, backup.filename).c_str(), ZIP_RDONLY, &error_code);
zip = zip_open(Utility::Path::join(_backupsDirectory, backup.filename).data(), ZIP_RDONLY, &error_code);
if(zip == nullptr) {
zip_error_t error;
zip_error_init_with_code(&error, error_code);
@ -306,9 +317,9 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
Containers::ScopeGuard zip_guard{zip, zip_close};
for(Containers::StringView file : backup.includedFiles) {
FILE* out = std::fopen(Utility::Directory::join(_saveDirectory, file).c_str(), "wb");
FILE* out = std::fopen(Utility::Path::join(_saveDirectory, file).data(), "wb");
if(out == nullptr) {
_lastError = Utility::formatString(error_format.data(), file, std::strerror(errno));
_lastError = Utility::format(error_format.data(), file, std::strerror(errno));
return false;
}

View file

@ -18,10 +18,11 @@
#include <cstring>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/String.h>
#include <Corrade/Utility/Unicode.h>
@ -87,14 +88,15 @@ SaveTool::SaveTool(const Arguments& arguments):
initialiseGui();
if((_initEventId = SDL_RegisterEvents(2)) == UnsignedInt(-1)) {
if((_initEventId = SDL_RegisterEvents(3)) == 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;
initialiseToolDirectories();
@ -104,9 +106,9 @@ SaveTool::SaveTool(const Arguments& arguments):
return;
}
_configDir = Utility::Directory::join(_gameDataDir, "Saved/Config/WindowsNoEditor");
_saveDir = Utility::Directory::join(_gameDataDir, "Saved/SaveGames");
_screenshotsDir = Utility::Directory::join(_gameDataDir, "Saved/Screenshots/WindowsNoEditor");
_configDir = Utility::Path::join(_gameDataDir, "Saved/Config/WindowsNoEditor");
_saveDir = Utility::Path::join(_gameDataDir, "Saved/SaveGames");
_screenshotsDir = Utility::Path::join(_gameDataDir, "Saved/Screenshots/WindowsNoEditor");
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", SDL_GetError(), window());
@ -187,88 +189,32 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id,
efsw::Action action,
std::string old_filename)
{
SDL_Event event;
SDL_zero(event);
event.type = _fileEventId;
if(watch_id == _watchIDs[StagingDir] && Utility::String::endsWith(filename, ".sav")) {
_massManager->refreshStagedMasses();
event.user.code = StagedUpdate;
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, _currentProfile->account() + ".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;
event.user.code = action;
event.user.data1 = Containers::String{filename}.release();
if(action == efsw::Actions::Moved) {
event.user.data2 = Containers::String{old_filename}.release();
}
SDL_PushEvent(&event);
return;
}
void SaveTool::drawEvent() {
@ -328,6 +274,9 @@ 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) {
@ -359,7 +308,7 @@ void SaveTool::updateCheckEvent(SDL_Event& event) {
}
if(r.status_code != 200) {
_queue.addToast(Toast::Type::Error, Utility::format("The request failed with error code {}: {}", r.status_code, r.reason));
_queue.addToast(Toast::Type::Error, Utility::format("The request failed with error code {}: {}", r.status_code, r.reason.c_str()));
return;
}
@ -425,6 +374,84 @@ void SaveTool::updateCheckEvent(SDL_Event& 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};
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);
}
static bool is_moved_after_save = false;
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;
_profileManager->refreshProfiles();
}
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(!is_moved_after_save) {
is_moved_after_save = false;
_currentMass->setDirty();
}
}
}
break;
case FileMoved:
if(is_unit) {
if(old_filename.hasSuffix(".tmp"_s)) {
is_moved_after_save = true;
return;
}
if(old_filename.hasSuffix(".sav"_s)) {
_massManager->refreshHangar(index);
_massManager->refreshHangar(old_index);
}
}
break;
case StagedUpdate:
_massManager->refreshStagedMasses();
break;
default:
_queue.addToast(Toast::Type::Warning, "Unknown file action type"_s);
}
}
void SaveTool::initialiseConfiguration() {
if(_conf.hasValue("cheat_mode"_s)) {
_cheatMode = _conf.value<bool>("cheat_mode"_s);
@ -535,19 +562,19 @@ void SaveTool::initialiseManager() {
}
void SaveTool::initialiseToolDirectories() {
_backupsDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "backups");
_stagingDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "staging");
_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::Directory::exists(_backupsDir)) {
Utility::Directory::mkpath(_backupsDir);
if(!Utility::Path::exists(_backupsDir)) {
Utility::Path::make(_backupsDir);
}
if(!Utility::Directory::exists(_stagingDir)) {
Utility::Directory::mkpath(_stagingDir);
if(!Utility::Path::exists(_stagingDir)) {
Utility::Path::make(_stagingDir);
}
//if(!Utility::Directory::exists(_armouryDir)) {
@ -576,9 +603,9 @@ auto SaveTool::findGameDataDirectory() -> bool {
return false;
}
_gameDataDir = Utility::Directory::join(Utility::Directory::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder");
_gameDataDir = Utility::Path::join(Utility::Path::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder"_s);
if(!Utility::Directory::exists(_gameDataDir)) {
if(!Utility::Path::exists(_gameDataDir)) {
_lastError = _gameDataDir + " wasn't found. Make sure to play the game at least once."_s;
return false;
}
@ -587,11 +614,7 @@ auto SaveTool::findGameDataDirectory() -> bool {
}
void SaveTool::initialiseMassManager() {
_massManager.emplace(_saveDir,
_currentProfile->account(),
_currentProfile->type() == ProfileType::Demo,
_stagingDir);
_massManager.emplace(_saveDir, _currentProfile->account(), _currentProfile->isDemo(), _stagingDir);
initialiseFileWatcher();
}
@ -774,7 +797,7 @@ void SaveTool::drawTooltip(Containers::StringView text, Float wrap_pos) {
}
void SaveTool::openUri(Containers::StringView uri) {
ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri.data()).c_str(), nullptr, nullptr, SW_SHOWDEFAULT);
ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri.data()), nullptr, nullptr, SW_SHOWDEFAULT);
}
void SaveTool::checkGameState() {

View file

@ -83,6 +83,15 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
void initEvent(SDL_Event& event);
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
};
void fileUpdateEvent(SDL_Event& event);
// Initialisation methods
void initialiseConfiguration();
void initialiseGui();
@ -217,6 +226,7 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
UnsignedInt _initEventId;
UnsignedInt _updateEventId;
UnsignedInt _fileEventId;
Containers::String _lastError;

View file

@ -19,8 +19,8 @@
#include <algorithm>
#include <Corrade/Containers/Reference.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/String.h>
#include "../FontAwesome/IconsFontAwesome5.h"
@ -28,8 +28,6 @@
#include "../Maps/LastMissionId.h"
#include "../Maps/StoryProgress.h"
static const std::string empty_str;
void SaveTool::drawManager() {
ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always);
ImGui::SetNextWindowSize({Float(windowSize().x()), Float(windowSize().y()) - ImGui::GetItemRectSize().y},
@ -43,8 +41,8 @@ void SaveTool::drawManager() {
}
drawAlignedText("Current profile: %s (%s)",
_currentProfile->companyName(),
_currentProfile->type() == ProfileType::Demo ? "demo" : "full game");
_currentProfile->companyName().data(),
_currentProfile->isDemo() ? "demo" : "full game");
ImGui::SameLine();
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to profile manager")) {
_currentProfile = nullptr;
@ -464,7 +462,7 @@ void SaveTool::drawMassManager() {
static int drag_drop_index = 0;
ImGui::TableSetColumnIndex(0);
ImGui::Selectable(Utility::formatString("{:.2d}", i + 1).c_str(),
ImGui::Selectable(Utility::format("{:.2d}", i + 1).data(),
false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap);
if(_massManager->hangar(i).state() == Mass::State::Valid &&
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
@ -573,16 +571,16 @@ void SaveTool::drawMassManager() {
ImGui::TextUnformatted("Staging area");
ImGui::SameLine();
if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) {
openUri(Utility::Directory::toNativeSeparators(_stagingDir));
openUri(Utility::Path::toNativeSeparators(_stagingDir));
}
for(const auto& pair : _massManager->stagedMasses()) {
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
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());
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::GetContentRegionAvailWidth()) {
drawTooltip(staged_formatted.data());
}
if(ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) {
ImGui::SetDragDropPayload("StagedMass", &(pair.first), sizeof(std::string));

View file

@ -93,8 +93,8 @@ void SaveTool::drawProfileManager() {
ImGui::TableSetColumnIndex(1);
ImGui::Text("%s%s",
profile.type() == ProfileType::Demo ? "Demo" : "Full",
profile.version() == ProfileVersion::Legacy ? " (legacy)" : "");
profile.isDemo() ? "Demo" : "Full",
profile.isLegacy() ? " (legacy)" : "");
ImGui::TableSetColumnIndex(2);
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {
@ -364,9 +364,9 @@ auto SaveTool::drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID {
}
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().data(),
_profileManager->profiles()[profile_index].type() == ProfileType::Demo ? "demo" : "full game");
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::PopTextWrapPos();
if(ImGui::BeginTable("##DeleteProfileLayout", 2)) {

View file

@ -16,7 +16,7 @@
#include "SaveTool.h"
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/Path.h>
#include "../FontAwesome/IconsFontAwesome5.h"
#include "../FontAwesome/IconsFontAwesome5Brands.h"
@ -24,29 +24,29 @@
void SaveTool::drawMainMenu() {
if(ImGui::BeginMainMenuBar()) {
if(ImGui::BeginMenu("Save Tool##SaveToolMenu")) {
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::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::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Directory::exists(_saveDir))) {
openUri(Utility::Directory::toNativeSeparators(_saveDir));
if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Path::exists(_saveDir))) {
openUri(Utility::Path::toNativeSeparators(_saveDir));
}
if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Directory::exists(_screenshotsDir))) {
openUri(Utility::Directory::toNativeSeparators(_screenshotsDir));
if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Path::exists(_screenshotsDir))) {
openUri(Utility::Path::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::Directory::exists(_backupsDir))) {
openUri(Utility::Directory::toNativeSeparators(_backupsDir));
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_EXCHANGE_ALT " Staging area", nullptr, false, Utility::Directory::exists(_stagingDir))) {
openUri(Utility::Directory::toNativeSeparators(_stagingDir));
if(ImGui::MenuItem(ICON_FA_EXCHANGE_ALT " Staging area", nullptr, false, Utility::Path::exists(_stagingDir))) {
openUri(Utility::Path::toNativeSeparators(_stagingDir));
}
ImGui::EndMenu();

View file

@ -16,7 +16,7 @@
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/Path.h>
#include "BinaryReader.h"
#include "BinaryWriter.h"
@ -124,16 +124,16 @@ auto UESaveFile::saveToFile() -> bool {
writer.closeFile();
if(!Utility::Directory::copy(_filepath, _filepath + ".bak"_s)) {
if(!Utility::Path::copy(_filepath, _filepath + ".bak"_s)) {
return false;
}
if(!Utility::Directory::rm(_filepath)) {
if(!Utility::Path::remove(_filepath)) {
return false;
}
if(!Utility::Directory::move(_filepath + ".tmp"_s, _filepath)) {
Utility::Directory::move(_filepath + ".bak"_s, _filepath);
if(!Utility::Path::move(_filepath + ".tmp"_s, _filepath)) {
Utility::Path::move(_filepath + ".bak"_s, _filepath);
return false;
}
@ -145,7 +145,7 @@ auto UESaveFile::saveToFile() -> bool {
void UESaveFile::loadData() {
_valid = false;
if(!Utility::Directory::exists(_filepath)) {
if(!Utility::Path::exists(_filepath)) {
return;
}

2
third-party/corrade vendored

@ -1 +1 @@
Subproject commit 98922c0dd19a00eb9f1ab2617c1d522b0b9b1743
Subproject commit dc4f2eac6814b37b5257d295c2838bcde95272aa

2
third-party/magnum vendored

@ -1 +1 @@
Subproject commit 5f54cc4702ac101c6d598933b2179d659b0c83b9
Subproject commit 3fc9028b5451aa95973f104d1ef2a1c0df589e64

@ -1 +1 @@
Subproject commit f29c091b0b699cdd092c9b80b4cb5535cf481758
Subproject commit 323c23f4e8e7cda9a7848c03401a3ba0a1de0bd4