553 lines
17 KiB
C++
553 lines
17 KiB
C++
/*
|
|
speciesgen
|
|
Copyright (C) 2022-2023 prisixia
|
|
|
|
This file is part of speciesgen.
|
|
|
|
speciesgen 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.
|
|
|
|
speciesgen 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 speciesgen. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "speciesgen.h"
|
|
|
|
//----------------------------------------------------------------------
|
|
// main()
|
|
//----------------------------------------------------------------------
|
|
|
|
wxIMPLEMENT_APP(SpeciesGen::App);
|
|
|
|
namespace SpeciesGen {
|
|
|
|
//----------------------------------------------------------------------
|
|
// App
|
|
//----------------------------------------------------------------------
|
|
|
|
bool App::OnInit() {
|
|
if (!wxApp::OnInit()) {
|
|
return false;
|
|
}
|
|
|
|
// NOLINTBEGIN(cppcoreguidelines-owning-memory): wxWidgets already manages
|
|
// its memory more or less so that there's no need for owning the memory
|
|
Frame *frame = new Frame("Species Support Generator", 680, 480);
|
|
wxMenu *file_menu = new wxMenu;
|
|
wxMenu *help_menu = new wxMenu;
|
|
wxMenuBar *menu_bar = new wxMenuBar(wxMB_DOCKABLE);
|
|
// NOLINTEND(cppcoreguidelines-owning-memory)
|
|
|
|
#if wxUSE_FILEDLG
|
|
file_menu->Append(TEXT_EXPORT, "&Export weightstages\tCTRL+S",
|
|
"Export the weightstages configuration to file.");
|
|
file_menu->Append(TEXT_IMPORT, "&Import weightstages\tCTRL+O",
|
|
"Import and overwrite the weightstages configuration.");
|
|
file_menu->Append(TEXT_IMPORT_APPEND, "&Append weightstages\tCTRL+SHIFT+O",
|
|
"Import and append to the weightstages configuration.");
|
|
file_menu->AppendSeparator();
|
|
#endif // wxUSE_FILEDLG
|
|
file_menu->Append(TEXT_QUIT, "&Exit\tALT+X", "Quit this program.");
|
|
|
|
help_menu->Append(TEXT_ABOUT, "&About");
|
|
|
|
menu_bar->Append(file_menu, "&File");
|
|
menu_bar->Append(help_menu, "&Help");
|
|
|
|
frame->SetMenuBar(menu_bar);
|
|
frame->Show(true);
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// SpritesPanel
|
|
//----------------------------------------------------------------------
|
|
|
|
/*
|
|
SpritesPanel::SpritesPanel(wxWindow *window, int x, int y, int w, int h,
|
|
const std::string handlerName)
|
|
: wxPanel(window, wxID_ANY, wxPoint(x, y), wxSize(w, h)),
|
|
ErrorHandler(handlerName)
|
|
{
|
|
wxImage::AddHandler(new wxPNGHandler);
|
|
wxBoxSizer *row1 = new wxBoxSizer(wxHORIZONTAL);
|
|
wxBoxSizer *row2 = new wxBoxSizer(wxHORIZONTAL);
|
|
wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
topSizer->Add(row1, 0, wxLEFT | wxUP | wxEXPAND, 10);
|
|
topSizer->Add(row2, 0, wxALL | wxEXPAND, 10);
|
|
|
|
SetSizer(topSizer);
|
|
}
|
|
*/
|
|
|
|
//----------------------------------------------------------------------
|
|
// Frame
|
|
//----------------------------------------------------------------------
|
|
|
|
wxBEGIN_EVENT_TABLE(Frame, wxFrame)
|
|
#if wxUSE_FILEDLG
|
|
EVT_MENU(TEXT_EXPORT, Frame::OnExport)
|
|
EVT_MENU(TEXT_IMPORT, Frame::OnImport)
|
|
EVT_MENU(TEXT_IMPORT_APPEND, Frame::OnImportAppend)
|
|
#endif // wxUSE_FILEDLG
|
|
EVT_MENU(TEXT_QUIT, Frame::OnQuit)
|
|
EVT_MENU(TEXT_ABOUT, Frame::OnAbout)
|
|
|
|
#if wxUSE_CLIPBOARD
|
|
// EVT_MENU(TEXT_CLIPBOARD_PASTE, Frame::OnPasteFromClipboard)
|
|
// EVT_MENU(TEXT_CLIPBOARD_COPY, Frame::OnCopyToClipboard)
|
|
// EVT_UPDATE_UI(TEXT_CLIPBOARD_PASTE, Frame::OnUpdatePasteFromClipboard)
|
|
// EVT_UPDATE_UI(TEXT_CLIPBOARD_COPY, Frame::OnUpdateCopyToClipboard)
|
|
#endif // wxUSE_CLIPBOARD
|
|
wxEND_EVENT_TABLE()
|
|
|
|
// NOLINTBEGIN(cppcoreguidelines-owning-memory): wxWidgets already manages its
|
|
// memory more or less so that there's no need for owning the memory
|
|
Frame::Frame(const wxString &title, int x, int y)
|
|
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(x, y),
|
|
wxDEFAULT_FRAME_STYLE) {
|
|
#ifdef WIN32
|
|
// SetIcon(wxICON(IDI_ICON1));
|
|
#endif // _WIN32
|
|
SetMinSize(wxSize(x, y));
|
|
|
|
#if wxUSE_STATUSBAR
|
|
/*
|
|
CreateStatusBar(2);
|
|
int *widths = new int[2];
|
|
widths[0] = 140;
|
|
widths[1] = -1;
|
|
SetStatusWidths(2, widths);
|
|
delete[] widths;
|
|
*/
|
|
|
|
CreateStatusBar(1);
|
|
#endif // wxUSE_STATUSBAR
|
|
|
|
// TODO: Implement SpritesPanel
|
|
m_notebook = new wxNotebook(this, wxID_ANY);
|
|
|
|
m_panel_main = new MainPanel(m_notebook, 10, 10, 0, 0, "Main");
|
|
m_panel_stages = new StagesPanel(m_notebook, 10, 10, 0, 0, "Stages");
|
|
// m_panel_sprites = new SpritesPanel(m_notebook, 10, 10, 300, 100);
|
|
// m_panel_main->GetSizer()->Fit(this);
|
|
|
|
m_notebook->AddPage(m_panel_main, "Main");
|
|
m_notebook->AddPage(m_panel_stages, "Stages");
|
|
// m_notebook->AddPage(m_panel_sprites, "Sprites");
|
|
wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
|
|
mainSizer->Add(m_notebook, 1, wxALL | wxEXPAND);
|
|
SetSizer(mainSizer);
|
|
DoCheckErrors();
|
|
m_panel_main->m_generate->Bind(wxEVT_BUTTON, &Frame::DoGenerateMod, this);
|
|
m_panel_main->m_author->Bind(wxEVT_TEXT, &Frame::OnCheckErrors, this);
|
|
m_panel_main->m_name->Bind(wxEVT_TEXT, &Frame::OnCheckErrors, this);
|
|
m_panel_main->m_friendlyName->Bind(wxEVT_TEXT, &Frame::OnCheckErrors, this);
|
|
m_panel_main->m_modDestination->Bind(wxEVT_TEXT, &Frame::OnCheckErrors,
|
|
this);
|
|
m_panel_stages->m_add->Bind(wxEVT_BUTTON, &Frame::OnAddWeightStage, this);
|
|
m_panel_stages->m_remove->Bind(wxEVT_BUTTON, &Frame::OnRemoveWeightStage,
|
|
this);
|
|
m_panel_stages->m_id->Bind(wxEVT_CHECKBOX, &Frame::OnClickCheckboxID, this);
|
|
m_panel_stages->m_subAdd->Bind(wxEVT_BUTTON, &Frame::OnAddWeightStageSub,
|
|
this);
|
|
m_panel_stages->m_subRemove->Bind(wxEVT_BUTTON,
|
|
&Frame::OnRemoveWeightStageSub, this);
|
|
}
|
|
// NOLINTEND(cppcoreguidelines-owning-memory)
|
|
|
|
#if wxUSE_CLIPBOARD
|
|
/*
|
|
void Frame::OnPasteFromClipboard(wxCommandEvent &WXUNUSED(event))
|
|
{
|
|
m_panel_main->DoPasteFromClipboard();
|
|
}
|
|
|
|
void Frame::OnCopyToClipboard(wxCommandEvent &WXUNUSED(event))
|
|
{
|
|
m_panel_main->DoCopyToClipboard();
|
|
}
|
|
|
|
void Frame::OnUpdatePasteFromClipboard(wxUpdateUIEvent &event)
|
|
{
|
|
wxClipboardLocker lockClip;
|
|
event.Enable(wxTheClipboard->IsSupported(wxDF_TEXT));
|
|
}
|
|
|
|
void Frame::OnUpdateCopyToClipboard(wxUpdateUIEvent &event)
|
|
{
|
|
event.Enable(m_panel_main->HasSelection());
|
|
}
|
|
*/
|
|
#endif // wxUSE_CLIPBOARD
|
|
|
|
void Frame::OnClickCheckboxID(wxCommandEvent &event) {
|
|
m_panel_stages->DoClickCheckboxID(event.IsChecked());
|
|
DoCheckErrors();
|
|
}
|
|
|
|
void Frame::OnAddWeightStage(wxCommandEvent &WXUNUSED(event)) {
|
|
m_panel_stages->DoAddWeightStage();
|
|
DoCheckErrors();
|
|
}
|
|
|
|
void Frame::OnRemoveWeightStage(wxCommandEvent &WXUNUSED(event)) {
|
|
m_panel_stages->DoRemoveWeightStage();
|
|
DoCheckErrors();
|
|
}
|
|
|
|
void Frame::OnAddWeightStageSub(wxCommandEvent &WXUNUSED(event)) {
|
|
m_panel_stages->DoAddWeightStageSub();
|
|
DoCheckErrors();
|
|
}
|
|
|
|
void Frame::OnRemoveWeightStageSub(wxCommandEvent &WXUNUSED(event)) {
|
|
m_panel_stages->DoRemoveWeightStageSub();
|
|
DoCheckErrors();
|
|
}
|
|
|
|
void Frame::OnQuit(wxCommandEvent &WXUNUSED(event)) { Close(true); }
|
|
|
|
void Frame::OnAbout(wxCommandEvent &WXUNUSED(event)) {
|
|
wxMessageDialog dialog(this, SPECIESGEN_ABOUT_PAGE,
|
|
"About Species Support Generator",
|
|
wxOK | wxICON_INFORMATION);
|
|
|
|
dialog.ShowModal();
|
|
}
|
|
|
|
#if wxUSE_FILEDLG
|
|
void Frame::OnExport(wxCommandEvent &WXUNUSED(event)) {
|
|
DoReadWeightStages(CONFIG_EXPORT);
|
|
}
|
|
|
|
void Frame::OnImport(wxCommandEvent &WXUNUSED(event)) {
|
|
DoReadWeightStages(CONFIG_IMPORT);
|
|
}
|
|
|
|
void Frame::OnImportAppend(wxCommandEvent &WXUNUSED(event)) {
|
|
DoReadWeightStages(CONFIG_IMPORT_APPEND);
|
|
}
|
|
|
|
void Frame::DoReadWeightStages(int style) {
|
|
std::filesystem::path path;
|
|
if ((CONFIG_EXPORT & style) == CONFIG_EXPORT) {
|
|
OnFileOpen("Export weightstages to JSON",
|
|
"JSON file (*.json)|*.json|Any file (*.*)|*.*", wxFD_SAVE,
|
|
path);
|
|
if (!path.empty()) {
|
|
const std::vector<Starpounds::WeightStage> stages =
|
|
m_panel_stages->GetWeightStages();
|
|
|
|
std::ofstream file_stages(path);
|
|
cereal::JSONOutputArchive archive(file_stages);
|
|
cereal::Save(archive, stages);
|
|
}
|
|
} else {
|
|
OnFileOpen("Import weightstages from JSON",
|
|
"JSON file (*.json)|*.json|Any file (*.*)|*.*",
|
|
wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST, path);
|
|
if (!path.empty()) {
|
|
std::vector<Starpounds::WeightStage> stages;
|
|
|
|
{
|
|
std::ifstream ifs(path);
|
|
cereal::JSONInputArchive archive(ifs);
|
|
cereal::Load(archive, stages);
|
|
}
|
|
|
|
if ((CONFIG_IMPORT_APPEND & style) != CONFIG_IMPORT_APPEND) {
|
|
m_panel_stages->ClearWeightStages();
|
|
}
|
|
|
|
for (const auto &stage : stages) {
|
|
m_panel_stages->DoAddWeightStage(stage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Frame::OnFileOpen(const std::string &message, const std::string &wildcard,
|
|
int style, std::filesystem::path &path) {
|
|
const std::filesystem::path path_home =
|
|
wxStandardPaths::Get()
|
|
.GetUserDir(wxStandardPaths::Dir_Desktop)
|
|
.ToStdString();
|
|
|
|
wxFileDialog dialog(this, message, path_home.string(), wxEmptyString,
|
|
wildcard, style);
|
|
|
|
if (dialog.ShowModal() == wxID_OK) {
|
|
path = dialog.GetPath().ToStdString();
|
|
}
|
|
}
|
|
#endif // wxUSE_FILEDLG
|
|
|
|
bool Frame::DoCheckErrors() {
|
|
const size_t errorCount_main = m_panel_main->CheckForErrors();
|
|
const size_t errorCount_stages = m_panel_stages->CheckForErrors();
|
|
bool hasError = errorCount_main > 0 || errorCount_stages > 0;
|
|
|
|
if (errorCount_main > 0) {
|
|
SetStatusText(m_panel_main->GetError(0));
|
|
} else if (errorCount_stages > 0) {
|
|
SetStatusText(m_panel_stages->GetError(0));
|
|
} else {
|
|
SetStatusText("[INFO]: No errors have been found, the generation "
|
|
"button has been unlocked.");
|
|
}
|
|
|
|
m_panel_main->m_generate->Enable(!hasError);
|
|
|
|
return hasError;
|
|
}
|
|
|
|
void Frame::OnCheckErrors(wxCommandEvent &WXUNUSED(event)) { DoCheckErrors(); }
|
|
|
|
void Frame::DoGenerateMod(wxCommandEvent &WXUNUSED(event)) {
|
|
wxBeginBusyCursor();
|
|
if (DoCheckErrors()) {
|
|
return;
|
|
}
|
|
for (size_t i = 0; i < m_notebook->GetPageCount(); i++) {
|
|
m_notebook->GetPage(i)->Disable();
|
|
}
|
|
|
|
const std::vector<Starpounds::WeightStage> stages =
|
|
m_panel_stages->GetWeightStages();
|
|
const std::string species = m_panel_main->m_name->GetValue().ToStdString();
|
|
const std::string friendlySpecies =
|
|
m_panel_main->m_friendlyName->GetValue().ToStdString();
|
|
const std::string author = m_panel_main->m_author->GetValue().ToStdString();
|
|
const std::filesystem::path path_mod =
|
|
m_panel_main->m_modDestination->GetValue().ToStdString() +
|
|
wxString::Format("/%ssupport", species).ToStdString();
|
|
const std::filesystem::path path_species =
|
|
path_mod /
|
|
wxString::Format("items/armors/weightstages/%s", species).ToStdString();
|
|
|
|
std::filesystem::create_directories(path_species);
|
|
|
|
{
|
|
const Starbound::Metadata metadata(
|
|
wxString::Format("Starpounds %s species", species).ToStdString(),
|
|
wxString::Format("Starpounds - %s species support", friendlySpecies)
|
|
.ToStdString(),
|
|
author);
|
|
|
|
const std::filesystem::path path_metadata = path_mod / "_metadata";
|
|
|
|
if (!std::ifstream(path_metadata).good()) {
|
|
std::ofstream file_metadata(path_metadata);
|
|
cereal::JSONOutputArchive archive(file_metadata);
|
|
cereal::Save(archive, metadata);
|
|
}
|
|
}
|
|
|
|
{
|
|
const std::filesystem::path path_starpounds =
|
|
path_mod / "scripts/starpounds";
|
|
std::filesystem::create_directories(path_starpounds);
|
|
const Starbound::Patch::Patch patch =
|
|
Starbound::Patch::Patch<Starpounds::SpeciesConfig>(
|
|
wxString::Format("/%s", species).ToStdString());
|
|
|
|
const std::filesystem::path path_patch =
|
|
path_starpounds / "starpounds_species.config.patch";
|
|
|
|
if (!std::ifstream(path_patch).good()) {
|
|
std::ofstream file_patch(path_patch);
|
|
cereal::JSONOutputArchive archive(file_patch);
|
|
cereal::Save(archive, std::vector({patch}));
|
|
}
|
|
}
|
|
|
|
const std::vector<std::filesystem::path> baseImages = {
|
|
"chestf.png", "chestm.png", "bsleevef.png", "bsleevem.png",
|
|
"fsleevef.png", "fsleevem.png", "icons.png"};
|
|
|
|
const std::unordered_map<std::string, std::string> aliases = {
|
|
{"swimIdle.2", "swimIdle.1"},
|
|
{"swim.5", "swimIdle.1"},
|
|
{"swim.6", "swimIdle.2"},
|
|
{"swim.7", "swimIdle.2"},
|
|
{"lay.1", "idle.1"}};
|
|
|
|
const std::vector<std::vector<std::optional<std::string>>> names = {
|
|
{std::nullopt, "idle.1", "idle.2", "idle.3", "idle.4", "idle.5",
|
|
"sit.1", std::nullopt, "duck.1"},
|
|
{std::nullopt, "walk.1", "walk.2", "walk.3", "walk.4", "walk.5",
|
|
"walk.6", "walk.7", "walk.8"},
|
|
{std::nullopt, "run.1", "run.2", "run.3", "run.4", "run.5", "run.6",
|
|
"run.7", "run.8"},
|
|
{std::nullopt, "jump.1", "jump.2", "jump.3", "jump.4", "fall.1",
|
|
"fall.2", "fall.3", "fall.4"},
|
|
{std::nullopt, "climb.1", "climb.2", "climb.3", "climb.4", "climb.5",
|
|
"climb.6", "climb.7", "climb.8"},
|
|
{std::nullopt, "swimIdle.1", std::nullopt, std::nullopt, "swim.1",
|
|
"swim.2", "swim.3", "swim.4", std::nullopt}};
|
|
|
|
const Starbound::Item::Frames maleFrames("chestm.png", "bsleevem.png",
|
|
"fsleevem.png");
|
|
const Starbound::Item::Frames femaleFrames("chestf.png", "bsleevef.png",
|
|
"fsleevef.png");
|
|
|
|
for (const Starpounds::WeightStage &stage : stages) {
|
|
const std::string baseShortDescription =
|
|
(stage.GetFriendlyName().empty()
|
|
? friendlySpecies
|
|
: wxString::Format("%s %s", stage.GetFriendlyName(),
|
|
friendlySpecies)
|
|
.ToStdString());
|
|
const std::string stageName = stage.GetName();
|
|
|
|
const std::filesystem::path path_stage = path_species / stageName;
|
|
|
|
if (!std::filesystem::exists(path_stage)) {
|
|
std::filesystem::create_directory(path_stage);
|
|
}
|
|
|
|
if (stage.HasFrames()) {
|
|
const Starbound::Frames::Frames frame(
|
|
aliases, Starbound::Frames::Grid(names));
|
|
for (const auto &pants : {"pantsf", "pantsm"}) {
|
|
const std::filesystem::path path_frame =
|
|
path_species /
|
|
wxString::Format("%s_%s.frames", stageName, pants)
|
|
.ToStdString();
|
|
|
|
if (!std::ifstream(path_frame).good()) {
|
|
std::ofstream file_frame(path_frame);
|
|
cereal::JSONOutputArchive archive(file_frame);
|
|
cereal::Save(archive, frame);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (stage.HasID()) {
|
|
std::vector<std::filesystem::path> _baseImages = baseImages;
|
|
|
|
std::filesystem::path path_pantsf = "pantsf.png";
|
|
std::filesystem::path path_pantsm = "pantsm.png";
|
|
|
|
if (stage.HasFrames()) {
|
|
path_pantsf =
|
|
wxString::Format("%s_pantsf.png", stageName).ToStdString();
|
|
path_pantsm =
|
|
wxString::Format("%s_pantsm.png", stageName).ToStdString();
|
|
}
|
|
|
|
_baseImages.push_back(path_pantsf);
|
|
_baseImages.push_back(path_pantsm);
|
|
|
|
for (const std::filesystem::path &image : _baseImages) {
|
|
if (!std::ifstream(path_stage / image).good()) {
|
|
std::ofstream(path_stage / image);
|
|
}
|
|
}
|
|
|
|
const std::filesystem::path path_chest =
|
|
path_stage / wxString::Format("%s%s.chest", stageName, species)
|
|
.ToStdString();
|
|
const std::filesystem::path path_leg =
|
|
path_stage /
|
|
wxString::Format("%s%s.legs", stageName, species).ToStdString();
|
|
const auto typeChest = magic_enum::enum_name(stage.GetChestType());
|
|
const auto typeLeg = magic_enum::enum_name(stage.GetLegType());
|
|
|
|
const Starbound::Item::Item item_chest(
|
|
wxString::Format("%s%schest", stageName, species).ToStdString(),
|
|
"icons.png:chest", Starbound::Item::Category::Chestwear,
|
|
stage.GetChestDescription(),
|
|
wxString::Format("%s %s", baseShortDescription,
|
|
static_cast<std::string>(typeChest))
|
|
.ToStdString(),
|
|
maleFrames, femaleFrames);
|
|
|
|
const Starbound::Item::Item item_leg(
|
|
wxString::Format("%s%slegs", stageName, species).ToStdString(),
|
|
"icons.png:pants", Starbound::Item::Category::Legwear,
|
|
stage.GetLegDescription(),
|
|
wxString::Format("%s %s", baseShortDescription,
|
|
static_cast<std::string>(typeLeg))
|
|
.ToStdString(),
|
|
Starbound::Item::Frames(path_pantsm),
|
|
Starbound::Item::Frames(path_pantsf));
|
|
|
|
if (!std::ifstream(path_chest).good()) {
|
|
std::ofstream file_chest(path_chest);
|
|
cereal::JSONOutputArchive archive(file_chest);
|
|
cereal::Save(archive, item_chest);
|
|
}
|
|
if (!std::ifstream(path_leg).good()) {
|
|
std::ofstream file_leg(path_leg);
|
|
cereal::JSONOutputArchive archive(file_leg);
|
|
cereal::Save(archive, item_leg);
|
|
}
|
|
}
|
|
|
|
const std::vector<Starpounds::WeightStageSub> subs = stage.GetSubs();
|
|
if (!subs.empty()) {
|
|
for (const Starpounds::WeightStageSub &sub : subs) {
|
|
const std::string subStageName = sub.GetName();
|
|
const std::string stageName =
|
|
(stage.HasID() ? stage.GetName() : "");
|
|
const std::filesystem::path path_subStage =
|
|
path_stage / subStageName;
|
|
|
|
if (!std::filesystem::exists(path_subStage)) {
|
|
std::filesystem::create_directory(path_subStage);
|
|
}
|
|
|
|
for (const std::filesystem::path &image : baseImages) {
|
|
if (!std::ifstream(path_subStage / image).good()) {
|
|
std::ofstream(path_subStage / image);
|
|
}
|
|
}
|
|
|
|
const std::filesystem::path path_chest =
|
|
path_subStage.string() +
|
|
wxString::Format("/%s%s%s.chest", stageName, subStageName,
|
|
species)
|
|
.ToStdString();
|
|
|
|
const Starbound::Item::Item item_chest(
|
|
wxString::Format("%s%s%schest", stageName, subStageName,
|
|
species)
|
|
.ToStdString(),
|
|
"icons.png:chest", Starbound::Item::Category::Chestwear,
|
|
sub.GetChestDescription(),
|
|
wxString::Format(
|
|
"%s %s %s", sub.GetFriendlyName(), baseShortDescription,
|
|
static_cast<std::string>(
|
|
magic_enum::enum_name(stage.GetChestType())))
|
|
.ToStdString(),
|
|
maleFrames, femaleFrames);
|
|
|
|
if (!std::ifstream(path_chest).good()) {
|
|
std::ofstream file_chest(path_chest);
|
|
cereal::JSONOutputArchive archive(file_chest);
|
|
cereal::Save(archive, item_chest);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < m_notebook->GetPageCount(); i++) {
|
|
m_notebook->GetPage(i)->Enable(true);
|
|
}
|
|
|
|
SetStatusText("[INFO]: Done, your mod has been successfully created!");
|
|
wxEndBusyCursor();
|
|
}
|
|
} // namespace SpeciesGen
|