Compare commits

...

7 Commits

7 changed files with 243 additions and 82 deletions

View File

@ -24,7 +24,7 @@ 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(NOT USE_CORRADE_SUBMODULE)
if(USE_CORRADE_SUBMODULE)
set(BUILD_STATIC ON CACHE BOOL "" FORCE)
set(WITH_INTERCONNECT OFF CACHE BOOL "" FORCE)
set(WITH_PLUGINMANAGER OFF CACHE BOOL "" FORCE)

View File

@ -62,10 +62,11 @@ EvtMainFrame::EvtMainFrame(wxWindow* parent):
{
SetIcon(wxIcon("MAINICON"));
//warningMessage(wxString::FromUTF8("Before you start using this app, a few things you should know:\n\n"
// "For this application to work properly, Steam Cloud syncing needs to be disabled for the game.\nTo disable it, right-click the game in your Steam library, click \"Properties\", go to the \"Updates\" tab, and uncheck \"Enable Steam Cloud synchronization for M.A.S.S. Builder\".\n\n"
// "DISCLAIMER: The developer of this application (Guillaume Jacquemin) isn't associated with Vermillion Digital, and both parties cannot be held responsible for data loss or corruption this app might cause. PLEASE USE AT YOUR OWN RISK!\n\n"
// "Last but not least, this application is released under the terms of the GNU General Public Licence version 3. Please see the COPYING file for more details."));
warningMessage(wxString::FromUTF8("Before you start using this app, a few things you should know:\n\n"
"This is a pre-release version of the application, and as a result, was not as tested as a version considered stable. Please make frequent backups when using it!\n\n"
"For this application to work properly, Steam Cloud syncing needs to be disabled for the game.\nTo disable it, right-click the game in your Steam library, click \"Properties\", go to the \"General\" tab, and uncheck \"Keep game saves in the Steam Cloud for M.A.S.S. Builder\".\n\n"
"DISCLAIMER: The developer of this application (Guillaume Jacquemin) isn't associated with Vermillion Digital, and both parties cannot be held responsible for data loss or corruption this app might cause. PLEASE USE AT YOUR OWN RISK!\n\n"
"Last but not least, this application is released under the terms of the GNU General Public Licence version 3. Please see the COPYING file for more details."));
if(!_mbManager.ready()) {
errorMessage("There was an error initialising the manager:\n\n" + _mbManager.lastError());
@ -77,14 +78,23 @@ EvtMainFrame::EvtMainFrame(wxWindow* parent):
return;
}
std::size_t default_profile = 0;
int counter = 0;
for(const Profile& p : _profileManager.profiles()) {
if(p.valid()) {
_profileChoice->Append(wxString::Format("%s%s", p.companyName(), p.type() == ProfileType::Demo ? " (Demo)" : ""));
if(p.type() == ProfileType::FullGame && default_profile == 0) {
default_profile = counter;
}
counter++;
}
}
_profileManager.setProfile(0);
_profileChoice->SetSelection(0);
_profileManager.setProfile(default_profile);
_profileChoice->SetSelection(default_profile);
_massManager.emplace(_profileManager.profileDirectory(),
_profileManager.currentProfile()->steamId(),
@ -182,24 +192,37 @@ void EvtMainFrame::companyRenameEvent(wxMouseEvent&) {
int result = dialog.ShowModal();
if(result == wxID_OK) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, renaming the company is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_profileManager.currentProfile()->renameCompany(dialog.getName())) {
errorMessage(error_prefix + _profileManager.currentProfile()->lastError());
}
else {
_profileChoice->SetString(_profileChoice->GetCurrentSelection(),
wxString::Format("%s%s",
_profileManager.currentProfile()->companyName(),
_profileManager.currentProfile()->type() == ProfileType::Demo ? " (Demo)" : ""));
}
break;
case GameState::Running:
errorMessage(error_prefix + "Renaming the company is disabled while the game is running.");
break;
if(_unsafeMode == false) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, renaming the company is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_profileManager.currentProfile()->renameCompany(dialog.getName())) {
errorMessage(error_prefix + _profileManager.currentProfile()->lastError());
}
else {
_profileChoice->SetString(_profileChoice->GetCurrentSelection(),
wxString::Format("%s%s",
_profileManager.currentProfile()->companyName(),
_profileManager.currentProfile()->type() == ProfileType::Demo ? " (Demo)" : ""));
}
break;
case GameState::Running:
errorMessage(error_prefix + "Renaming the company is disabled while the game is running.");
break;
}
}
else {
if(!_profileManager.currentProfile()->renameCompany(dialog.getName())) {
errorMessage(error_prefix + _profileManager.currentProfile()->lastError());
}
else {
_profileChoice->SetString(_profileChoice->GetCurrentSelection(),
wxString::Format("%s%s",
_profileManager.currentProfile()->companyName(),
_profileManager.currentProfile()->type() == ProfileType::Demo ? " (Demo)" : ""));
}
}
}
}
@ -228,18 +251,25 @@ void EvtMainFrame::importMassEvent(wxCommandEvent&) {
return;
}
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, importing is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->importMass(staged_selection, selected_hangar)) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Importing a M.A.S.S. is disabled while the game is running.");
break;
if(_unsafeMode == false) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, importing is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->importMass(staged_selection, selected_hangar)) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Importing a M.A.S.S. is disabled while the game is running.");
break;
}
}
else {
if(!_massManager->importMass(staged_selection, selected_hangar)) {
errorMessage(error_prefix + _massManager->lastError());
}
}
}
@ -269,18 +299,25 @@ void EvtMainFrame::moveMassEvent(wxCommandEvent&) {
return;
}
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, moving a M.A.S.S. is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->moveMass(source_slot, choice - 1)) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Moving a M.A.S.S. is disabled while the game is running.");
break;
if(_unsafeMode == false) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, moving a M.A.S.S. is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->moveMass(source_slot, choice - 1)) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Moving a M.A.S.S. is disabled while the game is running.");
break;
}
}
else {
if(!_massManager->moveMass(source_slot, choice - 1)) {
errorMessage(error_prefix + _massManager->lastError());
}
}
}
@ -292,18 +329,25 @@ void EvtMainFrame::deleteMassEvent(wxCommandEvent&) {
return;
}
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, deleting a M.A.S.S. is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->deleteMass(_installedListView->GetFirstSelected())) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Deleting a M.A.S.S. is disabled while the game is running.");
break;
if(_unsafeMode == false) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, deleting a M.A.S.S. is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->deleteMass(_installedListView->GetFirstSelected())) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Deleting a M.A.S.S. is disabled while the game is running.");
break;
}
}
else {
if(!_massManager->deleteMass(_installedListView->GetFirstSelected())) {
errorMessage(error_prefix + _massManager->lastError());
}
}
}
@ -315,18 +359,25 @@ void EvtMainFrame::renameMassEvent(wxCommandEvent&) {
int result = dialog.ShowModal();
if(result == wxID_OK) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, renaming a M.A.S.S. is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->renameMass(_installedListView->GetFirstSelected(), dialog.getName())) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Renaming a M.A.S.S. is disabled while the game is running.");
break;
if(_unsafeMode == false) {
switch(_mbManager.gameState()) {
case GameState::Unknown:
errorMessage(error_prefix + "For security reasons, renaming a M.A.S.S. is disabled if the game's status is unknown.");
break;
case GameState::NotRunning:
if(!_massManager->renameMass(_installedListView->GetFirstSelected(), dialog.getName())) {
errorMessage(error_prefix + _massManager->lastError());
}
break;
case GameState::Running:
errorMessage(error_prefix + "Renaming a M.A.S.S. is disabled while the game is running.");
break;
}
}
else {
if(!_massManager->renameMass(_installedListView->GetFirstSelected(), dialog.getName())) {
errorMessage(error_prefix + _massManager->lastError());
}
}
}
}
@ -455,6 +506,25 @@ void EvtMainFrame::gameCheckTimerEvent(wxTimerEvent&) {
isGameRunning();
}
void EvtMainFrame::unsafeCheckboxEvent(wxCommandEvent& event) {
if(event.IsChecked() == true) {
int confirmation = wxMessageBox("Are you sure you want to enable unsafe mode ?\n\n"
"Unsafe mode will allow you to perform changes even while the game is running, which can result in weird behaviour or even data corruption.",
"Question", wxYES_NO|wxCENTRE|wxICON_WARNING, this);
if(confirmation == wxYES) {
_unsafeMode = true;
}
else {
_unsafeCheckbox->SetValue(false);
}
}
else {
_unsafeMode = false;
}
updateCommandsState();
}
void EvtMainFrame::saveFileEventHandler(int event_type, const wxString& event_file, const wxFileSystemWatcherEvent& event) {
wxRegEx regex;
@ -639,11 +709,11 @@ void EvtMainFrame::updateCommandsState() {
GameState game_state = _mbManager.gameState();
MassState mass_state = _massManager->massState(selection);
_importButton->Enable(selection != -1 && staged_selection != -1 && game_state != GameState::Running);
_importButton->Enable(selection != -1 && staged_selection != -1 && (_unsafeMode == true || game_state == GameState::NotRunning));
_exportButton->Enable(selection != -1);
_moveButton->Enable(selection != -1 && game_state == GameState::NotRunning && mass_state == MassState::Valid);
_deleteButton->Enable(selection != -1 && game_state == GameState::NotRunning && mass_state != MassState::Empty);
_renameButton->Enable(selection != -1 && game_state == GameState::NotRunning && mass_state == MassState::Valid);
_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);

View File

@ -75,6 +75,7 @@ class EvtMainFrame: public MainFrame {
void tabChangeEvent(wxNotebookEvent& event);
void fileUpdateEvent(wxFileSystemWatcherEvent& event);
void gameCheckTimerEvent(wxTimerEvent&);
void unsafeCheckboxEvent(wxCommandEvent& event);
private:
void saveFileEventHandler(int event_type, const wxString& event_file, const wxFileSystemWatcherEvent& event);
@ -97,6 +98,8 @@ class EvtMainFrame: public MainFrame {
void warningMessage(const wxString& message);
void errorMessage(const wxString& message);
bool _unsafeMode = false;
MassBuilderManager _mbManager;
ProfileManager _profileManager;
Containers::Pointer<MassManager> _massManager;

View File

@ -38,6 +38,14 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
bSizerProfile->Add( _backupSelectedButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizerProfile->Add( 0, 0, 1, wxEXPAND, 5 );
_unsafeCheckbox = new wxCheckBox( _mainPanel, wxID_ANY, wxT("Unsafe mode"), wxDefaultPosition, wxDefaultSize, 0 );
_unsafeCheckbox->SetToolTip( wxT("CLICK AT YOUR OWN RISK!") );
bSizerProfile->Add( _unsafeCheckbox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizerMainPanel->Add( bSizerProfile, 0, wxEXPAND, 5 );
_managerNotebook = new wxNotebook( _mainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
@ -271,7 +279,7 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
bSizerMainPanel->Add( bSizerGameStatus, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
_aboutText = new wxStaticText( _mainPanel, wxID_ANY, wxT("This version of the application was partially tested on M.A.S.S. Builder early access version 0.5.4.\nIt may or may not work with other versions of the game.\nMade for the M.A.S.S. Builder community by Guillaume Jacquemin."), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL );
_aboutText = new wxStaticText( _mainPanel, wxID_ANY, wxT("This version of the application was partially tested on M.A.S.S. Builder early access version 0.5.7.\nIt may or may not work with other versions of the game.\nMade for the M.A.S.S. Builder community by Guillaume Jacquemin."), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL );
_aboutText->Wrap( -1 );
bSizerMainPanel->Add( _aboutText, 0, wxEXPAND|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 );
@ -295,6 +303,7 @@ 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 );
_unsafeCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrame::unsafeCheckboxEvent ), 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 );
@ -324,6 +333,7 @@ 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 );
_unsafeCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrame::unsafeCheckboxEvent ), 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 );

View File

@ -48,7 +48,7 @@
<property name="size">-1,-1</property>
<property name="style">wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU</property>
<property name="subclass">; ; forward_declare</property>
<property name="title">M.A.S.S. Builder Save Tool 2.0.0-pre1</property>
<property name="title">M.A.S.S. Builder Save Tool 2.0.0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
@ -327,6 +327,81 @@
<event name="OnButtonClick">backupSelectedProfileEvent</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Unsafe mode</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">_unsafeCheckbox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">CLICK AT YOUR OWN RISK!</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">unsafeCheckboxEvent</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
@ -2690,7 +2765,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">This version of the application was partially tested on M.A.S.S. Builder early access version 0.5.4.&#x0A;It may or may not work with other versions of the game.&#x0A;Made for the M.A.S.S. Builder community by Guillaume Jacquemin.</property>
<property name="label">This version of the application was partially tested on M.A.S.S. Builder early access version 0.5.7.&#x0A;It may or may not work with other versions of the game.&#x0A;Made for the M.A.S.S. Builder community by Guillaume Jacquemin.</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>

View File

@ -20,6 +20,7 @@
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/panel.h>
@ -46,6 +47,7 @@ class MainFrame : public wxFrame
wxStaticText* _profileLabel;
wxChoice* _profileChoice;
wxButton* _backupSelectedButton;
wxCheckBox* _unsafeCheckbox;
wxNotebook* _managerNotebook;
wxPanel* _profilePanel;
wxStaticText* _companyNameLabel;
@ -86,6 +88,7 @@ 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 unsafeCheckboxEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void tabChangeEvent( wxNotebookEvent& event ) { event.Skip(); }
virtual void companyRenameEvent( wxMouseEvent& event ) { event.Skip(); }
virtual void moveMassEvent( wxCommandEvent& event ) { event.Skip(); }
@ -111,7 +114,7 @@ class MainFrame : public wxFrame
public:
MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("M.A.S.S. Builder Save Tool 2.0.0-pre1"), 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.0.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();

View File

@ -28,7 +28,7 @@ class MyApp: public wxApp {
public:
bool OnInit() {
SetAppName("wxMASSManager");
SetAppDisplayName("wxMASSManager");
SetAppDisplayName("M.A.S.S. Builder Save Tool");
wxImage::AddHandler(new wxPNGHandler);