Add palette painting to metatile layer painter

This commit is contained in:
GriffinR 2025-07-28 12:12:53 -04:00
parent 9ce865a9c1
commit a88730ee3f
4 changed files with 71 additions and 43 deletions

View File

@ -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();

View File

@ -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<MetatileHistoryItem*> metatileHistory;

View File

@ -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();
}

View File

@ -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<QPoint> tileCoords = QList<QPoint>{
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<Tile> 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();