Fix tileset divider drawing, tile usage counts

This commit is contained in:
GriffinR 2025-08-04 14:13:01 -04:00
parent c1fc2c8201
commit b498eeec00
6 changed files with 56 additions and 46 deletions

View File

@ -90,7 +90,11 @@ public:
uint16_t firstMetatileId() const;
uint16_t lastMetatileId() const;
bool contains(uint16_t metatileId) const { return metatileId >= firstMetatileId() && metatileId <= lastMetatileId(); }
bool containsMetatileId(uint16_t metatileId) const { return metatileId >= firstMetatileId() && metatileId <= lastMetatileId(); }
uint16_t firstTileId() const;
uint16_t lastTileId() const;
bool containsTileId(uint16_t tileId) const { return tileId > firstTileId() && tileId <= lastTileId(); }
int numTiles() const { return m_tiles.length(); }
int maxTiles() const;

View File

@ -107,6 +107,14 @@ int Tileset::maxMetatiles() const {
return this->is_secondary ? Project::getNumMetatilesSecondary() : Project::getNumMetatilesPrimary();
}
uint16_t Tileset::firstTileId() const {
return this->is_secondary ? Project::getNumTilesPrimary() : 0;
}
uint16_t Tileset::lastTileId() const {
return qMax(1, firstMetatileId() + m_tiles.length()) - 1;
}
int Tileset::maxTiles() const {
return this->is_secondary ? Project::getNumTilesSecondary() : Project::getNumTilesPrimary();
}
@ -250,8 +258,8 @@ QString Tileset::getMetatileLabelPrefix(const QString &name)
}
bool Tileset::metatileIsValid(uint16_t metatileId, const Tileset *primaryTileset, const Tileset *secondaryTileset) {
return (primaryTileset && primaryTileset->contains(metatileId))
|| (secondaryTileset && secondaryTileset->contains(metatileId));
return (primaryTileset && primaryTileset->containsMetatileId(metatileId))
|| (secondaryTileset && secondaryTileset->containsMetatileId(metatileId));
}
QList<QList<QRgb>> Tileset::getBlockPalettes(const Tileset *primaryTileset, const Tileset *secondaryTileset, bool useTruePalettes) {

View File

@ -204,7 +204,7 @@ uint16_t MetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
if (ok) *ok = true;
int index = y * this->numMetatilesWide + x;
uint16_t metatileId = static_cast<uint16_t>(index);
if (primaryTileset() && primaryTileset()->contains(metatileId)) {
if (primaryTileset() && primaryTileset()->containsMetatileId(metatileId)) {
return metatileId;
}
@ -215,7 +215,7 @@ uint16_t MetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
int numPrimaryRounded = numPrimaryMetatilesRounded();
int firstSecondaryRow = numPrimaryRounded / this->numMetatilesWide;
metatileId = static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimaryRounded);
if (secondaryTileset() && secondaryTileset()->contains(metatileId) && y >= firstSecondaryRow) {
if (secondaryTileset() && secondaryTileset()->containsMetatileId(metatileId) && y >= firstSecondaryRow) {
return metatileId;
}
@ -224,12 +224,12 @@ uint16_t MetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
}
QPoint MetatileSelector::metatileIdToPos(uint16_t metatileId, bool *ok) const {
if (primaryTileset() && primaryTileset()->contains(metatileId)) {
if (primaryTileset() && primaryTileset()->containsMetatileId(metatileId)) {
if (ok) *ok = true;
int index = metatileId;
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
}
if (secondaryTileset() && secondaryTileset()->contains(metatileId)) {
if (secondaryTileset() && secondaryTileset()->containsMetatileId(metatileId)) {
if (ok) *ok = true;
int index = metatileId - Project::getNumMetatilesPrimary() + numPrimaryMetatilesRounded();
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);

View File

@ -794,7 +794,7 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset) {
int numTilesWide = image.width() / Tile::pixelWidth();
int numTilesHigh = image.height() / Tile::pixelHeight();
int totalTiles = numTilesHigh * numTilesWide;
int maxAllowedTiles = primary ? Project::getNumTilesPrimary() : Project::getNumTilesTotal() - Project::getNumTilesPrimary();
int maxAllowedTiles = primary ? Project::getNumTilesPrimary() : Project::getNumTilesSecondary();
if (totalTiles > maxAllowedTiles) {
ErrorMessage::show(QStringLiteral("Failed to import tiles."),
QString("The maximum number of tiles allowed in the %1 tileset is %2, but the provided image contains %3 total tiles.")
@ -899,7 +899,7 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
// Our selected metatile ID may have become invalid. Make sure it's in-bounds.
uint16_t metatileId = this->metatileSelector->getSelectedMetatileId();
Tileset *tileset = Tileset::getMetatileTileset(metatileId, this->primaryTileset, this->secondaryTileset);
if (tileset && !tileset->contains(metatileId)) {
if (tileset && !tileset->containsMetatileId(metatileId)) {
this->metatileSelector->select(qBound(tileset->firstMetatileId(), metatileId, tileset->lastMetatileId()));
}
@ -1233,31 +1233,25 @@ void TilesetEditor::countTileUsage() {
this->tileSelector->usedTiles.resize(Project::getNumTilesTotal());
this->tileSelector->usedTiles.fill(0);
// Count usage of our primary tileset's tiles in the secondary tilesets it gets paired with.
QSet<QString> tilesetNames = this->project->getPairedTilesetLabels(this->primaryTileset);
for (const auto &tilesetName : tilesetNames) {
Tileset *tileset = this->project->getTileset(tilesetName);
if (!tileset) continue;
for (const auto &metatile : tileset->metatiles()) {
for (const auto &tile : metatile->tiles) {
if (tile.tileId < Project::getNumTilesPrimary())
this->tileSelector->usedTiles[tile.tileId]++;
auto countTilesetTileUsage = [this](Tileset *searchTileset) {
// Count usage of our search tileset's tiles (in itself, and in any tilesets it gets paired with).
QSet<QString> tilesetNames = this->project->getPairedTilesetLabels(searchTileset);
tilesetNames.insert(searchTileset->name);
for (const auto &tilesetName : tilesetNames) {
Tileset *tileset = this->project->getTileset(tilesetName);
if (!tileset) continue;
for (const auto &metatile : tileset->metatiles()) {
for (const auto &tile : metatile->tiles) {
if (searchTileset->containsTileId(tile.tileId)) {
this->tileSelector->usedTiles[tile.tileId]++;
}
}
}
}
}
};
// Count usage of our secondary tileset's tiles in the primary tilesets it gets paired with.
tilesetNames = this->project->getPairedTilesetLabels(this->secondaryTileset);
for (const auto &tilesetName : tilesetNames) {
Tileset *tileset = this->project->getTileset(tilesetName);
if (!tileset) continue;
for (const auto &metatile : tileset->metatiles()) {
for (const auto &tile : metatile->tiles) {
if (tile.tileId >= Project::getNumTilesPrimary())
this->tileSelector->usedTiles[tile.tileId]++;
}
}
}
countTilesetTileUsage(this->primaryTileset);
countTilesetTileUsage(this->secondaryTileset);
}
void TilesetEditor::on_copyButton_MetatileLabel_clicked() {
@ -1396,9 +1390,9 @@ void TilesetEditor::applyMetatileSwapToLayouts(uint16_t metatileIdA, uint16_t me
// Get which tilesets our swapped metatiles belong to.
auto addSourceTileset = [this](uint16_t metatileId, TilesetPair *tilesets) {
if (this->primaryTileset->contains(metatileId)) {
if (this->primaryTileset->containsMetatileId(metatileId)) {
tilesets->primary = this->primaryTileset;
} else if (this->secondaryTileset->contains(metatileId)) {
} else if (this->secondaryTileset->containsMetatileId(metatileId)) {
tilesets->secondary = this->secondaryTileset;
} else {
// Invalid metatile, shouldn't happen

View File

@ -205,7 +205,7 @@ uint16_t TilesetEditorMetatileSelector::posToMetatileId(int x, int y, bool *ok)
if (ok) *ok = true;
int index = y * this->numMetatilesWide + x;
uint16_t metatileId = static_cast<uint16_t>(index);
if (this->primaryTileset && this->primaryTileset->contains(metatileId)) {
if (this->primaryTileset && this->primaryTileset->containsMetatileId(metatileId)) {
return metatileId;
}
@ -216,7 +216,7 @@ uint16_t TilesetEditorMetatileSelector::posToMetatileId(int x, int y, bool *ok)
int numPrimaryRounded = numPrimaryMetatilesRounded();
int firstSecondaryRow = numPrimaryRounded / this->numMetatilesWide;
metatileId = static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimaryRounded);
if (this->secondaryTileset && this->secondaryTileset->contains(metatileId) && y >= firstSecondaryRow) {
if (this->secondaryTileset && this->secondaryTileset->containsMetatileId(metatileId) && y >= firstSecondaryRow) {
return metatileId;
}
@ -225,12 +225,12 @@ uint16_t TilesetEditorMetatileSelector::posToMetatileId(int x, int y, bool *ok)
}
QPoint TilesetEditorMetatileSelector::metatileIdToPos(uint16_t metatileId, bool *ok) const {
if (this->primaryTileset && this->primaryTileset->contains(metatileId)) {
if (this->primaryTileset && this->primaryTileset->containsMetatileId(metatileId)) {
if (ok) *ok = true;
int index = metatileId;
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
}
if (this->secondaryTileset && this->secondaryTileset->contains(metatileId)) {
if (this->secondaryTileset && this->secondaryTileset->containsMetatileId(metatileId)) {
if (ok) *ok = true;
int index = metatileId - Project::getNumMetatilesPrimary() + numPrimaryMetatilesRounded();
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);

View File

@ -54,22 +54,26 @@ void TilesetEditorTileSelector::updateBasePixmap() {
int y = (tileId / this->numTilesWide) * this->cellHeight;
painter.drawImage(x, y, tileImage);
}
if (this->showDivider) {
int row = Util::roundUpToMultiple(Project::getNumTilesPrimary(), this->numTilesWide) / this->numTilesWide;
const int y = row * this->cellHeight;
painter.setPen(Qt::white);
painter.drawLine(0, y, this->numTilesWide * this->cellWidth, y);
}
painter.end();
this->basePixmap = QPixmap::fromImage(image);
}
void TilesetEditorTileSelector::draw() {
if (this->basePixmap.isNull())
updateBasePixmap();
setPixmap(this->basePixmap);
QPixmap pixmap = this->basePixmap;
if (this->showDivider) {
QPainter painter(&pixmap);
int row = Util::roundUpToMultiple(Project::getNumTilesPrimary(), this->numTilesWide) / this->numTilesWide;
const int y = row * this->cellHeight;
painter.setPen(Qt::white);
painter.drawLine(0, y, this->numTilesWide * this->cellWidth, y);
}
setPixmap(pixmap);
if (!this->externalSelection || (this->externalSelectionWidth == 1 && this->externalSelectionHeight == 1)) {
this->drawSelection();