diff --git a/MassManager/MassManager.cpp b/MassManager/MassManager.cpp index 6f02635..566e1b1 100644 --- a/MassManager/MassManager.cpp +++ b/MassManager/MassManager.cpp @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -40,15 +41,15 @@ constexpr unsigned char steamid_locator[] = { 'A', 'c', 'c', 'o', 'u', 'n', 't', constexpr unsigned char active_slot_locator[] = { 'A', 'c', 't', 'i', 'v', 'e', 'F', 'r', 'a', 'm', 'e', 'S', 'l', 'o', 't', '\0', 0x0C, '\0', '\0', '\0', 'I', 'n', 't', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'y', '\0' }; MassManager::MassManager() { - _ready = findSaveDirectory() && findSteamId(); + _ready = findSaveDirectory() && findSteamId() && findScreenshotDirectory(); if(!_ready) { return; } - _executableLocation = Utility::Directory::path(Utility::Directory::executableLocation()); + std::string executable_location = Utility::Directory::path(Utility::Directory::executableLocation()); - _stagingAreaDirectory = Utility::Directory::join(_executableLocation, "staging"); + _stagingAreaDirectory = Utility::Directory::join(executable_location, "staging"); _profileSaveName = Utility::formatString("Profile{}.sav", _steamId); @@ -57,7 +58,7 @@ MassManager::MassManager() { refreshHangar(i); } - initialiseStagingArea(); + loadScreenshots(); } auto MassManager::ready() -> bool { @@ -76,6 +77,10 @@ auto MassManager::stagingAreaDirectory() -> std::string const& { return _stagingAreaDirectory; } +auto MassManager::screenshotDirectory() -> std::string const& { + return _screenshotDirectory; +} + auto MassManager::steamId() -> std::string const& { return _steamId; } @@ -521,7 +526,7 @@ void MassManager::deleteStagedMass(int index) { } } -std::string MassManager::stagedMassName(int index) { +auto MassManager::stagedMassName(int index) -> std::string { int i = 0; for(const auto& mass_info : _stagedMasses) { if(i != index) { @@ -545,6 +550,89 @@ auto MassManager::stagedMassName(const std::string& filename) -> std::string { return iter->second; } +void MassManager::loadScreenshots() { + using Utility::Directory::Flag; + std::vector file_list = Utility::Directory::list(_screenshotDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot); + + auto iter = std::remove_if(file_list.begin(), file_list.end(), [](std::string& file){ + return !Utility::String::endsWith(file, ".png"); + }); + + file_list.erase(iter, file_list.end()); + + _screenshots.reserve(file_list.size()); + + for(const std::string& file : file_list) { + addScreenshot(file); + } +} + +auto MassManager::screenshots() -> std::vector const& { + return _screenshots; +} + +void MassManager::sortScreenshots(SortType type) { + _sortType = type; + sortScreenshots(); +} + +void MassManager::sortScreenshots(SortOrder order) { + _sortOrder = order; + sortScreenshots(); +} + +void MassManager::sortScreenshots() { + auto predicate = [this](const Screenshot& item_1, const Screenshot& item_2)->bool{ + switch(_sortType) { + case SortType::Filename: + return wxString::FromUTF8(item_1._filename.c_str()).CmpNoCase(wxString::FromUTF8(item_2._filename.c_str())) < 0; + case SortType::CreationDate: + return item_1._creationDate.IsEarlierThan(item_2._creationDate); + } + + return true; + }; + + switch(_sortOrder) { + case SortOrder::Ascending: + std::stable_sort(_screenshots.begin(), _screenshots.end(), predicate); + break; + case SortOrder::Descending: + std::stable_sort(_screenshots.rbegin(), _screenshots.rend(), predicate); + break; + } +} + +auto MassManager::updateScreenshot(const std::string& filename) -> int { + addScreenshot(filename); + sortScreenshots(); + int index = 0; + for(const Screenshot& s : _screenshots) { + if(s._filename == filename) { + return index; + } + } + + return -1; +} + +void MassManager::removeScreenshot(int index) { + if(static_cast(index + 1) > _screenshots.size()) { + return; + } + + auto it = _screenshots.begin() + index; + _screenshots.erase(it); +} + +void MassManager::deleteScreenshot(int index) { + if(static_cast(index + 1) > _screenshots.size()) { + return; + } + + Utility::Directory::rm(Utility::Directory::join(_screenshotDirectory, _screenshots[index]._filename)); +} + auto MassManager::findSaveDirectory() -> bool { wchar_t h[MAX_PATH]; if(!SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, h))) { @@ -581,3 +669,46 @@ auto MassManager::findSteamId() -> bool { _lastError = "Couldn't find the profile save."; return false; } + +auto MassManager::findScreenshotDirectory() -> bool { + wchar_t h[MAX_PATH]; + if(!SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, h))) { + _lastError = "SHGetFolderPathW() failed in MassManager::findScreenshotDirectory()"; + return false; + } + + _screenshotDirectory = Utility::Directory::join(Utility::Directory::fromNativeSeparators(Utility::Unicode::narrow(h)), "MASS_Builder/Saved/Screenshots/WindowsNoEditor"); + + if(!Utility::Directory::exists(_screenshotDirectory)) { + _lastError = _screenshotDirectory + " wasn't found."; + return false; + } + + return true; +} + +void MassManager::addScreenshot(const std::string& filename) { + std::string screenshot_path = Utility::Directory::toNativeSeparators(Utility::Directory::join(_screenshotDirectory, filename)); + + wxFileName screenshot_meta(screenshot_path); + wxDateTime creation_date; + screenshot_meta.GetTimes(nullptr, nullptr, &creation_date); + + wxImage thumb{screenshot_path, wxBITMAP_TYPE_PNG}; + + wxSize size = thumb.GetSize(); + if(size.GetWidth() > size.GetHeight()) { + size.Set(160, (size.GetHeight() * 160) / size.GetWidth()); + } + else if(size.GetHeight() > size.GetWidth()) { + size.Set((size.GetWidth() * 160) / size.GetHeight(), 160); + } + else { + size.Set(160, 160); + } + + thumb.Rescale(size.GetWidth(), size.GetHeight(), wxIMAGE_QUALITY_HIGH) + .Resize(wxSize{160, 160}, wxPoint{(160 - size.GetWidth()) / 2, (160 - size.GetHeight()) / 2}); + + _screenshots.push_back(Screenshot{filename, creation_date, thumb}); +} diff --git a/MassManager/MassManager.h b/MassManager/MassManager.h index bacdf5d..41d6ed4 100644 --- a/MassManager/MassManager.h +++ b/MassManager/MassManager.h @@ -24,6 +24,9 @@ #include #include +#include +#include + using namespace Corrade; enum class GameState : uint8_t { @@ -34,6 +37,20 @@ enum class HangarState : uint8_t { Empty, Invalid, Filled }; +enum class SortType : uint8_t { + Filename, CreationDate +}; + +enum class SortOrder: uint8_t { + Ascending, Descending +}; + +struct Screenshot { + std::string _filename; + wxDateTime _creationDate; + wxImage _thumbnail; +}; + class MassManager { public: MassManager(); @@ -43,6 +60,8 @@ class MassManager { auto saveDirectory() -> std::string const&; auto stagingAreaDirectory() -> std::string const&; + auto screenshotDirectory() -> std::string const&; + auto steamId() -> std::string const&; auto profileSaveName() -> std::string const&; @@ -54,13 +73,10 @@ class MassManager { auto importMass(const std::string& source, int hangar) -> bool; auto importMass(int staged_index, int hangar) -> bool; - auto exportMass(int hangar) -> bool; auto moveMass(int source, int destination) -> bool; - auto deleteMass(int hangar) -> bool; - auto renameMass(int hangar, const std::string& new_name) -> bool; auto backupSaves(const std::string& filename) -> bool; @@ -72,26 +88,35 @@ class MassManager { auto getMassName(const std::string& filename) -> Containers::Optional; auto initialiseStagingArea() -> std::vector; - auto updateStagedMass(const std::string& filename) -> int; auto removeStagedMass(const std::string& filename) -> int; - void deleteStagedMass(int index); - auto stagedMassName(int index) -> std::string; auto stagedMassName(const std::string& filename) -> std::string; + void loadScreenshots(); + auto screenshots() -> std::vector const&; + void sortScreenshots(SortType type); + void sortScreenshots(SortOrder order); + void sortScreenshots(); + auto updateScreenshot(const std::string& filename) -> int; + void removeScreenshot(int index); + void deleteScreenshot(int index); + private: auto findSaveDirectory() -> bool; auto findSteamId() -> bool; + auto findScreenshotDirectory() -> bool; + void addScreenshot(const std::string& filename); + bool _ready = false; std::string _lastError = ""; - std::string _executableLocation = ""; std::string _stagingAreaDirectory = ""; std::string _saveDirectory = ""; + std::string _screenshotDirectory = ""; std::string _steamId = ""; std::string _profileSaveName = ""; @@ -108,6 +133,10 @@ class MassManager { Containers::StaticArray<32, Hangar> _hangars{Containers::ValueInit}; std::map _stagedMasses; + + std::vector _screenshots; + SortType _sortType = SortType::Filename; + SortOrder _sortOrder = SortOrder::Ascending; }; #endif //MASSMANAGER_H