Expose new settings, add tabs to settings editor

This commit is contained in:
GriffinR 2023-12-08 15:13:21 -05:00
parent 61b1789d4b
commit 571ff8e328
6 changed files with 1174 additions and 714 deletions

File diff suppressed because it is too large Load diff

View file

@ -67,6 +67,8 @@ public:
this->theme = "default"; this->theme = "default";
this->textEditorOpenFolder = ""; this->textEditorOpenFolder = "";
this->textEditorGotoLine = ""; this->textEditorGotoLine = "";
this->paletteEditorBitDepth = 24;
this->projectSettingsTab = 0;
} }
void setRecentProject(QString project); void setRecentProject(QString project);
void setReopenOnLaunch(bool enabled); void setReopenOnLaunch(bool enabled);
@ -91,6 +93,7 @@ public:
void setTextEditorOpenFolder(const QString &command); void setTextEditorOpenFolder(const QString &command);
void setTextEditorGotoLine(const QString &command); void setTextEditorGotoLine(const QString &command);
void setPaletteEditorBitDepth(int bitDepth); void setPaletteEditorBitDepth(int bitDepth);
void setProjectSettingsTab(int tab);
QString getRecentProject(); QString getRecentProject();
bool getReopenOnLaunch(); bool getReopenOnLaunch();
MapSortOrder getMapSortOrder(); MapSortOrder getMapSortOrder();
@ -114,6 +117,7 @@ public:
QString getTextEditorOpenFolder(); QString getTextEditorOpenFolder();
QString getTextEditorGotoLine(); QString getTextEditorGotoLine();
int getPaletteEditorBitDepth(); int getPaletteEditorBitDepth();
int getProjectSettingsTab();
protected: protected:
virtual QString getConfigFilepath() override; virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override; virtual void parseConfigKeyValue(QString key, QString value) override;
@ -155,6 +159,7 @@ private:
QString textEditorOpenFolder; QString textEditorOpenFolder;
QString textEditorGotoLine; QString textEditorGotoLine;
int paletteEditorBitDepth; int paletteEditorBitDepth;
int projectSettingsTab;
}; };
extern PorymapConfig porymapConfig; extern PorymapConfig porymapConfig;

View file

@ -48,13 +48,16 @@ private:
void createProjectPathsTable(); void createProjectPathsTable();
QString chooseProjectFile(const QString &defaultFilepath); QString chooseProjectFile(const QString &defaultFilepath);
void choosePrefabsFile();
void chooseImageFile(QLineEdit * filepathEdit);
void chooseFile(QLineEdit * filepathEdit, const QString &description, const QString &extensions);
private slots: private slots:
void dialogButtonClicked(QAbstractButton *button); void dialogButtonClicked(QAbstractButton *button);
void choosePrefabsFileClicked(bool);
void importDefaultPrefabsClicked(bool); void importDefaultPrefabsClicked(bool);
void updateAttributeLimits(const QString &attrSize); void updateAttributeLimits(const QString &attrSize);
void markEdited(); void markEdited();
void on_mainTabs_tabBarClicked(int index);
}; };
#endif // PROJECTSETTINGSEDITOR_H #endif // PROJECTSETTINGSEDITOR_H

View file

@ -64,4 +64,15 @@ signals:
void textChanged(const QString &text); void textChanged(const QString &text);
}; };
class UIntHexSpinBox : public UIntSpinBox
{
Q_OBJECT
public:
UIntHexSpinBox(QWidget *parent = nullptr) : UIntSpinBox(parent) {
this->setPrefix("0x");
this->setDisplayIntegerBase(16);
this->setHasPadding(true);
}
};
#endif // UINTSPINBOX_H #endif // UINTSPINBOX_H

View file

@ -269,6 +269,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
if (this->paletteEditorBitDepth != 15 && this->paletteEditorBitDepth != 24){ if (this->paletteEditorBitDepth != 15 && this->paletteEditorBitDepth != 24){
this->paletteEditorBitDepth = 24; this->paletteEditorBitDepth = 24;
} }
} else if (key == "project_settings_tab") {
this->projectSettingsTab = getConfigInteger(key, value, 0);
} else { } else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
} }
@ -294,7 +296,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
map.insert("project_settings_editor_state", stringFromByteArray(this->projectSettingsEditorState)); map.insert("project_settings_editor_state", stringFromByteArray(this->projectSettingsEditorState));
map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry)); map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry));
map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState)); map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState));
map.insert("collision_opacity", QString("%1").arg(this->collisionOpacity)); map.insert("collision_opacity", QString::number(this->collisionOpacity));
map.insert("collision_zoom", QString::number(this->collisionZoom)); map.insert("collision_zoom", QString::number(this->collisionZoom));
map.insert("metatiles_zoom", QString::number(this->metatilesZoom)); map.insert("metatiles_zoom", QString::number(this->metatilesZoom));
map.insert("show_player_view", this->showPlayerView ? "1" : "0"); map.insert("show_player_view", this->showPlayerView ? "1" : "0");
@ -306,7 +308,8 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
map.insert("theme", this->theme); map.insert("theme", this->theme);
map.insert("text_editor_open_directory", this->textEditorOpenFolder); map.insert("text_editor_open_directory", this->textEditorOpenFolder);
map.insert("text_editor_goto_line", this->textEditorGotoLine); map.insert("text_editor_goto_line", this->textEditorGotoLine);
map.insert("palette_editor_bit_depth", QString("%1").arg(this->paletteEditorBitDepth)); map.insert("palette_editor_bit_depth", QString::number(this->paletteEditorBitDepth));
map.insert("project_settings_tab", QString::number(this->projectSettingsTab));
return map; return map;
} }
@ -451,6 +454,11 @@ void PorymapConfig::setPaletteEditorBitDepth(int bitDepth) {
this->save(); this->save();
} }
void PorymapConfig::setProjectSettingsTab(int tab) {
this->projectSettingsTab = tab;
this->save();
}
QString PorymapConfig::getRecentProject() { QString PorymapConfig::getRecentProject() {
return this->recentProject; return this->recentProject;
} }
@ -575,6 +583,10 @@ int PorymapConfig::getPaletteEditorBitDepth() {
return this->paletteEditorBitDepth; return this->paletteEditorBitDepth;
} }
int PorymapConfig::getProjectSettingsTab() {
return this->projectSettingsTab;
}
const QStringList ProjectConfig::versionStrings = { const QStringList ProjectConfig::versionStrings = {
"pokeruby", "pokeruby",
"pokefirered", "pokefirered",
@ -713,10 +725,10 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
} else if (key == "collision_sheet_path") { } else if (key == "collision_sheet_path") {
this->collisionSheetPath = value; this->collisionSheetPath = value;
} else if (key == "collision_sheet_width") { } else if (key == "collision_sheet_width") {
// Max for these two keys is if a user specifies blocks with 1 bit for metatile ID and 15 bits for collision or elevation // TODO: Update max once Block layout can be edited (0x7FFF for 15 bits)
this->collisionSheetWidth = getConfigInteger(key, value, 1, 0x7FFF, 2); this->collisionSheetWidth = getConfigInteger(key, value, 1, 4, 2);
} else if (key == "collision_sheet_height") { } else if (key == "collision_sheet_height") {
this->collisionSheetHeight = getConfigInteger(key, value, 1, 0x7FFF, 16); this->collisionSheetHeight = getConfigInteger(key, value, 1, 16, 16);
} else { } else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
} }

View file

@ -33,7 +33,6 @@ ProjectSettingsEditor::~ProjectSettingsEditor()
void ProjectSettingsEditor::connectSignals() { void ProjectSettingsEditor::connectSignals() {
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked);
connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked);
connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked); connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked);
connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults); connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults);
connect(ui->comboBox_AttributesSize, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::updateAttributeLimits); connect(ui->comboBox_AttributesSize, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::updateAttributeLimits);
@ -45,6 +44,15 @@ void ProjectSettingsEditor::connectSignals() {
this->setBorderMetatilesUi(customSize); this->setBorderMetatilesUi(customSize);
}); });
// Connect file selection buttons
connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, [this](bool) { this->choosePrefabsFile(); });
connect(ui->button_CollisionGraphics, &QAbstractButton::clicked, [this](bool) { this->chooseImageFile(ui->lineEdit_CollisionGraphics); });
connect(ui->button_ObjectsIcon, &QAbstractButton::clicked, [this](bool) { this->chooseImageFile(ui->lineEdit_ObjectsIcon); });
connect(ui->button_WarpsIcon, &QAbstractButton::clicked, [this](bool) { this->chooseImageFile(ui->lineEdit_WarpsIcon); });
connect(ui->button_TriggersIcon, &QAbstractButton::clicked, [this](bool) { this->chooseImageFile(ui->lineEdit_TriggersIcon); });
connect(ui->button_BGsIcon, &QAbstractButton::clicked, [this](bool) { this->chooseImageFile(ui->lineEdit_BGsIcon); });
connect(ui->button_HealspotsIcon, &QAbstractButton::clicked, [this](bool) { this->chooseImageFile(ui->lineEdit_HealspotsIcon); });
// Record that there are unsaved changes if any of the settings are modified // Record that there are unsaved changes if any of the settings are modified
for (auto combo : ui->centralwidget->findChildren<NoScrollComboBox *>()) for (auto combo : ui->centralwidget->findChildren<NoScrollComboBox *>())
connect(combo, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); connect(combo, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited);
@ -64,6 +72,11 @@ void ProjectSettingsEditor::markEdited() {
this->hasUnsavedChanges = true; this->hasUnsavedChanges = true;
} }
// Remember the current settings tab for future sessions
void ProjectSettingsEditor::on_mainTabs_tabBarClicked(int index) {
porymapConfig.setProjectSettingsTab(index);
}
void ProjectSettingsEditor::initUi() { void ProjectSettingsEditor::initUi() {
// Populate combo boxes // Populate combo boxes
if (project) ui->comboBox_DefaultPrimaryTileset->addItems(project->primaryTilesetLabels); if (project) ui->comboBox_DefaultPrimaryTileset->addItems(project->primaryTilesetLabels);
@ -71,6 +84,9 @@ void ProjectSettingsEditor::initUi() {
ui->comboBox_BaseGameVersion->addItems(ProjectConfig::versionStrings); ui->comboBox_BaseGameVersion->addItems(ProjectConfig::versionStrings);
ui->comboBox_AttributesSize->addItems({"1", "2", "4"}); ui->comboBox_AttributesSize->addItems({"1", "2", "4"});
// Select tab from last session
ui->mainTabs->setCurrentIndex(porymapConfig.getProjectSettingsTab());
// Validate that the border metatiles text is a comma-separated list of metatile values // Validate that the border metatiles text is a comma-separated list of metatile values
const QString regex_Hex = "(0[xX])?[A-Fa-f0-9]+"; const QString regex_Hex = "(0[xX])?[A-Fa-f0-9]+";
static const QRegularExpression expression(QString("^(%1,)*%1$").arg(regex_Hex)); // Comma-separated list of hex values static const QRegularExpression expression(QString("^(%1,)*%1$").arg(regex_Hex)); // Comma-separated list of hex values
@ -84,7 +100,10 @@ void ProjectSettingsEditor::initUi() {
ui->spinBox_BorderMetatile2->setMaximum(maxMetatileId); ui->spinBox_BorderMetatile2->setMaximum(maxMetatileId);
ui->spinBox_BorderMetatile3->setMaximum(maxMetatileId); ui->spinBox_BorderMetatile3->setMaximum(maxMetatileId);
ui->spinBox_BorderMetatile4->setMaximum(maxMetatileId); ui->spinBox_BorderMetatile4->setMaximum(maxMetatileId);
ui->spinBox_Elevation->setMaximum(15); ui->spinBox_Elevation->setMaximum(Project::getMaxElevation());
ui->spinBox_Collision->setMaximum(Project::getMaxCollision());
ui->spinBox_MaxElevation->setMaximum(Project::getMaxElevation());
ui->spinBox_MaxCollision->setMaximum(Project::getMaxCollision());
} }
void ProjectSettingsEditor::setBorderMetatilesUi(bool customSize) { void ProjectSettingsEditor::setBorderMetatilesUi(bool customSize) {
@ -227,7 +246,10 @@ void ProjectSettingsEditor::refresh() {
// Set spin box values // Set spin box values
ui->spinBox_Elevation->setValue(projectConfig.getNewMapElevation()); ui->spinBox_Elevation->setValue(projectConfig.getNewMapElevation());
ui->spinBox_Collision->setValue(projectConfig.getNewMapCollision());
ui->spinBox_FillMetatile->setValue(projectConfig.getNewMapMetatileId()); ui->spinBox_FillMetatile->setValue(projectConfig.getNewMapMetatileId());
ui->spinBox_MaxElevation->setValue(projectConfig.getCollisionSheetHeight() - 1);
ui->spinBox_MaxCollision->setValue(projectConfig.getCollisionSheetWidth() - 1);
ui->spinBox_BehaviorMask->setValue(projectConfig.getMetatileBehaviorMask()); ui->spinBox_BehaviorMask->setValue(projectConfig.getMetatileBehaviorMask());
ui->spinBox_EncounterTypeMask->setValue(projectConfig.getMetatileEncounterTypeMask()); ui->spinBox_EncounterTypeMask->setValue(projectConfig.getMetatileEncounterTypeMask());
ui->spinBox_LayerTypeMask->setValue(projectConfig.getMetatileLayerTypeMask()); ui->spinBox_LayerTypeMask->setValue(projectConfig.getMetatileLayerTypeMask());
@ -240,6 +262,12 @@ void ProjectSettingsEditor::refresh() {
// Set line edit texts // Set line edit texts
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath());
ui->lineEdit_CollisionGraphics->setText(projectConfig.getCollisionSheetPath());
ui->lineEdit_ObjectsIcon->setText(projectConfig.getEventIconPath(Event::Group::Object));
ui->lineEdit_WarpsIcon->setText(projectConfig.getEventIconPath(Event::Group::Warp));
ui->lineEdit_TriggersIcon->setText(projectConfig.getEventIconPath(Event::Group::Coord));
ui->lineEdit_BGsIcon->setText(projectConfig.getEventIconPath(Event::Group::Bg));
ui->lineEdit_HealspotsIcon->setText(projectConfig.getEventIconPath(Event::Group::Heal));
for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>()) for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>())
lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true)); lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true));
@ -253,10 +281,13 @@ void ProjectSettingsEditor::save() {
// Prevent a call to save() for each of the config settings // Prevent a call to save() for each of the config settings
projectConfig.setSaveDisabled(true); projectConfig.setSaveDisabled(true);
// Save combo box settings
projectConfig.setDefaultPrimaryTileset(ui->comboBox_DefaultPrimaryTileset->currentText()); projectConfig.setDefaultPrimaryTileset(ui->comboBox_DefaultPrimaryTileset->currentText());
projectConfig.setDefaultSecondaryTileset(ui->comboBox_DefaultSecondaryTileset->currentText()); projectConfig.setDefaultSecondaryTileset(ui->comboBox_DefaultSecondaryTileset->currentText());
projectConfig.setBaseGameVersion(projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText())); projectConfig.setBaseGameVersion(projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText()));
projectConfig.setMetatileAttributesSize(ui->comboBox_AttributesSize->currentText().toInt()); projectConfig.setMetatileAttributesSize(ui->comboBox_AttributesSize->currentText().toInt());
// Save check box settings
projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked()); projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked());
userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked()); userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked());
projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked()); projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked());
@ -272,15 +303,30 @@ void ProjectSettingsEditor::save() {
projectConfig.setUseCustomBorderSize(ui->checkBox_EnableCustomBorderSize->isChecked()); projectConfig.setUseCustomBorderSize(ui->checkBox_EnableCustomBorderSize->isChecked());
projectConfig.setTilesetsHaveCallback(ui->checkBox_OutputCallback->isChecked()); projectConfig.setTilesetsHaveCallback(ui->checkBox_OutputCallback->isChecked());
projectConfig.setTilesetsHaveIsCompressed(ui->checkBox_OutputIsCompressed->isChecked()); projectConfig.setTilesetsHaveIsCompressed(ui->checkBox_OutputIsCompressed->isChecked());
// Save spin box settings
projectConfig.setNewMapElevation(ui->spinBox_Elevation->value()); projectConfig.setNewMapElevation(ui->spinBox_Elevation->value());
projectConfig.setNewMapCollision(ui->spinBox_Collision->value());
projectConfig.setNewMapMetatileId(ui->spinBox_FillMetatile->value()); projectConfig.setNewMapMetatileId(ui->spinBox_FillMetatile->value());
projectConfig.setCollisionSheetHeight(ui->spinBox_MaxElevation->value() + 1);
projectConfig.setCollisionSheetWidth(ui->spinBox_MaxCollision->value() + 1);
projectConfig.setMetatileBehaviorMask(ui->spinBox_BehaviorMask->value()); projectConfig.setMetatileBehaviorMask(ui->spinBox_BehaviorMask->value());
projectConfig.setMetatileTerrainTypeMask(ui->spinBox_TerrainTypeMask->value()); projectConfig.setMetatileTerrainTypeMask(ui->spinBox_TerrainTypeMask->value());
projectConfig.setMetatileEncounterTypeMask(ui->spinBox_EncounterTypeMask->value()); projectConfig.setMetatileEncounterTypeMask(ui->spinBox_EncounterTypeMask->value());
projectConfig.setMetatileLayerTypeMask(ui->spinBox_LayerTypeMask->value()); projectConfig.setMetatileLayerTypeMask(ui->spinBox_LayerTypeMask->value());
// Save line edit settings
projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text()); projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text());
projectConfig.setCollisionSheetPath(ui->lineEdit_CollisionGraphics->text());
projectConfig.setEventIconPath(Event::Group::Object, ui->lineEdit_ObjectsIcon->text());
projectConfig.setEventIconPath(Event::Group::Warp, ui->lineEdit_WarpsIcon->text());
projectConfig.setEventIconPath(Event::Group::Coord, ui->lineEdit_TriggersIcon->text());
projectConfig.setEventIconPath(Event::Group::Bg, ui->lineEdit_BGsIcon->text());
projectConfig.setEventIconPath(Event::Group::Heal, ui->lineEdit_HealspotsIcon->text());
for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>()) for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>())
projectConfig.setFilePath(lineEdit->objectName(), lineEdit->text()); projectConfig.setFilePath(lineEdit->objectName(), lineEdit->text());
// Save border metatile IDs
projectConfig.setNewMapBorderMetatileIds(this->getBorderMetatileIds(ui->checkBox_EnableCustomBorderSize->isChecked())); projectConfig.setNewMapBorderMetatileIds(this->getBorderMetatileIds(ui->checkBox_EnableCustomBorderSize->isChecked()));
projectConfig.setSaveDisabled(false); projectConfig.setSaveDisabled(false);
@ -293,14 +339,16 @@ void ProjectSettingsEditor::save() {
} }
// Pick a file to use as the new prefabs file path // Pick a file to use as the new prefabs file path
void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { void ProjectSettingsEditor::choosePrefabsFile() {
QString startPath = this->project->importExportPath; this->chooseFile(ui->lineEdit_PrefabsPath, "Choose Prefabs File", "JSON Files (*.json)");
QFileInfo fileInfo(ui->lineEdit_PrefabsPath->text()); }
if (fileInfo.exists() && fileInfo.isFile() && fileInfo.suffix() == "json") {
// Current setting is a valid JSON file. Start the file dialog there void ProjectSettingsEditor::chooseImageFile(QLineEdit * filepathEdit) {
startPath = fileInfo.dir().absolutePath(); this->chooseFile(filepathEdit, "Choose Image File", "Images (*.png *.jpg)");
} }
QString filepath = QFileDialog::getOpenFileName(this, "Choose Prefabs File", startPath, "JSON Files (*.json)");
void ProjectSettingsEditor::chooseFile(QLineEdit * filepathEdit, const QString &description, const QString &extensions) {
QString filepath = QFileDialog::getOpenFileName(this, description, this->project->importExportPath, extensions);
if (filepath.isEmpty()) if (filepath.isEmpty())
return; return;
this->project->setImportExportPath(filepath); this->project->setImportExportPath(filepath);
@ -308,7 +356,7 @@ void ProjectSettingsEditor::choosePrefabsFileClicked(bool) {
// Display relative path if this file is in the project folder // Display relative path if this file is in the project folder
if (filepath.startsWith(this->baseDir)) if (filepath.startsWith(this->baseDir))
filepath.remove(0, this->baseDir.length()); filepath.remove(0, this->baseDir.length());
ui->lineEdit_PrefabsPath->setText(filepath); if (filepathEdit) filepathEdit->setText(filepath);
this->hasUnsavedChanges = true; this->hasUnsavedChanges = true;
} }