Some early work on classes.
This commit is contained in:
parent
401d7d747e
commit
9ddea11b6e
9 changed files with 698 additions and 0 deletions
|
@ -47,8 +47,16 @@ add_executable(wxMASSManager WIN32
|
||||||
GUI/NameChangeDialog.cpp
|
GUI/NameChangeDialog.cpp
|
||||||
GUI/EvtNameChangeDialog.h
|
GUI/EvtNameChangeDialog.h
|
||||||
GUI/EvtNameChangeDialog.cpp
|
GUI/EvtNameChangeDialog.cpp
|
||||||
|
MassBuilderManager/MassBuilderManager.h
|
||||||
|
MassBuilderManager/MassBuilderManager.cpp
|
||||||
MassManager/MassManager.h
|
MassManager/MassManager.h
|
||||||
MassManager/MassManager.cpp
|
MassManager/MassManager.cpp
|
||||||
|
Profile/Profile.h
|
||||||
|
Profile/Profile.cpp
|
||||||
|
ProfileManager/ProfileManager.h
|
||||||
|
ProfileManager/ProfileManager.cpp
|
||||||
|
ScreenshotManager/ScreenshotManager.h
|
||||||
|
ScreenshotManager/ScreenshotManager.cpp
|
||||||
resource.rc)
|
resource.rc)
|
||||||
|
|
||||||
target_compile_options(wxMASSManager PRIVATE -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -fpermissive)
|
target_compile_options(wxMASSManager PRIVATE -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -fpermissive)
|
||||||
|
|
87
MassBuilderManager/MassBuilderManager.cpp
Normal file
87
MassBuilderManager/MassBuilderManager.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 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 <shlobj.h>
|
||||||
|
#include <wtsapi32.h>
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Directory.h>
|
||||||
|
#include <Corrade/Utility/Unicode.h>
|
||||||
|
|
||||||
|
#include "MassBuilderManager.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
MassBuilderManager::MassBuilderManager() {
|
||||||
|
_ready = findSaveDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MassBuilderManager::ready() -> bool {
|
||||||
|
return _ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MassBuilderManager::lastError() -> std::string const& {
|
||||||
|
return _lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MassBuilderManager::saveDirectory() -> std::string const& {
|
||||||
|
return _saveDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MassBuilderManager::checkGameState() -> GameState {
|
||||||
|
WTS_PROCESS_INFOW* process_infos = nullptr;
|
||||||
|
unsigned long process_count = 0;
|
||||||
|
_gameState = GameState::Unknown;
|
||||||
|
|
||||||
|
if(WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &process_infos, &process_count)) {
|
||||||
|
for(unsigned long i = 0; i < process_count; ++i) {
|
||||||
|
if(std::wcscmp(process_infos[i].pProcessName, L"MASS_Builder-Win64-Shipping.exe") == 0) {
|
||||||
|
_gameState = GameState::Running;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_gameState = GameState::NotRunning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(process_infos != nullptr) {
|
||||||
|
WTSFreeMemory(process_infos);
|
||||||
|
process_infos = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _gameState;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MassBuilderManager::gameState() -> GameState {
|
||||||
|
return _gameState;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MassBuilderManager::findSaveDirectory() -> bool {
|
||||||
|
wchar_t h[MAX_PATH];
|
||||||
|
if(!SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, h))) {
|
||||||
|
_lastError = "SHGetFolderPathW() failed in MassBuilderManager::findSaveDirectory()";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_saveDirectory = Utility::Directory::join(Utility::Directory::fromNativeSeparators(Utility::Unicode::narrow(h)), "MASS_Builder");
|
||||||
|
|
||||||
|
if(!Utility::Directory::exists(_saveDirectory)) {
|
||||||
|
_lastError = _saveDirectory + " wasn't found.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
52
MassBuilderManager/MassBuilderManager.h
Normal file
52
MassBuilderManager/MassBuilderManager.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef MASSBUILDERMANAGER_H
|
||||||
|
#define MASSBUILDERMANAGER_H
|
||||||
|
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 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 <cstdint>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum class GameState : std::uint8_t {
|
||||||
|
Unknown, NotRunning, Running
|
||||||
|
};
|
||||||
|
|
||||||
|
class MassBuilderManager {
|
||||||
|
public:
|
||||||
|
MassBuilderManager();
|
||||||
|
|
||||||
|
auto ready() -> bool;
|
||||||
|
auto lastError() -> std::string const&;
|
||||||
|
|
||||||
|
auto saveDirectory() -> std::string const&;
|
||||||
|
|
||||||
|
auto checkGameState() -> GameState;
|
||||||
|
auto gameState() -> GameState;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto findSaveDirectory() -> bool;
|
||||||
|
|
||||||
|
bool _ready = false;
|
||||||
|
|
||||||
|
std::string _lastError = "";
|
||||||
|
|
||||||
|
std::string _saveDirectory = "";
|
||||||
|
|
||||||
|
GameState _gameState = GameState::Unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //MASSBUILDERMANAGER_H
|
134
Profile/Profile.cpp
Normal file
134
Profile/Profile.cpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Utility/Directory.h>
|
||||||
|
#include <Corrade/Utility/String.h>
|
||||||
|
|
||||||
|
#include "Profile.h"
|
||||||
|
|
||||||
|
constexpr char company_name_locator[] = { 'C', 'o', 'm', 'p', 'a', 'n', 'y', 'N', 'a', 'm', 'e', '\0', 0x0C, '\0', '\0', '\0', 'S', 't', 'r', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'y', '\0' };
|
||||||
|
|
||||||
|
constexpr 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' };
|
||||||
|
|
||||||
|
constexpr char credits_locator[] = { 'C', 'r', 'e', 'd', 'i', 't', '\0', 0x0C, '\0', '\0', '\0', 'I', 'n', 't', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'y', '\0' };
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
Profile::Profile(const std::string& path) {
|
||||||
|
auto map = Utility::Directory::mapRead(path);
|
||||||
|
|
||||||
|
if(!map) {
|
||||||
|
_lastError = "Couldn't memory-map " + Utility::Directory::filename(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_profileDirectory = Utility::Directory::path(path);
|
||||||
|
_filename = Utility::Directory::filename(path);
|
||||||
|
|
||||||
|
if(Utility::String::beginsWith(_filename, "Demo")) {
|
||||||
|
_type = ProfileType::Demo;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_type = ProfileType::FullGame;
|
||||||
|
}
|
||||||
|
|
||||||
|
_steamId = Utility::String::ltrim(Utility::String::rtrim(_filename, ".sav"), (_type == ProfileType::Demo ? "Demo" : "") + std::string{"Profile"});
|
||||||
|
|
||||||
|
auto it = std::search(map.begin(), map.end(), &company_name_locator[0], &company_name_locator[27]);
|
||||||
|
|
||||||
|
if(it == map.end()) {
|
||||||
|
_lastError = "Couldn't find a company name in " + _filename;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_companyName = std::string{it + 41};
|
||||||
|
|
||||||
|
_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::valid() const -> bool {
|
||||||
|
return _valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::lastError() const -> std::string const& {
|
||||||
|
return _lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::filename() const -> std::string const& {
|
||||||
|
return _filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::type() const -> ProfileType {
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::steamId() const -> std::string const& {
|
||||||
|
return _steamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::companyName() const -> std::string const& {
|
||||||
|
return _companyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::activeFrameSlot() const -> std::int8_t {
|
||||||
|
return _activeFrameSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::getActiveFrameSlot() -> std::int8_t {
|
||||||
|
auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename));
|
||||||
|
|
||||||
|
auto iter = std::search(mmap.begin(), mmap.end(), &active_slot_locator[0], &active_slot_locator[31]);
|
||||||
|
|
||||||
|
if(iter == mmap.end()) {
|
||||||
|
if(std::search(mmap.begin(), mmap.end(), &credits_locator[0], &credits_locator[22]) != mmap.end()) {
|
||||||
|
_activeFrameSlot = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file.";
|
||||||
|
_activeFrameSlot = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_activeFrameSlot = *(iter + 41);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _activeFrameSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::credits() const -> std::int32_t {
|
||||||
|
return _credits;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Profile::getCredits() -> std::int32_t {
|
||||||
|
auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename));
|
||||||
|
|
||||||
|
auto iter = std::search(mmap.begin(), mmap.end(), &credits_locator[0], &credits_locator[22]);
|
||||||
|
|
||||||
|
if(iter != mmap.end()) {
|
||||||
|
_credits = ((*(iter + 0x20)) << 0) +
|
||||||
|
((*(iter + 0x21)) << 8) +
|
||||||
|
((*(iter + 0x22)) << 16) +
|
||||||
|
((*(iter + 0x23)) << 24);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_credits = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _credits;
|
||||||
|
}
|
53
Profile/Profile.h
Normal file
53
Profile/Profile.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef PROFILE_H
|
||||||
|
#define PROFILE_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum class ProfileType : std::uint8_t {
|
||||||
|
Demo,
|
||||||
|
FullGame
|
||||||
|
};
|
||||||
|
|
||||||
|
class Profile {
|
||||||
|
public:
|
||||||
|
explicit Profile(const std::string& path);
|
||||||
|
|
||||||
|
auto valid() const -> bool;
|
||||||
|
|
||||||
|
auto lastError() const -> std::string const&;
|
||||||
|
|
||||||
|
auto filename() const -> std::string const&;
|
||||||
|
|
||||||
|
auto type() const -> ProfileType;
|
||||||
|
|
||||||
|
auto steamId() const -> std::string const&;
|
||||||
|
|
||||||
|
auto companyName() const -> std::string const&;
|
||||||
|
|
||||||
|
auto activeFrameSlot() const -> std::int8_t;
|
||||||
|
auto getActiveFrameSlot() -> std::int8_t;
|
||||||
|
|
||||||
|
auto credits() const -> std::int32_t;
|
||||||
|
auto getCredits() -> std::int32_t;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _profileDirectory;
|
||||||
|
std::string _filename;
|
||||||
|
|
||||||
|
ProfileType _type;
|
||||||
|
|
||||||
|
std::string _steamId;
|
||||||
|
|
||||||
|
bool _valid = false;
|
||||||
|
std::string _lastError = "";
|
||||||
|
|
||||||
|
std::string _companyName;
|
||||||
|
|
||||||
|
std::int8_t _activeFrameSlot = 0;
|
||||||
|
|
||||||
|
std::int32_t _credits;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //PROFILE_H
|
100
ProfileManager/ProfileManager.cpp
Normal file
100
ProfileManager/ProfileManager.cpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 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 <regex>
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Directory.h>
|
||||||
|
#include <Corrade/Utility/String.h>
|
||||||
|
|
||||||
|
#include "ProfileManager.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
ProfileManager::ProfileManager(const std::string& base_path) {
|
||||||
|
_profileDirectory = Utility::Directory::join(base_path, "Saved/SaveGames");
|
||||||
|
|
||||||
|
if(Utility::Directory::exists(_profileDirectory) == false) {
|
||||||
|
_lastError = "Couldn't find the profile directory. Make sure you played enough of the game.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Utility::Directory::Flag;
|
||||||
|
std::vector<std::string> files = Utility::Directory::list(_profileDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end());
|
||||||
|
|
||||||
|
for(const std::string& file : files) {
|
||||||
|
Profile profile{Utility::Directory::join(_profileDirectory, file)};
|
||||||
|
|
||||||
|
if(profile.valid() == false) {
|
||||||
|
Utility::Warning{} << "Profile" << file.c_str() << "is invalid:" << profile.lastError().c_str();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_profiles.push_back(std::move(profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_profiles.size() == 0) {
|
||||||
|
_lastError = "No profiles were found.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ProfileManager::ready() -> bool {
|
||||||
|
return _ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ProfileManager::lastError() -> std::string const& {
|
||||||
|
return _lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ProfileManager::profileDirectory() -> std::string const& {
|
||||||
|
return _profileDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ProfileManager::profiles() -> std::vector<Profile> const& {
|
||||||
|
return _profiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ProfileManager::currentProfile() -> Profile* {
|
||||||
|
return _currentProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ProfileManager::setProfile(std::size_t index) -> bool {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_currentProfile = &(_profiles.at(index));
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
catch(const std::out_of_range&) {
|
||||||
|
_lastError = "Invalid profile index";
|
||||||
|
_currentProfile = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
52
ProfileManager/ProfileManager.h
Normal file
52
ProfileManager/ProfileManager.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef PROFILEMANAGER_H
|
||||||
|
#define PROFILEMANAGER_H
|
||||||
|
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../Profile/Profile.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
class ProfileManager {
|
||||||
|
public:
|
||||||
|
ProfileManager(const std::string& base_path);
|
||||||
|
|
||||||
|
auto ready() -> bool;
|
||||||
|
auto lastError() -> std::string const&;
|
||||||
|
|
||||||
|
auto profileDirectory() -> std::string const&;
|
||||||
|
|
||||||
|
auto profiles() -> std::vector<Profile> const&;
|
||||||
|
|
||||||
|
auto currentProfile() -> Profile*;
|
||||||
|
auto setProfile(std::size_t index) -> bool;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _ready = false;
|
||||||
|
std::string _lastError = "";
|
||||||
|
|
||||||
|
std::string _profileDirectory;
|
||||||
|
|
||||||
|
std::vector<Profile> _profiles;
|
||||||
|
|
||||||
|
Profile* _currentProfile = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //PROFILEMANAGER_H
|
145
ScreenshotManager/ScreenshotManager.cpp
Normal file
145
ScreenshotManager/ScreenshotManager.cpp
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Directory.h>
|
||||||
|
#include <Corrade/Utility/String.h>
|
||||||
|
|
||||||
|
#include <wx/filename.h>
|
||||||
|
|
||||||
|
#include "ScreenshotManager.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
ScreenshotManager::ScreenshotManager(const std::string& base_path) {
|
||||||
|
_screenshotDirectory = Utility::Directory::join(base_path, "Saved/Screenshots/WindowsNoEditor");
|
||||||
|
|
||||||
|
if(!Utility::Directory::exists(_screenshotDirectory)) {
|
||||||
|
Utility::Directory::mkpath(_screenshotDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
using Utility::Directory::Flag;
|
||||||
|
std::vector<std::string> 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 ScreenshotManager::screenshotDirectory() -> std::string const& {
|
||||||
|
return _screenshotDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ScreenshotManager::screenshots() -> std::vector<Screenshot> const& {
|
||||||
|
return _screenshots;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenshotManager::sortScreenshots(SortType type) {
|
||||||
|
_sortType = type;
|
||||||
|
sortScreenshots();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenshotManager::sortScreenshots(SortOrder order) {
|
||||||
|
_sortOrder = order;
|
||||||
|
sortScreenshots();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenshotManager::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 ScreenshotManager::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 ScreenshotManager::removeScreenshot(int index) {
|
||||||
|
if(static_cast<size_t>(index + 1) > _screenshots.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = _screenshots.begin() + index;
|
||||||
|
_screenshots.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenshotManager::deleteScreenshot(int index) {
|
||||||
|
if(static_cast<size_t>(index + 1) > _screenshots.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utility::Directory::rm(Utility::Directory::join(_screenshotDirectory, _screenshots[index]._filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenshotManager::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});
|
||||||
|
}
|
67
ScreenshotManager/ScreenshotManager.h
Normal file
67
ScreenshotManager/ScreenshotManager.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef SCREENSHOTMANAGER_H
|
||||||
|
#define SCREENSHOTMANAGER_H
|
||||||
|
|
||||||
|
// wxMASSManager
|
||||||
|
// Copyright (C) 2020 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <wx/datetime.h>
|
||||||
|
#include <wx/image.h>
|
||||||
|
|
||||||
|
enum class SortType : uint8_t {
|
||||||
|
Filename, CreationDate
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SortOrder: uint8_t {
|
||||||
|
Ascending, Descending
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Screenshot {
|
||||||
|
std::string _filename;
|
||||||
|
wxDateTime _creationDate;
|
||||||
|
wxImage _thumbnail;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScreenshotManager {
|
||||||
|
public:
|
||||||
|
ScreenshotManager(const std::string& base_path);
|
||||||
|
|
||||||
|
auto screenshotDirectory() -> std::string const&;
|
||||||
|
|
||||||
|
auto screenshots() -> std::vector<Screenshot> 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:
|
||||||
|
void addScreenshot(const std::string& filename);
|
||||||
|
|
||||||
|
std::string _screenshotDirectory = "";
|
||||||
|
|
||||||
|
std::vector<Screenshot> _screenshots;
|
||||||
|
|
||||||
|
SortType _sortType = SortType::Filename;
|
||||||
|
SortOrder _sortOrder = SortOrder::Ascending;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //SCREENSHOTMANAGER_H
|
Loading…
Reference in a new issue