diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index cb49c992..1ff9d0fb 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -6,12 +6,12 @@ 0 0 - 727 - 700 + 733 + 784 - Qt::ClickFocus + Qt::FocusPolicy::ClickFocus Tileset Editor @@ -21,7 +21,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal false @@ -34,10 +34,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain @@ -58,15 +58,15 @@ true - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop 0 0 - 223 - 593 + 239 + 659 @@ -88,17 +88,17 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::Vertical + Qt::Orientation::Vertical @@ -121,7 +121,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -129,10 +129,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised @@ -162,14 +162,14 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised - QLayout::SetMinimumSize + QLayout::SizeConstraint::SetMinimumSize 0 @@ -195,6 +195,70 @@ false + + + + true + + + + + + + + 0 + 0 + + + + + 185 + 0 + + + + + + + + Metatile Label (Optional) + + + + + + + Bottom/Top + + + + + + + Terrain Type + + + + + + + Layer Type + + + + + + + + 0 + 0 + + + + QComboBox::InsertPolicy::NoInsert + + + @@ -216,10 +280,10 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff @@ -236,15 +300,18 @@ - - + + - Qt::Vertical + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Maximum - 20 - 1 + 10 + 20 @@ -262,14 +329,28 @@ - - + + - Metatile Label (Optional) + Metatile Behavior - + + + + Raw Attributes Value + + + + + + + Encounter Type + + + + <html><head/><body><p>Copies the full metatile label to the clipboard.</p></body></html> @@ -283,92 +364,21 @@ - - - - - 0 - 0 - - - - - 185 - 0 - - - - - - - - - 0 - 0 - - - - QComboBox::InsertPolicy::NoInsert - - - - - - - Layer Type - - - - - - - true - - - - - - - Metatile Behavior - - - - - + + - Qt::Horizontal - - - QSizePolicy::Maximum + Qt::Orientation::Vertical - 10 - 20 + 20 + 1 - - - - Encounter Type - - - - - - - Terrain Type - - - - - - - Bottom/Top - - + + @@ -408,7 +418,7 @@ - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight @@ -432,10 +442,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Fixed + QSizePolicy::Policy::Fixed @@ -460,10 +470,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain @@ -506,13 +516,13 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff @@ -522,7 +532,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -544,15 +554,15 @@ true - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop 0 0 - 455 - 232 + 445 + 237 @@ -571,17 +581,17 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::Vertical + Qt::Orientation::Vertical @@ -598,7 +608,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -613,8 +623,8 @@ 0 0 - 727 - 22 + 733 + 37 @@ -657,6 +667,7 @@ + @@ -817,6 +828,14 @@ Show Tileset Divider + + + true + + + Show Raw Metatile Attributes + + @@ -829,6 +848,16 @@ QGraphicsView
mapview.h
+ + UIntSpinBox + QAbstractSpinBox +
uintspinbox.h
+
+ + UIntHexSpinBox + UIntSpinBox +
uintspinbox.h
+
diff --git a/include/config.h b/include/config.h index 6661d5a6..0786c761 100644 --- a/include/config.h +++ b/include/config.h @@ -72,6 +72,7 @@ public: this->showTilesetEditorMetatileGrid = false; this->showTilesetEditorLayerGrid = true; this->showTilesetEditorDivider = false; + this->showTilesetEditorRawAttributes = false; this->monitorFiles = true; this->tilesetCheckerboardFill = true; this->newMapHeaderSectionExpanded = false; @@ -132,6 +133,7 @@ public: bool showTilesetEditorMetatileGrid; bool showTilesetEditorLayerGrid; bool showTilesetEditorDivider; + bool showTilesetEditorRawAttributes; bool monitorFiles; bool tilesetCheckerboardFill; bool newMapHeaderSectionExpanded; diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 31dc20db..d659390a 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -97,8 +97,6 @@ private slots: void on_lineEdit_metatileLabel_editingFinished(); - void on_comboBox_layerType_activated(int arg1); - void on_actionExport_Primary_Tiles_Image_triggered(); void on_actionExport_Secondary_Tiles_Image_triggered(); void on_actionExport_Primary_Metatiles_Image_triggered(); @@ -116,7 +114,7 @@ private slots: void on_horizontalSlider_TilesZoom_valueChanged(int value); private: - void setAttributesUi(); + void initAttributesUi(); void initMetatileSelector(); void initTileSelector(); void initSelectedTileItem(); @@ -143,7 +141,14 @@ private: void commitMetatileChange(Metatile * prevMetatile); void commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel); uint32_t attributeNameToValue(Metatile::Attr attribute, const QString &text, bool *ok); - void setAttributeFromComboBox(Metatile::Attr attribute, NoScrollComboBox *combo); + void commitAttributeFromComboBox(Metatile::Attr attribute, NoScrollComboBox *combo); + void onRawAttributesEdited(); + void refreshMetatileAttributes(); + void commitMetatileBehavior(); + void commitEncounterType(); + void commitTerrainType(); + void commitLayerType(); + void setRawAttributesVisible(bool visible); Ui::TilesetEditor *ui; History metatileHistory; diff --git a/src/config.cpp b/src/config.cpp index e193df7a..62ab31f3 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -388,6 +388,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->showTilesetEditorLayerGrid = getConfigBool(key, value); } else if (key == "show_tileset_editor_divider") { this->showTilesetEditorDivider = getConfigBool(key, value); + } else if (key == "show_tileset_editor_raw_attributes") { + this->showTilesetEditorRawAttributes = getConfigBool(key, value); } else if (key == "monitor_files") { this->monitorFiles = getConfigBool(key, value); } else if (key == "tileset_checkerboard_fill") { @@ -497,6 +499,7 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("show_tileset_editor_metatile_grid", this->showTilesetEditorMetatileGrid ? "1" : "0"); map.insert("show_tileset_editor_layer_grid", this->showTilesetEditorLayerGrid ? "1" : "0"); map.insert("show_tileset_editor_divider", this->showTilesetEditorDivider ? "1" : "0"); + map.insert("show_tileset_editor_raw_attributes", this->showTilesetEditorRawAttributes ? "1" : "0"); map.insert("monitor_files", this->monitorFiles ? "1" : "0"); map.insert("tileset_checkerboard_fill", this->tilesetCheckerboardFill ? "1" : "0"); map.insert("new_map_header_section_expanded", this->newMapHeaderSectionExpanded ? "1" : "0"); diff --git a/src/core/metatile.cpp b/src/core/metatile.cpp index a0d4e9fb..073fd867 100644 --- a/src/core/metatile.cpp +++ b/src/core/metatile.cpp @@ -10,11 +10,11 @@ static const QMap attributePackersFRLG = { {Metatile::Attr::TerrainType, BitPacker(0x00003E00) }, {Metatile::Attr::EncounterType, BitPacker(0x07000000) }, {Metatile::Attr::LayerType, BitPacker(0x60000000) }, - //{Metatile::Attr::Unused, BitPacker(0x98FFC000) }, + {Metatile::Attr::Unused, BitPacker(0x98FFC000) }, }; static const QMap attributePackersRSE = { {Metatile::Attr::Behavior, BitPacker(0x00FF) }, - //{Metatile::Attr::Unused, BitPacker(0x0F00) }, + {Metatile::Attr::Unused, BitPacker(0x0F00) }, {Metatile::Attr::LayerType, BitPacker(0xF000) }, }; diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 7bf684d5..ebc466ce 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -32,6 +32,8 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent) this->paletteId = ui->spinBox_paletteSelector->value(); ui->actionShow_Tileset_Divider->setChecked(porymapConfig.showTilesetEditorDivider); + ui->actionShow_Raw_Metatile_Attributes->setChecked(porymapConfig.showTilesetEditorRawAttributes); + ui->spinBox_paletteSelector->setMinimum(0); ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1); @@ -43,18 +45,7 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent) connect(filter, &ActiveWindowFilter::activated, this, &TilesetEditor::onWindowActivated); this->installEventFilter(filter); - // Update the metatile's attributes values when the attribute combo boxes are edited. - connect(ui->comboBox_metatileBehaviors->lineEdit(), &QLineEdit::editingFinished, [this] { - setAttributeFromComboBox(Metatile::Attr::Behavior, ui->comboBox_metatileBehaviors); - }); - connect(ui->comboBox_encounterType->lineEdit(), &QLineEdit::editingFinished, [this] { - setAttributeFromComboBox(Metatile::Attr::EncounterType, ui->comboBox_encounterType); - }); - connect(ui->comboBox_terrainType->lineEdit(), &QLineEdit::editingFinished, [this] { - setAttributeFromComboBox(Metatile::Attr::TerrainType, ui->comboBox_terrainType); - }); - - setAttributesUi(); + initAttributesUi(); initMetatileSelector(); initMetatileLayersItem(); initTileSelector(); @@ -131,7 +122,18 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi this->initMetatileHistory(); } -void TilesetEditor::setAttributesUi() { +void TilesetEditor::initAttributesUi() { + // Update the metatile's attributes values when the attribute combo boxes are edited. + // We avoid using the 'currentTextChanged' signal here, we want to know when we can clean up the input field and commit changes. + connect(ui->comboBox_metatileBehaviors->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitMetatileBehavior); + connect(ui->comboBox_encounterType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitEncounterType); + connect(ui->comboBox_terrainType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitTerrainType); + connect(ui->comboBox_layerType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitLayerType); + connect(ui->comboBox_metatileBehaviors, &QComboBox::activated, this, &TilesetEditor::commitMetatileBehavior); + connect(ui->comboBox_encounterType, &QComboBox::activated, this, &TilesetEditor::commitEncounterType); + connect(ui->comboBox_terrainType, &QComboBox::activated, this, &TilesetEditor::commitTerrainType); + connect(ui->comboBox_layerType, &QComboBox::activated, this, &TilesetEditor::commitLayerType); + // Behavior if (projectConfig.metatileBehaviorMask) { for (auto i = project->metatileBehaviorMapInverse.constBegin(); i != project->metatileBehaviorMapInverse.constEnd(); i++) { @@ -184,9 +186,22 @@ void TilesetEditor::setAttributesUi() { this->ui->label_layerType->setVisible(false); this->ui->label_BottomTop->setText("Bottom/Middle/Top"); } + + // Raw attributes value + ui->spinBox_rawAttributesValue->setMaximum(Metatile::getMaxAttributesMask()); + setRawAttributesVisible(ui->actionShow_Raw_Metatile_Attributes->isChecked()); + connect(ui->spinBox_rawAttributesValue, &UIntHexSpinBox::editingFinished, this, &TilesetEditor::onRawAttributesEdited); + connect(ui->actionShow_Raw_Metatile_Attributes, &QAction::toggled, this, &TilesetEditor::setRawAttributesVisible); + this->ui->frame_Properties->adjustSize(); } +void TilesetEditor::setRawAttributesVisible(bool visible) { + porymapConfig.showTilesetEditorRawAttributes = visible; + ui->label_rawAttributesValue->setVisible(visible); + ui->spinBox_rawAttributesValue->setVisible(visible); +} + void TilesetEditor::initMetatileSelector() { this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->layout); @@ -421,10 +436,7 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->ui->lineEdit_metatileLabel->setText(labels.owned); this->ui->lineEdit_metatileLabel->setPlaceholderText(labels.shared); - this->ui->comboBox_metatileBehaviors->setHexItem(this->metatile->behavior()); - this->ui->comboBox_layerType->setHexItem(this->metatile->layerType()); - this->ui->comboBox_encounterType->setHexItem(this->metatile->encounterType()); - this->ui->comboBox_terrainType->setHexItem(this->metatile->terrainType()); + refreshMetatileAttributes(); } void TilesetEditor::queueMetatileReload(uint16_t metatileId) { @@ -581,16 +593,6 @@ void TilesetEditor::commitMetatileChange(Metatile * prevMetatile) this->commitMetatileAndLabelChange(prevMetatile, this->ui->lineEdit_metatileLabel->text()); } -void TilesetEditor::on_comboBox_layerType_activated(int layerType) -{ - if (this->metatile) { - Metatile *prevMetatile = new Metatile(*this->metatile); - this->metatile->setLayerType(layerType); - this->commitMetatileChange(prevMetatile); - this->metatileSelector->drawSelectedMetatile(); // Changing the layer type can affect how fully transparent metatiles appear - } -} - uint32_t TilesetEditor::attributeNameToValue(Metatile::Attr attribute, const QString &text, bool *ok) { if (ok) *ok = true; if (attribute == Metatile::Attr::Behavior) { @@ -605,11 +607,15 @@ uint32_t TilesetEditor::attributeNameToValue(Metatile::Attr attribute, const QSt for (auto i = project->terrainTypeToName.constBegin(); i != project->terrainTypeToName.constEnd(); i++) { if (i.value() == text) return i.key(); } + } else if (attribute == Metatile::Attr::LayerType) { + // The layer type text is not editable, it uses special display names. Just get the index of the display name. + int i = ui->comboBox_layerType->findText(text); + if (i >= 0) return i; } return text.toUInt(ok, 0); } -void TilesetEditor::setAttributeFromComboBox(Metatile::Attr attribute, NoScrollComboBox *combo) { +void TilesetEditor::commitAttributeFromComboBox(Metatile::Attr attribute, NoScrollComboBox *combo) { if (!this->metatile) return; @@ -619,6 +625,10 @@ void TilesetEditor::setAttributeFromComboBox(Metatile::Attr attribute, NoScrollC Metatile *prevMetatile = new Metatile(*this->metatile); this->metatile->setAttribute(attribute, newValue); this->commitMetatileChange(prevMetatile); + + // When an attribute changes we also need to update the raw value display. + const QSignalBlocker b_RawAttributesValue(ui->spinBox_rawAttributesValue); + ui->spinBox_rawAttributesValue->setValue(this->metatile->getAttributes()); } // Update the text in the combo box to reflect the final value. @@ -627,6 +637,50 @@ void TilesetEditor::setAttributeFromComboBox(Metatile::Attr attribute, NoScrollC combo->setHexItem(this->metatile->getAttribute(attribute)); } +void TilesetEditor::onRawAttributesEdited() { + uint32_t newAttributes = ui->spinBox_rawAttributesValue->value(); + if (newAttributes != this->metatile->getAttributes()) { + Metatile *prevMetatile = new Metatile(*this->metatile); + this->metatile->setAttributes(newAttributes); + this->commitMetatileChange(prevMetatile); + } + refreshMetatileAttributes(); +} + +void TilesetEditor::refreshMetatileAttributes() { + if (!this->metatile) return; + + const QSignalBlocker b_MetatileBehaviors(ui->comboBox_metatileBehaviors); + const QSignalBlocker b_EncounterType(ui->comboBox_encounterType); + const QSignalBlocker b_TerrainType(ui->comboBox_terrainType); + const QSignalBlocker b_LayerType(ui->comboBox_layerType); + const QSignalBlocker b_RawAttributesValue(ui->spinBox_rawAttributesValue); + ui->comboBox_metatileBehaviors->setHexItem(this->metatile->behavior()); + ui->comboBox_encounterType->setHexItem(this->metatile->encounterType()); + ui->comboBox_terrainType->setHexItem(this->metatile->terrainType()); + ui->comboBox_layerType->setHexItem(this->metatile->layerType()); + ui->spinBox_rawAttributesValue->setValue(this->metatile->getAttributes()); + + this->metatileSelector->drawSelectedMetatile(); +} + +void TilesetEditor::commitMetatileBehavior() { + commitAttributeFromComboBox(Metatile::Attr::Behavior, ui->comboBox_metatileBehaviors); +} + +void TilesetEditor::commitEncounterType() { + commitAttributeFromComboBox(Metatile::Attr::EncounterType, ui->comboBox_encounterType); +} + +void TilesetEditor::commitTerrainType() { + commitAttributeFromComboBox(Metatile::Attr::TerrainType, ui->comboBox_terrainType); +}; + +void TilesetEditor::commitLayerType() { + commitAttributeFromComboBox(Metatile::Attr::LayerType, ui->comboBox_layerType); + this->metatileSelector->drawSelectedMetatile(); // Changing the layer type can affect how fully transparent metatiles appear +} + void TilesetEditor::on_actionSave_Tileset_triggered() { // Need this temporary flag to stop selection resetting after saving.