Compare commits

..

No commits in common. "master" and "v2.1.1" have entirely different histories.

35 changed files with 1603 additions and 2922 deletions

View File

@ -1,5 +1,5 @@
# wxMASSManager
# Copyright (C) 2020-2021 Guillaume Jacquemin
# 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
@ -18,23 +18,84 @@ cmake_minimum_required(VERSION 3.5)
project(wxMASSManager LANGUAGES CXX)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/modules/" ${CMAKE_MODULE_PATH})
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_EXTENSIONS ON)
option(USE_CORRADE_SUBMODULE "Use Corrade from the Git submodule. If set to OFF, make sure you have Corrade 2020.06 or later installed to a path CMake can search in." ON)
if(USE_CORRADE_SUBMODULE)
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 OFF CACHE BOOL "" FORCE)
set(WITH_PLUGINMANAGER OFF CACHE BOOL "" FORCE)
set(WITH_TESTSUITE OFF CACHE BOOL "" FORCE)
add_subdirectory(corrade EXCLUDE_FROM_ALL)
endif()
add_subdirectory(src)
find_package(Corrade REQUIRED Containers Utility)
include_directories(SYSTEM "C:/msys64/mingw64/lib/wx/include/msw-unicode-static-3.0")
include_directories(SYSTEM "C:/msys64/mingw64/include/wx-3.0")
set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON)
add_executable(wxMASSManager WIN32
main.cpp
GUI/MainFrame.fbp
GUI/MainFrame.h
GUI/MainFrame.cpp
GUI/EvtMainFrame.h
GUI/EvtMainFrame.cpp
GUI/NameChangeDialog.fbp
GUI/NameChangeDialog.h
GUI/NameChangeDialog.cpp
GUI/EvtNameChangeDialog.h
GUI/EvtNameChangeDialog.cpp
Maps/LastMissionId.h
Maps/StoryProgress.h
Mass/Mass.h
Mass/Mass.cpp
MassBuilderManager/MassBuilderManager.h
MassBuilderManager/MassBuilderManager.cpp
MassManager/MassManager.h
MassManager/MassManager.cpp
Profile/Profile.h
Profile/Profile.cpp
ProfileManager/ProfileManager.h
ProfileManager/ProfileManager.cpp
ScreenshotManager/ScreenshotManager.h
ScreenshotManager/ScreenshotManager.cpp
resource.rc)
target_compile_options(wxMASSManager PRIVATE -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -fpermissive)
target_link_options(wxMASSManager PRIVATE -static -static-libgcc -static-libstdc++ -pipe -Wl,--subsystem,windows -mwindows)
target_link_libraries(wxMASSManager PRIVATE
Corrade::Containers
Corrade::Utility
wx_mswu_adv-3.0
wx_mswu_core-3.0
wx_baseu-3.0
wxregexu-3.0
wxexpat-3.0
wxtiff-3.0
wxjpeg-3.0
wxpng-3.0
wxzlib-3.0
rpcrt4
oleaut32
ole32
uuid
lzma
jbig
winspool
winmm
shell32
comctl32
comdlg32
advapi32
wsock32
gdi32
oleacc
wtsapi32)

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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
@ -22,7 +22,6 @@
#include <wx/busyinfo.h>
#include <wx/filedlg.h>
#include <wx/menu.h>
#include <wx/msgdlg.h>
#include <wx/numdlg.h>
#include <wx/regex.h>
@ -109,7 +108,7 @@ EvtMainFrame::EvtMainFrame(wxWindow* parent):
_gameCheckTimer.Start(2000);
initStoryProgressMenu();
_screenshotsList->SetImageList(&_screenshotThumbs, wxIMAGE_LIST_NORMAL);
}
EvtMainFrame::~EvtMainFrame() {
@ -167,7 +166,7 @@ void EvtMainFrame::backupSelectedProfileEvent(wxCommandEvent&) {
}
}
void EvtMainFrame::companyRenameEvent(wxCommandEvent&) {
void EvtMainFrame::companyRenameEvent(wxMouseEvent&) {
const static std::string error_prefix = "Rename failed:\n\n";
EvtNameChangeDialog dialog{this};
@ -210,114 +209,6 @@ void EvtMainFrame::companyRenameEvent(wxCommandEvent&) {
}
}
void EvtMainFrame::creditsEditEvent(wxCommandEvent&) {
const static std::string error_prefix = "Credits change failed:\n\n";
if(_unsafeMode == true || _mbManager.gameState() == GameState::NotRunning) {
long number = wxGetNumberFromUser("Please enter a number of credits between 0 and 2 000 000 000 included:", "Credits:", "Input credits",
_profileManager.currentProfile()->credits(), 0, 2000000000, this);
if(number == -1 || number == _profileManager.currentProfile()->credits()) {
return;
}
if(!_profileManager.currentProfile()->setCredits(number)) {
errorMessage(error_prefix + _profileManager.currentProfile()->lastError());
}
updateProfileStats();
}
else if(_mbManager.gameState() == GameState::Unknown) {
errorMessage(error_prefix + "For security reasons, changing credits is disabled if the game's status is unknown.");
}
else if(_mbManager.gameState() == GameState::Running) {
errorMessage(error_prefix + "For security reasons, changing credits is disabled if the game is running.");
}
}
void EvtMainFrame::storyProgressSelectionEvent(wxCommandEvent& event) {
const static std::string error_prefix = "StoryProgress change failed:\n\n";
std::int32_t story_progress = event.GetId() ^ (-10000);
if(_unsafeMode == false) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, changing the story progression is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_profileManager.currentProfile()->setStoryProgress(story_progress)) {
errorMessage(error_prefix + _profileManager.currentProfile()->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Changing the story progression is disabled while the game is running.");
break;
}
}
else if(!_profileManager.currentProfile()->setStoryProgress(story_progress)) {
errorMessage(error_prefix + _profileManager.currentProfile()->lastError());
}
updateProfileStats();
}
void EvtMainFrame::openStoryProgressMenuEvent(wxCommandEvent&) {
PopupMenu(_storyProgressSelectionMenu.get());
}
void EvtMainFrame::inventoryChangeEvent(wxPropertyGridEvent& event) {
const static std::string error_prefix = "Inventory change failed:\n\n";
std::int32_t value = event.GetPropertyValue().GetInteger();
Profile* profile = _profileManager.currentProfile();
if(value > 1000000 || value < 0) {
event.SetValidationFailureMessage(error_prefix + "The value must not be higher than 1 million or lower than 0");
event.Veto();
return;
}
if(_unsafeMode == true || _mbManager.gameState() == GameState::NotRunning) {
wxPGProperty* prop = event.GetProperty();
bool success = false;
if(prop == _verseSteel) { success = profile->setVerseSteel(value); }
else if(prop == _undinium) { success = profile->setUndinium(value); }
else if(prop == _necriumAlloy) { success = profile->setNecriumAlloy(value); }
else if(prop == _lunarite) { success = profile->setLunarite(value); }
else if(prop == _asterite) { success = profile->setAsterite(value); }
else if(prop == _ednil) { success = profile->setEdnil(value); }
else if(prop == _nuflalt) { success = profile->setNuflalt(value); }
else if(prop == _aurelene) { success = profile->setAurelene(value); }
else if(prop == _soldus) { success = profile->setSoldus(value); }
else if(prop == _synthesizedN) { success = profile->setSynthesizedN(value); }
else if(prop == _alcarbonite) { success = profile->setAlcarbonite(value); }
else if(prop == _keriphene) { success = profile->setKeriphene(value); }
else if(prop == _nitinolCM) { success = profile->setNitinolCM(value); }
else if(prop == _quarkium) { success = profile->setQuarkium(value); }
else if(prop == _alterene) { success = profile->setAlterene(value); }
else if(prop == _mixedComposition) { success = profile->setMixedComposition(value); }
else if(prop == _voidResidue) { success = profile->setVoidResidue(value); }
else if(prop == _muscularConstruction) { success = profile->setMuscularConstruction(value); }
else if(prop == _mineralExoskeletology) { success = profile->setMineralExoskeletology(value); }
else if(prop == _carbonizedSkin) { success = profile->setCarbonizedSkin(value); }
if(!success) {
event.SetValidationFailureMessage(error_prefix + profile->lastError());
event.Veto();
}
}
else if(_mbManager.gameState() == GameState::Unknown) {
event.SetValidationFailureMessage(error_prefix + "For security reasons, changing the inventory is disabled if the game's status is unknown.");
event.Veto();
}
else if(_mbManager.gameState() == GameState::Running) {
event.SetValidationFailureMessage(error_prefix + "For security reasons, changing the inventory is disabled if the game is running.");
event.Veto();
}
}
void EvtMainFrame::importMassEvent(wxCommandEvent&) {
const static std::string error_prefix = "Importing failed:\n\n";
@ -506,8 +397,63 @@ void EvtMainFrame::listColumnDragEvent(wxListEvent& event) {
event.Veto();
}
void EvtMainFrame::screenshotListSelectionEvent(wxListEvent&) {
updateCommandsState();
}
void EvtMainFrame::screenshotFilenameSortingEvent(wxCommandEvent&) {
_screenshotManager->sortScreenshots(SortType::Filename);
updateScreenshotList();
}
void EvtMainFrame::screenshotCreationDateSortingEvent(wxCommandEvent&) {
_screenshotManager->sortScreenshots(SortType::CreationDate);
updateScreenshotList();
}
void EvtMainFrame::screenshotAscendingSortingEvent(wxCommandEvent&) {
_screenshotManager->sortScreenshots(SortOrder::Ascending);
updateScreenshotList();
}
void EvtMainFrame::screenshotDescendingSortingEvent(wxCommandEvent&) {
_screenshotManager->sortScreenshots(SortOrder::Descending);
updateScreenshotList();
}
void EvtMainFrame::viewScreenshotEvent(wxCommandEvent&) {
viewScreenshot();
}
void EvtMainFrame::viewScreenshotEvent(wxListEvent&) {
viewScreenshot();
}
void EvtMainFrame::deleteScreenshotEvent(wxCommandEvent&) {
if(wxMessageBox("Are you sure you want to delete the selected screenshot ? This operation cannot be undone.",
"Are you sure ?", wxYES_NO|wxCENTRE|wxICON_QUESTION, this) == wxNO) {
return;
}
long selection = _screenshotsList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if(selection != -1) {
_screenshotManager->deleteScreenshot(selection);
}
}
void EvtMainFrame::openScreenshotDirEvent(wxCommandEvent&) {
wxExecute("explorer.exe " + Utility::Directory::toNativeSeparators(Utility::Directory::join(_profileManager.profileDirectory(), "../Screenshots/WindowsNoEditor")));
wxExecute("explorer.exe " + Utility::Directory::toNativeSeparators(_screenshotManager->screenshotDirectory()));
}
void EvtMainFrame::tabChangeEvent(wxNotebookEvent& event) {
if(event.GetSelection() == 2 && !_screenshotManager) {
wxBusyInfo busy{"Loading screenshots...", this};
_screenshotManager.emplace(_mbManager.saveDirectory());
_watcher.AddTree(wxFileName(Utility::Directory::toNativeSeparators(_screenshotManager->screenshotDirectory()), wxPATH_WIN),
wxFSW_EVENT_CREATE|wxFSW_EVENT_DELETE, "*.png"); // Not monitoring MODIFY or RENAME, because they're a massive pain to handle. Ugh.
updateScreenshotList();
}
}
void EvtMainFrame::fileUpdateEvent(wxFileSystemWatcherEvent& event) {
@ -529,6 +475,9 @@ void EvtMainFrame::fileUpdateEvent(wxFileSystemWatcherEvent& event) {
else if(_massManager && event_path == Utility::Directory::toNativeSeparators(_massManager->stagingAreaDirectory())) {
stagingFileEventHandler(event_type, event_file, event);
}
else if(_screenshotManager && event_path == Utility::Directory::toNativeSeparators(_screenshotManager->screenshotDirectory())) {
screenshotFileEventHandler(event_type, event_file);
}
_lastWatcherEventType = event_type;
@ -650,10 +599,29 @@ void EvtMainFrame::stagingFileEventHandler(int event_type, const wxString& event
}
}
void EvtMainFrame::screenshotFileEventHandler(int event_type, const wxString& event_file) {
int index = -1;
switch(event_type) {
case wxFSW_EVENT_CREATE:
_screenshotManager->updateScreenshot(event_file.ToUTF8().data());
updateScreenshotList();
break;
case wxFSW_EVENT_DELETE:
index = _screenshotsList->FindItem(-1, event_file, true);
if(index != -1) {
_screenshotManager->removeScreenshot(index);
_screenshotsList->DeleteItem(index);
}
break;
}
}
void EvtMainFrame::updateProfileStats() {
Profile* current_profile = _profileManager.currentProfile();
_companyName->SetLabel(current_profile->getCompanyName());
_credits->SetLabel(wxString::Format("%i", current_profile->getCredits()));
if(story_progress_map.find(current_profile->getStoryProgress()) != story_progress_map.end()) {
@ -669,81 +637,6 @@ void EvtMainFrame::updateProfileStats() {
else {
_lastMissionId->SetLabel(wxString::Format("0x%X", current_profile->lastMissionId()));
}
_verseSteel->SetValueFromInt(current_profile->getVerseSteel());
_undinium->SetValueFromInt(current_profile->getUndinium());
_necriumAlloy->SetValueFromInt(current_profile->getNecriumAlloy());
_lunarite->SetValueFromInt(current_profile->getLunarite());
_asterite->SetValueFromInt(current_profile->getAsterite());
_ednil->SetValueFromInt(current_profile->getEdnil());
_nuflalt->SetValueFromInt(current_profile->getNuflalt());
_aurelene->SetValueFromInt(current_profile->getAurelene());
_soldus->SetValueFromInt(current_profile->getSoldus());
_synthesizedN->SetValueFromInt(current_profile->getSynthesizedN());
_alcarbonite->SetValueFromInt(current_profile->getAlcarbonite());
_keriphene->SetValueFromInt(current_profile->getKeriphene());
_nitinolCM->SetValueFromInt(current_profile->getNitinolCM());
_quarkium->SetValueFromInt(current_profile->getQuarkium());
_alterene->SetValueFromInt(current_profile->getAlterene());
_mixedComposition->SetValueFromInt(current_profile->getMixedComposition());
_voidResidue->SetValueFromInt(current_profile->getVoidResidue());
_muscularConstruction->SetValueFromInt(current_profile->getMuscularConstruction());
_mineralExoskeletology->SetValueFromInt(current_profile->getMineralExoskeletology());
_carbonizedSkin->SetValueFromInt(current_profile->getCarbonizedSkin());
updateCommandsState();
}
void EvtMainFrame::initStoryProgressMenu() {
_storyProgressSelectionMenu.emplace();
if(!_storyProgressSelectionMenu) {
errorMessage("Error initialising the story progress selection menu.");
this->Destroy();
return;
}
wxMenu* submenu = nullptr;
for(const auto& pair : story_progress_map) {
if(std::strncmp(pair.second + 10, "start", 5) == 0) {
submenu = new wxMenu();
if(!submenu) {
errorMessage("Error initialising the story progress selection menu.");
this->Destroy();
return;
}
_storyProgressSelectionMenu->Append(wxID_ANY, wxString{pair.second, 9}, submenu);
wxMenuItem* item = submenu->Append(pair.first ^ (-10000), "Chapter start");
if(!item) {
errorMessage("Error initialising the story progress selection menu.");
this->Destroy();
return;
}
}
else {
if(!submenu) {
errorMessage("Error initialising the story progress selection menu.");
this->Destroy();
return;
}
wxMenuItem* item = submenu->Append(pair.first ^ (-10000), wxString{pair.second + 12});
if(!item) {
errorMessage("Error initialising the story progress selection menu.");
this->Destroy();
return;
}
}
}
_storyProgressSelectionMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(EvtMainFrame::storyProgressSelectionEvent), nullptr, this);
}
void EvtMainFrame::initialiseListView() {
@ -812,24 +705,16 @@ void EvtMainFrame::updateCommandsState() {
GameState game_state = _mbManager.gameState();
MassState mass_state = _massManager->massState(selection);
_companyRenameButton->Enable(_unsafeMode == true || game_state == GameState::NotRunning);
_creditsEditButton->Enable(_unsafeMode == true || game_state == GameState::NotRunning);
_storyProgressChangeButton->Enable(_unsafeMode == true || game_state == GameState::NotRunning);
wxPropertyGridConstIterator it = _researchInventoryPropGrid->GetIterator(wxPG_ITERATE_NORMAL);
while(!it.AtEnd()) {
if(it.GetProperty()->IsCategory() == false) {
it.GetProperty()->Enable(it.GetProperty()->GetValue().GetInteger() != -1 && (_unsafeMode == true || game_state == GameState::NotRunning));
}
it.Next();
}
_importButton->Enable(selection != -1 && staged_selection != -1 && (_unsafeMode == true || game_state == GameState::NotRunning));
_exportButton->Enable(selection != -1);
_moveButton->Enable(selection != -1 && (_unsafeMode == true || game_state == GameState::NotRunning) && mass_state == MassState::Valid);
_deleteButton->Enable(selection != -1 && (_unsafeMode == true || game_state == GameState::NotRunning) && mass_state != MassState::Empty);
_renameButton->Enable(selection != -1 && (_unsafeMode == true || game_state == GameState::NotRunning) && mass_state == MassState::Valid);
_deleteStagedButton->Enable(staged_selection != -1);
long screenshot_selection = _screenshotsList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
_viewScreenshotButton->Enable(screenshot_selection != -1);
_deleteScreenshotButton->Enable(screenshot_selection != -1);
}
void EvtMainFrame::refreshHangar(int slot) {
@ -852,6 +737,53 @@ void EvtMainFrame::refreshHangar(int slot) {
}
}
void EvtMainFrame::updateScreenshotList() {
_screenshotsList->DeleteAllItems();
_screenshotThumbs.RemoveAll();
int index = 0;
for(const Screenshot& s : _screenshotManager->screenshots()) {
_screenshotsList->InsertItem(index,
wxString::Format("%s\n%s", wxString::FromUTF8(s._filename.c_str()), s._creationDate.Format("%d/%m/%Y %H:%M:%S")),
_screenshotThumbs.Add(s._thumbnail));
++index;
}
}
void EvtMainFrame::viewScreenshot() {
long selection = _screenshotsList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if(selection == -1) {
return;
}
wxBitmap image(Utility::Directory::toNativeSeparators(Utility::Directory::join(_screenshotManager->screenshotDirectory(),
_screenshotManager->screenshots().at(selection)._filename)), wxBITMAP_TYPE_PNG);
wxDialog view_dialog;
view_dialog.Create(this, wxID_ANY, "Screenshot viewer", wxDefaultPosition, wxSize{1024, 576}, wxCAPTION|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU);
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
wxScrolledWindow* scroller = new wxScrolledWindow(&view_dialog, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL);
scroller->SetScrollRate(5, 5);
wxBoxSizer* scroller_sizer = new wxBoxSizer(wxVERTICAL);
wxStaticBitmap* screenshot = new wxStaticBitmap(scroller, wxID_ANY, image);
scroller_sizer->Add(screenshot, 1, wxEXPAND, 5);
scroller->SetSizer(scroller_sizer);
scroller->Layout();
scroller_sizer->FitInside(scroller);
sizer->Add(scroller, 1, wxEXPAND, 5);
view_dialog.SetSizer(sizer);
view_dialog.Layout();
sizer->FitInside(&view_dialog);
view_dialog.Centre();
view_dialog.ShowModal();
}
void EvtMainFrame::infoMessage(const wxString& message) {
wxMessageBox(message, "Information", wxOK|wxCENTRE|wxICON_INFORMATION, this);
}

View File

@ -2,7 +2,7 @@
#define __EvtMainFrame__
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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
@ -28,6 +28,7 @@
#include "../MassBuilderManager/MassBuilderManager.h"
#include "../Profile/Profile.h"
#include "../ProfileManager/ProfileManager.h"
#include "../ScreenshotManager/ScreenshotManager.h"
#include "MainFrame.h"
@ -42,41 +43,46 @@ class EvtMainFrame: public MainFrame {
protected:
// Profile-related events
void profileSelectionEvent(wxCommandEvent&) override;
void backupSelectedProfileEvent(wxCommandEvent&) override;
void companyRenameEvent(wxCommandEvent&) override;
void creditsEditEvent(wxCommandEvent&) override;
void storyProgressSelectionEvent(wxCommandEvent& event);
void openStoryProgressMenuEvent(wxCommandEvent&) override;
void inventoryChangeEvent(wxPropertyGridEvent& event) override;
void profileSelectionEvent(wxCommandEvent&);
void backupSelectedProfileEvent(wxCommandEvent&);
void companyRenameEvent(wxMouseEvent&);
// M.A.S.S.-related events
void importMassEvent(wxCommandEvent&) override;
void exportMassEvent(wxCommandEvent&) override;
void moveMassEvent(wxCommandEvent&) override;
void deleteMassEvent(wxCommandEvent&) override;
void renameMassEvent(wxCommandEvent&) override;
void openSaveDirEvent(wxCommandEvent&) override;
void stagingSelectionEvent(wxCommandEvent&) override;
void deleteStagedEvent(wxCommandEvent&) override;
void openStagingDirEvent(wxCommandEvent&) override;
void importMassEvent(wxCommandEvent&);
void exportMassEvent(wxCommandEvent&);
void moveMassEvent(wxCommandEvent&);
void deleteMassEvent(wxCommandEvent&);
void renameMassEvent(wxCommandEvent&);
void openSaveDirEvent(wxCommandEvent&);
void stagingSelectionEvent(wxCommandEvent&);
void deleteStagedEvent(wxCommandEvent&);
void openStagingDirEvent(wxCommandEvent&);
void installedSelectionEvent(wxListEvent&);
void listColumnDragEvent(wxListEvent&);
// Screenshot-related events
void openScreenshotDirEvent(wxCommandEvent&) override;
void screenshotListSelectionEvent(wxListEvent&);
void screenshotFilenameSortingEvent(wxCommandEvent&);
void screenshotCreationDateSortingEvent(wxCommandEvent&);
void screenshotAscendingSortingEvent(wxCommandEvent&);
void screenshotDescendingSortingEvent(wxCommandEvent&);
void viewScreenshotEvent(wxCommandEvent&);
void viewScreenshotEvent(wxListEvent&);
void deleteScreenshotEvent(wxCommandEvent&);
void openScreenshotDirEvent(wxCommandEvent&);
// General events
void tabChangeEvent(wxNotebookEvent& event);
void fileUpdateEvent(wxFileSystemWatcherEvent& event);
void gameCheckTimerEvent(wxTimerEvent&) override;
void unsafeCheckboxEvent(wxCommandEvent& event) override;
void gameCheckTimerEvent(wxTimerEvent&);
void unsafeCheckboxEvent(wxCommandEvent& event);
private:
void saveFileEventHandler(int event_type, const wxString& event_file, const wxFileSystemWatcherEvent& event);
void stagingFileEventHandler(int event_type, const wxString& event_file, const wxFileSystemWatcherEvent& event);
void screenshotFileEventHandler(int event_type, const wxString& event_file);
void updateProfileStats();
void initStoryProgressMenu();
void initialiseListView();
void isGameRunning();
@ -85,6 +91,9 @@ class EvtMainFrame: public MainFrame {
void updateCommandsState();
void refreshHangar(int slot);
void updateScreenshotList();
void viewScreenshot();
void infoMessage(const wxString& message);
void warningMessage(const wxString& message);
void errorMessage(const wxString& message);
@ -94,11 +103,12 @@ class EvtMainFrame: public MainFrame {
MassBuilderManager _mbManager;
ProfileManager _profileManager;
Containers::Pointer<MassManager> _massManager;
Containers::Pointer<wxMenu> _storyProgressSelectionMenu;
Containers::Pointer<ScreenshotManager> _screenshotManager;
wxFileSystemWatcher _watcher;
int _lastWatcherEventType = 0;
wxImageList _screenshotThumbs{160, 160, true, 0};
};
#endif // __EvtMainFrame__

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -2,7 +2,7 @@
#define __EvtNameChangeDialog__
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -11,7 +11,7 @@
MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxSize( -1,600 ), wxSize( -1,600 ) );
this->SetSizeHints( wxSize( -1,600 ), wxDefaultSize );
wxBoxSizer* bSizerMain;
bSizerMain = new wxBoxSizer( wxVERTICAL );
@ -37,9 +37,6 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
_backupSelectedButton = new wxButton( _mainPanel, wxID_ANY, wxT("Backup selected profile"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerProfile->Add( _backupSelectedButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
_openScreenshotDirButton = new wxButton( _mainPanel, wxID_ANY, wxT("Open screenshots folder"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerProfile->Add( _openScreenshotDirButton, 0, wxALL, 5 );
bSizerProfile->Add( 0, 0, 1, wxEXPAND, 5 );
@ -67,10 +64,14 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
_companyNameLabel = new wxStaticText( sbSizerGeneralInfo->GetStaticBox(), wxID_ANY, wxT("Company name:"), wxDefaultPosition, wxDefaultSize, 0 );
_companyNameLabel->Wrap( -1 );
_companyNameLabel->SetToolTip( wxT("EXPERIMENTAL: Double-click the company name to rename it.") );
fgSizerGeneralStats->Add( _companyNameLabel, 0, wxALL, 5 );
_companyName = new wxStaticText( sbSizerGeneralInfo->GetStaticBox(), wxID_ANY, wxT("<blank>"), wxDefaultPosition, wxDefaultSize, 0 );
_companyName->Wrap( -1 );
_companyName->SetToolTip( wxT("EXPERIMENTAL: Double-click the company name to rename it.") );
fgSizerGeneralStats->Add( _companyName, 0, wxALL|wxEXPAND, 5 );
_creditsLabel = new wxStaticText( sbSizerGeneralInfo->GetStaticBox(), wxID_ANY, wxT("Credits:"), wxDefaultPosition, wxDefaultSize, 0 );
@ -108,69 +109,14 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
sbSizerGeneralInfo->Add( fgSizerGeneralStats, 1, wxEXPAND, 5 );
wxBoxSizer* bSizerProfileCommands;
bSizerProfileCommands = new wxBoxSizer( wxHORIZONTAL );
_companyRenameButton = new wxButton( sbSizerGeneralInfo->GetStaticBox(), wxID_ANY, wxT("Rename company"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerProfileCommands->Add( _companyRenameButton, 0, wxALL, 5 );
_creditsEditButton = new wxButton( sbSizerGeneralInfo->GetStaticBox(), wxID_ANY, wxT("Edit credits"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerProfileCommands->Add( _creditsEditButton, 0, wxALL, 5 );
_storyProgressChangeButton = new wxButton( sbSizerGeneralInfo->GetStaticBox(), wxID_ANY, wxT("Change story progress"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerProfileCommands->Add( _storyProgressChangeButton, 0, wxALL, 5 );
sbSizerGeneralInfo->Add( bSizerProfileCommands, 0, wxEXPAND, 5 );
bSizerProfilePanel->Add( sbSizerGeneralInfo, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerBottomHalf;
bSizerBottomHalf = new wxBoxSizer( wxHORIZONTAL );
wxStaticBoxSizer* sbSizerResearchInv;
sbSizerResearchInv = new wxStaticBoxSizer( new wxStaticBox( _profilePanel, wxID_ANY, wxT("Research inventory") ), wxVERTICAL );
_researchInventoryPropGrid = new wxPropertyGrid(sbSizerResearchInv->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_HIDE_MARGIN|wxPG_SPLITTER_AUTO_CENTER|wxPG_STATIC_LAYOUT|wxPG_STATIC_SPLITTER);
_materialsCategory = _researchInventoryPropGrid->Append( new wxPropertyCategory( wxT("Materials"), wxT("Materials") ) );
_verseSteel = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Verse Steel"), wxT("Verse Steel") ) );
_undinium = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Undinium"), wxT("Undinium") ) );
_necriumAlloy = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Necrium Alloy"), wxT("Necrium Alloy") ) );
_lunarite = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Lunarite"), wxT("Lunarite") ) );
_asterite = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Asterite"), wxT("Asterite") ) );
_ednil = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Ednil"), wxT("Ednil") ) );
_nuflalt = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Nuflalt"), wxT("Nuflalt") ) );
_aurelene = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Aurelene"), wxT("Aurelene") ) );
_soldus = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Soldus"), wxT("Soldus") ) );
_synthesizedN = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Synthesized N."), wxT("Synthesized N.") ) );
_alcarbonite = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Alcarbonite"), wxT("Alcarbonite") ) );
_keriphene = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Keriphene"), wxT("Keriphene") ) );
_nitinolCM = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Nitinol-CM"), wxT("Nitinol-CM") ) );
_quarkium = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Quarkium"), wxT("Quarkium") ) );
_alterene = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Alterene"), wxT("Alterene") ) );
_quarkDataCategory = _researchInventoryPropGrid->Append( new wxPropertyCategory( wxT("Quark Data"), wxT("Quark Data") ) );
_mixedComposition = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Mixed Composition"), wxT("Mixed Composition") ) );
_voidResidue = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Void Residue"), wxT("Void Residue") ) );
_muscularConstruction = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Muscular Construction"), wxT("Muscular Construction") ) );
_mineralExoskeletology = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Mineral Exoskeletology"), wxT("Mineral Exoskeletology") ) );
_carbonizedSkin = _researchInventoryPropGrid->Append( new wxIntProperty( wxT("Carbonized Skin"), wxT("Carbonized Skin") ) );
sbSizerResearchInv->Add( _researchInventoryPropGrid, 1, wxALL|wxEXPAND, 5 );
bSizerBottomHalf->Add( sbSizerResearchInv, 1, wxEXPAND|wxALL, 5 );
bSizerBottomHalf->Add( 0, 0, 1, wxEXPAND, 5 );
bSizerProfilePanel->Add( bSizerBottomHalf, 1, wxEXPAND, 5 );
bSizerProfilePanel->Add( sbSizerGeneralInfo, 1, wxEXPAND|wxALL, 5 );
_profilePanel->SetSizer( bSizerProfilePanel );
_profilePanel->Layout();
bSizerProfilePanel->Fit( _profilePanel );
_managerNotebook->AddPage( _profilePanel, wxT("Profile details and stats"), true );
_managerNotebook->AddPage( _profilePanel, wxT("Profile details and stats"), false );
_massPanel = new wxPanel( _managerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerMassPanel;
bSizerMassPanel = new wxBoxSizer( wxHORIZONTAL );
@ -247,6 +193,65 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
_massPanel->Layout();
bSizerMassPanel->Fit( _massPanel );
_managerNotebook->AddPage( _massPanel, wxT("M.A.S.S.es"), false );
_screenshotsPanel = new wxPanel( _managerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerScreenshotsPanel;
bSizerScreenshotsPanel = new wxBoxSizer( wxHORIZONTAL );
_screenshotsList = new wxListCtrl( _screenshotsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ALIGN_TOP|wxLC_AUTOARRANGE|wxLC_ICON|wxLC_SINGLE_SEL );
bSizerScreenshotsPanel->Add( _screenshotsList, 1, wxALL|wxEXPAND, 5 );
wxBoxSizer* bSizerScreenshotCommands;
bSizerScreenshotCommands = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizerSorting;
sbSizerSorting = new wxStaticBoxSizer( new wxStaticBox( _screenshotsPanel, wxID_ANY, wxT("Sorting") ), wxVERTICAL );
wxBoxSizer* bSizerSortType;
bSizerSortType = new wxBoxSizer( wxHORIZONTAL );
_nameRadio = new wxRadioButton( sbSizerSorting->GetStaticBox(), wxID_ANY, wxT("Filename"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
_nameRadio->SetValue( true );
bSizerSortType->Add( _nameRadio, 1, wxALL, 5 );
_creationDateRadio = new wxRadioButton( sbSizerSorting->GetStaticBox(), wxID_ANY, wxT("Creation date"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerSortType->Add( _creationDateRadio, 1, wxALL, 5 );
sbSizerSorting->Add( bSizerSortType, 1, wxEXPAND, 5 );
wxBoxSizer* bSizerSortOrder;
bSizerSortOrder = new wxBoxSizer( wxHORIZONTAL );
_ascendingRadio = new wxRadioButton( sbSizerSorting->GetStaticBox(), wxID_ANY, wxT("Ascending"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
_ascendingRadio->SetValue( true );
bSizerSortOrder->Add( _ascendingRadio, 1, wxALL, 5 );
_descendingRadio = new wxRadioButton( sbSizerSorting->GetStaticBox(), wxID_ANY, wxT("Descending"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerSortOrder->Add( _descendingRadio, 1, wxALL, 5 );
sbSizerSorting->Add( bSizerSortOrder, 1, wxEXPAND, 5 );
bSizerScreenshotCommands->Add( sbSizerSorting, 0, wxEXPAND|wxALL, 5 );
_viewScreenshotButton = new wxButton( _screenshotsPanel, wxID_ANY, wxT("View"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerScreenshotCommands->Add( _viewScreenshotButton, 0, wxALL|wxEXPAND, 5 );
_deleteScreenshotButton = new wxButton( _screenshotsPanel, wxID_ANY, wxT("Delete"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerScreenshotCommands->Add( _deleteScreenshotButton, 0, wxALL|wxEXPAND, 5 );
_screenshotDirButton = new wxButton( _screenshotsPanel, wxID_ANY, wxT("Open directory"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerScreenshotCommands->Add( _screenshotDirButton, 0, wxALL|wxEXPAND, 5 );
bSizerScreenshotsPanel->Add( bSizerScreenshotCommands, 0, wxEXPAND, 5 );
_screenshotsPanel->SetSizer( bSizerScreenshotsPanel );
_screenshotsPanel->Layout();
bSizerScreenshotsPanel->Fit( _screenshotsPanel );
_managerNotebook->AddPage( _screenshotsPanel, wxT("Photo mode shots"), false );
bSizerMainPanel->Add( _managerNotebook, 1, wxEXPAND, 5 );
@ -298,12 +303,9 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
// Connect Events
_profileChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainFrame::profileSelectionEvent ), NULL, this );
_backupSelectedButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::backupSelectedProfileEvent ), NULL, this );
_openScreenshotDirButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openScreenshotDirEvent ), NULL, this );
_unsafeCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrame::unsafeCheckboxEvent ), NULL, this );
_companyRenameButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::companyRenameEvent ), NULL, this );
_creditsEditButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::creditsEditEvent ), NULL, this );
_storyProgressChangeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openStoryProgressMenuEvent ), NULL, this );
_researchInventoryPropGrid->Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( MainFrame::inventoryChangeEvent ), NULL, this );
_managerNotebook->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( MainFrame::tabChangeEvent ), NULL, this );
_companyName->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( MainFrame::companyRenameEvent ), NULL, this );
_moveButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::moveMassEvent ), NULL, this );
_deleteButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::deleteMassEvent ), NULL, this );
_renameButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::renameMassEvent ), NULL, this );
@ -313,6 +315,16 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
_stagingList->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( MainFrame::stagingSelectionEvent ), NULL, this );
_deleteStagedButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::deleteStagedEvent ), NULL, this );
_stagingAreaButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openStagingDirEvent ), NULL, this );
_screenshotsList->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( MainFrame::viewScreenshotEvent ), NULL, this );
_screenshotsList->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( MainFrame::screenshotListSelectionEvent ), NULL, this );
_screenshotsList->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( MainFrame::screenshotListSelectionEvent ), NULL, this );
_nameRadio->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotFilenameSortingEvent ), NULL, this );
_creationDateRadio->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotCreationDateSortingEvent ), NULL, this );
_ascendingRadio->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotAscendingSortingEvent ), NULL, this );
_descendingRadio->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotDescendingSortingEvent ), NULL, this );
_viewScreenshotButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::viewScreenshotEvent ), NULL, this );
_deleteScreenshotButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::deleteScreenshotEvent ), NULL, this );
_screenshotDirButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openScreenshotDirEvent ), NULL, this );
this->Connect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( MainFrame::gameCheckTimerEvent ) );
}
@ -321,12 +333,9 @@ MainFrame::~MainFrame()
// Disconnect Events
_profileChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainFrame::profileSelectionEvent ), NULL, this );
_backupSelectedButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::backupSelectedProfileEvent ), NULL, this );
_openScreenshotDirButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openScreenshotDirEvent ), NULL, this );
_unsafeCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrame::unsafeCheckboxEvent ), NULL, this );
_companyRenameButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::companyRenameEvent ), NULL, this );
_creditsEditButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::creditsEditEvent ), NULL, this );
_storyProgressChangeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openStoryProgressMenuEvent ), NULL, this );
_researchInventoryPropGrid->Disconnect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( MainFrame::inventoryChangeEvent ), NULL, this );
_managerNotebook->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( MainFrame::tabChangeEvent ), NULL, this );
_companyName->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( MainFrame::companyRenameEvent ), NULL, this );
_moveButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::moveMassEvent ), NULL, this );
_deleteButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::deleteMassEvent ), NULL, this );
_renameButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::renameMassEvent ), NULL, this );
@ -336,6 +345,16 @@ MainFrame::~MainFrame()
_stagingList->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( MainFrame::stagingSelectionEvent ), NULL, this );
_deleteStagedButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::deleteStagedEvent ), NULL, this );
_stagingAreaButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openStagingDirEvent ), NULL, this );
_screenshotsList->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( MainFrame::viewScreenshotEvent ), NULL, this );
_screenshotsList->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( MainFrame::screenshotListSelectionEvent ), NULL, this );
_screenshotsList->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( MainFrame::screenshotListSelectionEvent ), NULL, this );
_nameRadio->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotFilenameSortingEvent ), NULL, this );
_creationDateRadio->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotCreationDateSortingEvent ), NULL, this );
_ascendingRadio->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotAscendingSortingEvent ), NULL, this );
_descendingRadio->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainFrame::screenshotDescendingSortingEvent ), NULL, this );
_viewScreenshotButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::viewScreenshotEvent ), NULL, this );
_deleteScreenshotButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::deleteScreenshotEvent ), NULL, this );
_screenshotDirButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::openScreenshotDirEvent ), NULL, this );
this->Disconnect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( MainFrame::gameCheckTimerEvent ) );
}

File diff suppressed because it is too large Load Diff

View File

@ -23,11 +23,10 @@
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/propgrid/propgrid.h>
#include <wx/propgrid/advprops.h>
#include <wx/panel.h>
#include <wx/listctrl.h>
#include <wx/listbox.h>
#include <wx/radiobut.h>
#include <wx/notebook.h>
#include <wx/hyperlink.h>
#include <wx/timer.h>
@ -48,7 +47,6 @@ class MainFrame : public wxFrame
wxStaticText* _profileLabel;
wxChoice* _profileChoice;
wxButton* _backupSelectedButton;
wxButton* _openScreenshotDirButton;
wxCheckBox* _unsafeCheckbox;
wxNotebook* _managerNotebook;
wxPanel* _profilePanel;
@ -60,32 +58,6 @@ class MainFrame : public wxFrame
wxStaticText* _storyProgress;
wxStaticText* _lastMissionIdLabel;
wxStaticText* _lastMissionId;
wxButton* _companyRenameButton;
wxButton* _creditsEditButton;
wxButton* _storyProgressChangeButton;
wxPropertyGrid* _researchInventoryPropGrid;
wxPGProperty* _materialsCategory;
wxPGProperty* _verseSteel;
wxPGProperty* _undinium;
wxPGProperty* _necriumAlloy;
wxPGProperty* _lunarite;
wxPGProperty* _asterite;
wxPGProperty* _ednil;
wxPGProperty* _nuflalt;
wxPGProperty* _aurelene;
wxPGProperty* _soldus;
wxPGProperty* _synthesizedN;
wxPGProperty* _alcarbonite;
wxPGProperty* _keriphene;
wxPGProperty* _nitinolCM;
wxPGProperty* _quarkium;
wxPGProperty* _alterene;
wxPGProperty* _quarkDataCategory;
wxPGProperty* _mixedComposition;
wxPGProperty* _voidResidue;
wxPGProperty* _muscularConstruction;
wxPGProperty* _mineralExoskeletology;
wxPGProperty* _carbonizedSkin;
wxPanel* _massPanel;
wxListView* _installedListView;
wxButton* _moveButton;
@ -97,6 +69,15 @@ class MainFrame : public wxFrame
wxListBox* _stagingList;
wxButton* _deleteStagedButton;
wxButton* _stagingAreaButton;
wxPanel* _screenshotsPanel;
wxListCtrl* _screenshotsList;
wxRadioButton* _nameRadio;
wxRadioButton* _creationDateRadio;
wxRadioButton* _ascendingRadio;
wxRadioButton* _descendingRadio;
wxButton* _viewScreenshotButton;
wxButton* _deleteScreenshotButton;
wxButton* _screenshotDirButton;
wxStaticText* _riskLabel;
wxStaticText* _gameStatusLabel;
wxStaticText* _gameStatus;
@ -107,12 +88,9 @@ class MainFrame : public wxFrame
// Virtual event handlers, overide them in your derived class
virtual void profileSelectionEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void backupSelectedProfileEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void openScreenshotDirEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void unsafeCheckboxEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void companyRenameEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void creditsEditEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void openStoryProgressMenuEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void inventoryChangeEvent( wxPropertyGridEvent& event ) { event.Skip(); }
virtual void tabChangeEvent( wxNotebookEvent& event ) { event.Skip(); }
virtual void companyRenameEvent( wxMouseEvent& event ) { event.Skip(); }
virtual void moveMassEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void deleteMassEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void renameMassEvent( wxCommandEvent& event ) { event.Skip(); }
@ -122,12 +100,21 @@ class MainFrame : public wxFrame
virtual void stagingSelectionEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void deleteStagedEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void openStagingDirEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void viewScreenshotEvent( wxListEvent& event ) { event.Skip(); }
virtual void screenshotListSelectionEvent( wxListEvent& event ) { event.Skip(); }
virtual void screenshotFilenameSortingEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void screenshotCreationDateSortingEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void screenshotAscendingSortingEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void screenshotDescendingSortingEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void viewScreenshotEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void deleteScreenshotEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void openScreenshotDirEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void gameCheckTimerEvent( wxTimerEvent& event ) { event.Skip(); }
public:
MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("M.A.S.S. Builder Save Tool 2.3.0"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxCLIP_CHILDREN|wxTAB_TRAVERSAL );
MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("M.A.S.S. Builder Save Tool 2.1.1"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxCLIP_CHILDREN|wxTAB_TRAVERSAL );
~MainFrame();

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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
@ -21,8 +21,7 @@
#include <map>
static const std::map<std::int32_t, const char*> story_progress_map {{
{0x00, "Chapter 1 start - Company isn't named yet"},
{0x64, "Chapter 1 - First time in the hangar"},
{0x64, "Chapter 1 start"},
{0x65, "Chapter 1 - After 1st meeting with Quin in mission section"},
{0x66, "Chapter 1 - After training, talking with Reina and Quin in hangar"},

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -2,7 +2,7 @@
#define MASS_H
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -2,7 +2,7 @@
#define MASSBUILDERMANAGER_H
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -1,5 +1,5 @@
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

View File

@ -2,7 +2,7 @@
#define MASSMANAGER_H
// wxMASSManager
// Copyright (C) 2020-2021 Guillaume Jacquemin
// 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

265
Profile/Profile.cpp Normal file
View File

@ -0,0 +1,265 @@
// 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 <Corrade/version.h>
#if !(CORRADE_VERSION_YEAR * 100 + CORRADE_VERSION_MONTH >= 202006)
#error This application requires Corrade 2020.06 or later to build.
#endif
#include <algorithm>
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/String.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include "Profile.h"
constexpr char company_name_locator[] = "CompanyName\0\x0c\0\0\0StrProperty";
constexpr char active_slot_locator[] = "ActiveFrameSlot\0\x0c\0\0\0IntProperty";
constexpr char credits_locator[] = "Credit\0\x0c\0\0\0IntProperty";
constexpr char story_progress_locator[] = "StoryProgress\0\x0c\0\0\0IntProperty";
constexpr char last_mission_id_locator[] = "LastMissionID\0\x0c\0\0\0IntProperty";
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::getCompanyName() -> std::string const& {
auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename));
auto it = std::search(mmap.begin(), mmap.end(), &company_name_locator[0], &company_name_locator[27]);
if(it == mmap.end()) {
_lastError = "Couldn't find a company name in " + _filename;
_companyName = "";
}
else {
_companyName = std::string{it + 41};
}
return _companyName;
}
auto Profile::renameCompany(const std::string& new_name) -> bool {
char length_difference = static_cast<char>(_companyName.length() - new_name.length());
std::string profile_data = Utility::Directory::readString(Utility::Directory::join(_profileDirectory, _filename));
auto iter = std::search(profile_data.begin(), profile_data.end(), &company_name_locator[0], &company_name_locator[27]);
if(iter != profile_data.end()) {
*(iter + 0x1C) = *(iter + 0x1C) - length_difference;
*(iter + 0x25) = *(iter + 0x25) - length_difference;
while(*(iter + 0x29) != '\0') {
profile_data.erase(iter + 0x29);
}
profile_data.insert(iter + 0x29, new_name.cbegin(), new_name.cend());