diff --git a/include/ui/metatilelayersitem.h b/include/ui/metatilelayersitem.h index ceea3ff8..61eae902 100644 --- a/include/ui/metatilelayersitem.h +++ b/include/ui/metatilelayersitem.h @@ -22,9 +22,14 @@ private: Tileset *secondaryTileset; QPoint prevChangedPos; QPoint prevHoveredPos; + QPoint getBoundedPos(const QPointF &); + void requestTileChange(const QPoint &pos); + void requestPaletteChange(const QPoint &pos); + void updateSelection(); signals: - void tileChanged(int, int); + void tileChanged(const QPoint &pos); + void paletteChanged(const QPoint &pos); void selectedTilesChanged(QPoint, int, int); void hoveredTileChanged(const Tile &tile); void hoveredTileCleared(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 1266da14..4d8c5b95 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -69,7 +69,6 @@ private slots: void onHoveredTileChanged(const Tile&); void onHoveredTileChanged(uint16_t); void onHoveredTileCleared(); - void onMetatileLayerTileChanged(int, int); void onMetatileLayerSelectionChanged(QPoint, int, int); void onPaletteEditorChangedPaletteColor(); @@ -138,6 +137,7 @@ private: void setRawAttributesVisible(bool visible); void refreshTileFlips(); void refreshPaletteId(); + void paintSelectedLayerTiles(const QPoint &pos, bool paletteOnly = false); Ui::TilesetEditor *ui; History metatileHistory; diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp index 223c6f1a..9c95f6ef 100644 --- a/src/ui/metatilelayersitem.cpp +++ b/src/ui/metatilelayersitem.cpp @@ -76,34 +76,49 @@ void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondary this->clearLastHoveredCoords(); } +// We request our current selection to be painted, +// this class doesn't handle changing the metatile data. +void MetatileLayersItem::requestTileChange(const QPoint &pos) { + this->prevChangedPos = pos; + this->clearLastHoveredCoords(); + emit this->tileChanged(pos); +} +void MetatileLayersItem::requestPaletteChange(const QPoint &pos) { + this->prevChangedPos = pos; + this->clearLastHoveredCoords(); + emit this->paletteChanged(pos); +} + +void MetatileLayersItem::updateSelection() { + QPoint selectionOrigin = this->getSelectionStart(); + QSize dimensions = this->getSelectionDimensions(); + emit this->selectedTilesChanged(selectionOrigin, dimensions.width(), dimensions.height()); + this->drawSelection(); +} + void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons() & Qt::RightButton) { SelectablePixmapItem::mousePressEvent(event); - QPoint selectionOrigin = this->getSelectionStart(); - QSize dimensions = this->getSelectionDimensions(); - emit this->selectedTilesChanged(selectionOrigin, dimensions.width(), dimensions.height()); - this->drawSelection(); + updateSelection(); + } else if (event->modifiers() & Qt::ControlModifier) { + requestPaletteChange(getBoundedPos(event->pos())); } else { - const QPoint pos = this->getBoundedPos(event->pos()); - this->prevChangedPos = pos; - this->clearLastHoveredCoords(); - emit this->tileChanged(pos.x(), pos.y()); + requestTileChange(getBoundedPos(event->pos())); } } void MetatileLayersItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons() & Qt::RightButton) { SelectablePixmapItem::mouseMoveEvent(event); - QPoint selectionOrigin = this->getSelectionStart(); - QSize dimensions = this->getSelectionDimensions(); - emit this->selectedTilesChanged(selectionOrigin, dimensions.width(), dimensions.height()); - this->drawSelection(); + updateSelection(); } else { const QPoint pos = this->getBoundedPos(event->pos()); - if (prevChangedPos != pos) { - this->prevChangedPos = pos; - this->clearLastHoveredCoords(); - emit this->tileChanged(pos.x(), pos.y()); + if (this->prevChangedPos != pos) { + if (event->modifiers() & Qt::ControlModifier) { + requestPaletteChange(pos); + } else { + requestTileChange(pos); + } } } } @@ -111,11 +126,10 @@ void MetatileLayersItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { void MetatileLayersItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons() & Qt::RightButton) { SelectablePixmapItem::mouseReleaseEvent(event); - QPoint selectionOrigin = this->getSelectionStart(); - QSize dimensions = this->getSelectionDimensions(); - emit this->selectedTilesChanged(selectionOrigin, dimensions.width(), dimensions.height()); + updateSelection(); } + // Clear selection rectangle this->draw(); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index c5407930..adc3f280 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -237,15 +237,11 @@ void TilesetEditor::initMetatileSelector() void TilesetEditor::initMetatileLayersItem() { Metatile *metatile = Tileset::getMetatile(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset); this->metatileLayersItem = new MetatileLayersItem(metatile, this->primaryTileset, this->secondaryTileset); - connect(this->metatileLayersItem, &MetatileLayersItem::tileChanged, - this, &TilesetEditor::onMetatileLayerTileChanged); - connect(this->metatileLayersItem, &MetatileLayersItem::selectedTilesChanged, - this, &TilesetEditor::onMetatileLayerSelectionChanged); - connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileChanged, [this](const Tile &tile) { - onHoveredTileChanged(tile); - }); - connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileCleared, - this, &TilesetEditor::onHoveredTileCleared); + connect(this->metatileLayersItem, &MetatileLayersItem::tileChanged, [this](const QPoint &pos) { paintSelectedLayerTiles(pos); }); + connect(this->metatileLayersItem, &MetatileLayersItem::paletteChanged, [this](const QPoint &pos) { paintSelectedLayerTiles(pos, true); }); + connect(this->metatileLayersItem, &MetatileLayersItem::selectedTilesChanged, this, &TilesetEditor::onMetatileLayerSelectionChanged); + connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileChanged, [this](const Tile &tile) { onHoveredTileChanged(tile); }); + connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileCleared, this, &TilesetEditor::onHoveredTileCleared); bool showGrid = porymapConfig.showTilesetEditorLayerGrid; this->ui->actionLayer_Grid->setChecked(showGrid); @@ -470,7 +466,7 @@ void TilesetEditor::onHoveredTileCleared() { this->ui->statusbar->clearMessage(); } -void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { +void TilesetEditor::paintSelectedLayerTiles(const QPoint &pos, bool paletteOnly) { static const QList tileCoords = QList{ QPoint(0, 0), QPoint(1, 0), @@ -485,6 +481,7 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { QPoint(4, 1), QPoint(5, 1), }; + bool changed = false; Metatile *prevMetatile = new Metatile(*this->metatile); QSize dimensions = this->tileSelector->getSelectionDimensions(); QList tiles = this->tileSelector->getSelectedTiles(); @@ -492,23 +489,35 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { int maxTileIndex = projectConfig.getNumTilesInMetatile(); for (int j = 0; j < dimensions.height(); j++) { for (int i = 0; i < dimensions.width(); i++) { - int tileIndex = ((x + i) / 2 * 4) + ((y + j) * 2) + ((x + i) % 2); - if (tileIndex < maxTileIndex - && tileCoords.at(tileIndex).x() >= x - && tileCoords.at(tileIndex).y() >= y){ - Tile &tile = this->metatile->tiles[tileIndex]; - tile.tileId = tiles.at(selectedTileIndex).tileId; - tile.xflip = tiles.at(selectedTileIndex).xflip; - tile.yflip = tiles.at(selectedTileIndex).yflip; - tile.palette = tiles.at(selectedTileIndex).palette; - if (this->tileSelector->showUnused) { - this->tileSelector->usedTiles[tile.tileId] += 1; - this->tileSelector->usedTiles[prevMetatile->tiles[tileIndex].tileId] -= 1; + int tileIndex = ((pos.x() + i) / 2 * 4) + ((pos.y() + j) * 2) + ((pos.x() + i) % 2); + QPoint tilePos = tileCoords.at(tileIndex); + if (tileIndex < maxTileIndex && tilePos.x() >= pos.x() && tilePos.y() >= pos.y()){ + Tile &destTile = this->metatile->tiles[tileIndex]; + const Tile srcTile = tiles.at(selectedTileIndex); + if (paletteOnly) { + if (srcTile.palette == destTile.palette) + continue; // Ignore no-ops for edit history + destTile.palette = srcTile.palette; + } else { + if (srcTile == destTile) + continue; // Ignore no-ops for edit history + + // Update tile usage count + if (this->tileSelector->showUnused && destTile.tileId != srcTile.tileId) { + this->tileSelector->usedTiles[srcTile.tileId] += 1; + this->tileSelector->usedTiles[destTile.tileId] -= 1; + } + destTile = srcTile; } + changed = true; } selectedTileIndex++; } } + if (!changed) { + delete prevMetatile; + return; + } this->metatileSelector->drawSelectedMetatile(); this->metatileLayersItem->draw();