diff --git a/include/core/tile.h b/include/core/tile.h index 585ceebf..a13e9fc7 100644 --- a/include/core/tile.h +++ b/include/core/tile.h @@ -29,6 +29,7 @@ public: static constexpr int pixelWidth() { return 8; } static constexpr int pixelHeight() { return 8; } static constexpr QSize pixelSize() { return QSize(Tile::pixelWidth(), Tile::pixelHeight()); } + static constexpr int sizeInBytes() { return sizeof(uint16_t); } }; inline bool operator==(const Tile &a, const Tile &b) { diff --git a/include/core/tileset.h b/include/core/tileset.h index 80fef000..d592a429 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -30,10 +30,8 @@ public: QString metatile_attrs_label; QString metatile_attrs_path; QString tilesImagePath; - QImage tilesImage; QStringList palettePaths; - QList tiles; QHash metatileLabels; QList> palettes; QList> palettePreviews; @@ -77,15 +75,24 @@ public: void setMetatiles(const QList &metatiles); void addMetatile(Metatile* metatile); - QList metatiles() const { return m_metatiles; } + const QList &metatiles() const { return m_metatiles; } Metatile* metatileAt(unsigned int i) const { return m_metatiles.at(i); } void clearMetatiles(); void resizeMetatiles(int newNumMetatiles); int numMetatiles() const { return m_metatiles.length(); } + int maxMetatiles() const; + + int numTiles() const { return m_tiles.length(); } + int maxTiles() const; + + QImage tileImage(uint16_t tileId) const { return m_tiles.value(Tile::getIndexInTileset(tileId)); } private: QList m_metatiles; + + QList m_tiles; + QImage m_tilesImage; bool m_hasUnsavedTilesImage = false; }; diff --git a/include/project.h b/include/project.h index c5ef6338..3dbae1c5 100644 --- a/include/project.h +++ b/include/project.h @@ -255,10 +255,13 @@ public: static QMargins getMetatileViewDistance(); static int getNumTilesPrimary() { return num_tiles_primary; } static int getNumTilesTotal() { return num_tiles_total; } + static int getNumTilesSecondary() { return getNumTilesTotal() - getNumTilesPrimary(); } static int getNumMetatilesPrimary() { return num_metatiles_primary; } static int getNumMetatilesTotal() { return Block::getMaxMetatileId() + 1; } + static int getNumMetatilesSecondary() { return getNumMetatilesTotal() - getNumMetatilesPrimary(); } static int getNumPalettesPrimary(){ return num_pals_primary; } static int getNumPalettesTotal() { return num_pals_total; } + static int getNumPalettesSecondary() { return getNumPalettesTotal() - getNumPalettesPrimary(); } static QString getEmptyMapsecName(); static QString getMapGroupPrefix(); diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h index bed655e1..2b1982ba 100644 --- a/include/ui/tileseteditortileselector.h +++ b/include/ui/tileseteditortileselector.h @@ -43,6 +43,7 @@ protected: void hoverLeaveEvent(QGraphicsSceneHoverEvent*); private: + QPixmap basePixmap; bool externalSelection; int externalSelectionWidth; int externalSelectionHeight; @@ -63,7 +64,7 @@ private: QList getCurPaletteTable(); QList buildSelectedTiles(int, int, QList); QImage buildImage(int tileIdStart, int numTiles); - + void updateBasePixmap(); void drawUnused(); signals: diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index ca0650fe..729c3334 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -20,15 +20,15 @@ Tileset::Tileset(const Tileset &other) metatile_attrs_label(other.metatile_attrs_label), metatile_attrs_path(other.metatile_attrs_path), tilesImagePath(other.tilesImagePath), - tilesImage(other.tilesImage.copy()), palettePaths(other.palettePaths), metatileLabels(other.metatileLabels), palettes(other.palettes), palettePreviews(other.palettePreviews), + m_tilesImage(other.m_tilesImage.copy()), m_hasUnsavedTilesImage(other.m_hasUnsavedTilesImage) { - for (auto tile : other.tiles) { - tiles.append(tile.copy()); + for (auto tile : other.m_tiles) { + m_tiles.append(tile.copy()); } for (auto *metatile : other.m_metatiles) { @@ -46,15 +46,15 @@ Tileset &Tileset::operator=(const Tileset &other) { metatile_attrs_label = other.metatile_attrs_label; metatile_attrs_path = other.metatile_attrs_path; tilesImagePath = other.tilesImagePath; - tilesImage = other.tilesImage.copy(); + m_tilesImage = other.m_tilesImage.copy(); palettePaths = other.palettePaths; metatileLabels = other.metatileLabels; palettes = other.palettes; palettePreviews = other.palettePreviews; - tiles.clear(); - for (auto tile : other.tiles) { - tiles.append(tile.copy()); + m_tiles.clear(); + for (auto tile : other.m_tiles) { + m_tiles.append(tile.copy()); } clearMetatiles(); @@ -94,6 +94,14 @@ void Tileset::resizeMetatiles(int newNumMetatiles) { } } +int Tileset::maxMetatiles() const { + return this->is_secondary ? Project::getNumMetatilesSecondary() : Project::getNumMetatilesPrimary(); +} + +int Tileset::maxTiles() const { + return this->is_secondary ? Project::getNumTilesSecondary() : Project::getNumTilesPrimary(); +} + Tileset* Tileset::getTileTileset(int tileId, Tileset *primaryTileset, Tileset *secondaryTileset) { if (tileId < Project::getNumTilesPrimary()) { return primaryTileset; @@ -407,17 +415,25 @@ QHash Tileset::getHeaderMemberMap(bool usingAsm) bool Tileset::loadMetatiles() { clearMetatiles(); - QFile metatiles_file(this->metatiles_path); - if (!metatiles_file.open(QIODevice::ReadOnly)) { - logError(QString("Could not open '%1' for reading: %2").arg(this->metatiles_path).arg(metatiles_file.errorString())); + QFile file(this->metatiles_path); + if (!file.open(QIODevice::ReadOnly)) { + logError(QString("Could not open '%1' for reading: %2").arg(this->metatiles_path).arg(file.errorString())); return false; } - QByteArray data = metatiles_file.readAll(); + QByteArray data = file.readAll(); int tilesPerMetatile = projectConfig.getNumTilesInMetatile(); - int bytesPerMetatile = 2 * tilesPerMetatile; - int num_metatiles = data.length() / bytesPerMetatile; - for (int i = 0; i < num_metatiles; i++) { + int bytesPerMetatile = Tile::sizeInBytes() * tilesPerMetatile; + int numMetatiles = data.length() / bytesPerMetatile; + if (numMetatiles > maxMetatiles()) { + logWarn(QString("%1 metatile count %2 exceeds limit of %3. Additional metatiles will be ignored.") + .arg(this->name) + .arg(numMetatiles) + .arg(maxMetatiles())); + numMetatiles = maxMetatiles(); + } + + for (int i = 0; i < numMetatiles; i++) { auto metatile = new Metatile; int index = i * bytesPerMetatile; for (int j = 0; j < tilesPerMetatile; j++) { @@ -431,9 +447,9 @@ bool Tileset::loadMetatiles() { } bool Tileset::saveMetatiles() { - QFile metatiles_file(this->metatiles_path); - if (!metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - logError(QString("Could not open '%1' for writing: %2").arg(this->metatiles_path).arg(metatiles_file.errorString())); + QFile file(this->metatiles_path); + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + logError(QString("Could not open '%1' for writing: %2").arg(this->metatiles_path).arg(file.errorString())); return false; } @@ -441,31 +457,40 @@ bool Tileset::saveMetatiles() { int numTiles = projectConfig.getNumTilesInMetatile(); for (const auto &metatile : m_metatiles) { for (int i = 0; i < numTiles; i++) { - uint16_t tile = metatile->tiles.at(i).rawValue(); + uint16_t tile = metatile->tiles.value(i).rawValue(); data.append(static_cast(tile)); data.append(static_cast(tile >> 8)); } } - metatiles_file.write(data); + file.write(data); return true; } bool Tileset::loadMetatileAttributes() { - QFile attrs_file(this->metatile_attrs_path); - if (!attrs_file.open(QIODevice::ReadOnly)) { - logError(QString("Could not open '%1' for reading: %2").arg(this->metatile_attrs_path).arg(attrs_file.errorString())); + QFile file(this->metatile_attrs_path); + if (!file.open(QIODevice::ReadOnly)) { + logError(QString("Could not open '%1' for reading: %2").arg(this->metatile_attrs_path).arg(file.errorString())); return false; } - QByteArray data = attrs_file.readAll(); + QByteArray data = file.readAll(); int attrSize = projectConfig.metatileAttributesSize; int numMetatiles = m_metatiles.length(); int numMetatileAttrs = data.length() / attrSize; - if (numMetatiles != numMetatileAttrs) { - logWarn(QString("Metatile count %1 does not match metatile attribute count %2 in %3").arg(numMetatiles).arg(numMetatileAttrs).arg(this->name)); + if (numMetatileAttrs > numMetatiles) { + logWarn(QString("%1 metatile attributes count %2 exceeds metatile count of %3. Additional attributes will be ignored.") + .arg(this->name) + .arg(numMetatileAttrs) + .arg(numMetatiles)); + numMetatileAttrs = numMetatiles; + } else if (numMetatileAttrs < numMetatiles) { + logWarn(QString("%1 metatile attributes count %2 is fewer than the metatile count of %3. Missing attributes will default to 0.") + .arg(this->name) + .arg(numMetatileAttrs) + .arg(numMetatiles)); } - for (int i = 0; i < qMin(numMetatiles, numMetatileAttrs); i++) { + for (int i = 0; i < numMetatileAttrs; i++) { uint32_t attributes = 0; for (int j = 0; j < attrSize; j++) attributes |= static_cast(data.at(i * attrSize + j)) << (8 * j); @@ -475,9 +500,9 @@ bool Tileset::loadMetatileAttributes() { } bool Tileset::saveMetatileAttributes() { - QFile attrs_file(this->metatile_attrs_path); - if (!attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - logError(QString("Could not open '%1' for writing: %2").arg(this->metatile_attrs_path).arg(attrs_file.errorString())); + QFile file(this->metatile_attrs_path); + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + logError(QString("Could not open '%1' for writing: %2").arg(this->metatile_attrs_path).arg(file.errorString())); return false; } @@ -487,21 +512,36 @@ bool Tileset::saveMetatileAttributes() { for (int i = 0; i < projectConfig.metatileAttributesSize; i++) data.append(static_cast(attributes >> (8 * i))); } - attrs_file.write(data); + file.write(data); return true; } bool Tileset::loadTilesImage(QImage *importedImage) { QImage image; + bool imported = false; if (importedImage) { image = *importedImage; - m_hasUnsavedTilesImage = true; + imported = true; } else if (QFile::exists(this->tilesImagePath)) { // No image provided, load from file path. image = QImage(this->tilesImagePath).convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither); - } else { - // Use default image + } + + if (image.isNull()) { + logWarn(QString("Failed to load tiles image for %1. Using default tiles image.").arg(this->name)); image = QImage(Tile::pixelWidth(), Tile::pixelHeight(), QImage::Format_Indexed8); + image.fill(0); + } + + // Validate image dimensions + if (image.width() % Tile::pixelWidth() || image.height() % Tile::pixelHeight()) { + logError(QString("%1 tiles image has invalid dimensions %2x%3. Dimensions must be a multiple of %4x%5.") + .arg(this->name) + .arg(image.width()) + .arg(image.height()) + .arg(Tile::pixelWidth()) + .arg(Tile::pixelHeight())); + return false; } // Validate image contains 16 colors. @@ -515,15 +555,31 @@ bool Tileset::loadTilesImage(QImage *importedImage) { } image.setColorTable(colorTable); } + m_tilesImage = image; - QList tiles; + // Cut up the full tiles image into individual tile images. + m_tiles.clear(); for (int y = 0; y < image.height(); y += Tile::pixelHeight()) for (int x = 0; x < image.width(); x += Tile::pixelWidth()) { - QImage tile = image.copy(x, y, Tile::pixelWidth(), Tile::pixelHeight()); - tiles.append(tile); + m_tiles.append(image.copy(x, y, Tile::pixelWidth(), Tile::pixelHeight())); } - this->tilesImage = image; - this->tiles = tiles; + + if (m_tiles.length() > maxTiles()) { + logWarn(QString("%1 tile count of %2 exceeds limit of %3. Additional tiles will not be displayed.") + .arg(this->name) + .arg(m_tiles.length()) + .arg(maxTiles())); + + // Just resize m_tiles so that numTiles() reports the correct tile count. + // We'll leave m_tilesImage alone (it doesn't get displayed, and we don't want to delete the user's image data). + m_tiles = m_tiles.mid(0, maxTiles()); + } + + if (imported) { + // Only set this flag once we've successfully loaded the tiles image. + m_hasUnsavedTilesImage = true; + } + return true; } @@ -533,7 +589,7 @@ bool Tileset::saveTilesImage() { if (!m_hasUnsavedTilesImage) return true; - if (!this->tilesImage.save(this->tilesImagePath, "PNG")) { + if (!m_tilesImage.save(this->tilesImagePath, "PNG")) { logError(QString("Failed to save tiles image '%1'").arg(this->tilesImagePath)); return false; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 36aef9e5..697ce835 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2844,7 +2844,9 @@ void MainWindow::on_actionTileset_Editor_triggered() openSubWindow(this->tilesetEditor); MetatileSelection selection = this->editor->metatile_selector_item->getMetatileSelection(); - this->tilesetEditor->selectMetatile(selection.metatileItems.first().metatileId); + if (!selection.metatileItems.isEmpty()) { + this->tilesetEditor->selectMetatile(selection.metatileItems.first().metatileId); + } } void MainWindow::initTilesetEditor() { diff --git a/src/project.cpp b/src/project.cpp index cc3a567f..2957ca2b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -2461,6 +2461,7 @@ bool Project::readFieldmapMasks() { projectConfig.blockCollisionMask = blockMask; if (readBlockMask(elevationMaskName, &blockMask)) projectConfig.blockElevationMask = blockMask; + Block::setLayout(); // Read RSE metatile attribute masks auto it = defines.find(behaviorMaskName); @@ -3469,7 +3470,6 @@ void Project::applyParsedLimits() { projectConfig.metatileEncounterTypeMask &= maxMask; projectConfig.metatileLayerTypeMask &= maxMask; - Block::setLayout(); Metatile::setLayout(this); Project::num_metatiles_primary = qBound(1, Project::num_metatiles_primary, Block::getMaxMetatileId() + 1); diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index c7b6d386..a1730791 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -546,13 +546,13 @@ int MainWindow::getNumSecondaryTilesetMetatiles() { int MainWindow::getNumPrimaryTilesetTiles() { if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return 0; - return this->editor->layout->tileset_primary->tiles.length(); + return this->editor->layout->tileset_primary->numTiles(); } int MainWindow::getNumSecondaryTilesetTiles() { if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return 0; - return this->editor->layout->tileset_secondary->tiles.length(); + return this->editor->layout->tileset_secondary->numTiles(); } QString MainWindow::getPrimaryTileset() { @@ -797,12 +797,15 @@ void MainWindow::setMetatileTile(int metatileId, int tileIndex, QJSValue tileObj QJSValue MainWindow::getTilePixels(int tileId) { if (tileId < 0 || !this->editor || !this->editor->layout) return QJSValue(); + + const int numPixels = Tile::pixelWidth() * Tile::pixelHeight(); QImage tileImage = getTileImage(tileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); - if (tileImage.isNull() || tileImage.sizeInBytes() < 64) + if (tileImage.isNull() || tileImage.sizeInBytes() < numPixels) return QJSValue(); + const uchar * pixels = tileImage.constBits(); - QJSValue pixelArray = Scripting::getEngine()->newArray(64); - for (int i = 0; i < 64; i++) { + QJSValue pixelArray = Scripting::getEngine()->newArray(numPixels); + for (int i = 0; i < numPixels; i++) { pixelArray.setProperty(i, pixels[i]); } return pixelArray; diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index ef966852..188398bb 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -9,7 +9,7 @@ QImage getCollisionMetatileImage(Block block) { } QImage getCollisionMetatileImage(int collision, int elevation) { - const QImage * image = Editor::collisionIcons.at(collision).at(elevation); + const QImage * image = Editor::collisionIcons.value(collision).value(elevation); return image ? *image : QImage(); } @@ -158,11 +158,7 @@ QImage getMetatileImage( QImage getTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset) { Tileset *tileset = Tileset::getTileTileset(tileId, primaryTileset, secondaryTileset); - int index = Tile::getIndexInTileset(tileId); - if (!tileset) { - return QImage(); - } - return tileset->tiles.value(index, QImage()); + return tileset ? tileset->tileImage(tileId) : QImage(); } QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, const QList &palette) { @@ -170,10 +166,10 @@ QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *se if (tileImage.isNull()) { tileImage = QImage(Tile::pixelWidth(), Tile::pixelHeight(), QImage::Format_RGBA8888); QPainter painter(&tileImage); - painter.fillRect(0, 0, tileImage.width(), tileImage.height(), palette.at(0)); + painter.fillRect(0, 0, tileImage.width(), tileImage.height(), palette.value(0)); } else { for (int i = 0; i < 16; i++) { - tileImage.setColor(i, palette.at(i)); + tileImage.setColor(i, palette.value(i)); } } @@ -245,26 +241,26 @@ QImage getMetatileSheetImage(Tileset *primaryTileset, const QSize &metatileSize, bool useTruePalettes) { - QImage primaryImage = getMetatileSheetImage(primaryTileset, - secondaryTileset, - 0, - primaryTileset ? primaryTileset->numMetatiles()-1 : 0, - numMetatilesWide, - layerOrder, - layerOpacity, - metatileSize, - useTruePalettes); + auto createSheetImage = [=](uint16_t start, Tileset *tileset) { + uint16_t end = start; + if (tileset) { + if (tileset->numMetatiles() == 0) + return QImage(); + end += tileset->numMetatiles() - 1; + } + return getMetatileSheetImage(primaryTileset, + secondaryTileset, + start, + end, + numMetatilesWide, + layerOrder, + layerOpacity, + metatileSize, + useTruePalettes); + }; - uint16_t secondaryMetatileIdStart = Project::getNumMetatilesPrimary(); - QImage secondaryImage = getMetatileSheetImage(primaryTileset, - secondaryTileset, - secondaryMetatileIdStart, - secondaryMetatileIdStart + (secondaryTileset ? secondaryTileset->numMetatiles()-1 : 0), - numMetatilesWide, - layerOrder, - layerOpacity, - metatileSize, - useTruePalettes); + QImage primaryImage = createSheetImage(0, primaryTileset); + QImage secondaryImage = createSheetImage(Project::getNumMetatilesPrimary(), secondaryTileset); QImage image(qMax(primaryImage.width(), secondaryImage.width()), primaryImage.height() + secondaryImage.height(), QImage::Format_RGBA8888); image.fill(getInvalidImageColor()); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index b25130bd..e64a6add 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -783,7 +783,10 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset) { image = image.convertToFormat(QImage::Format::Format_Indexed8, colorTable); } - tileset->loadTilesImage(&image); + if (!tileset->loadTilesImage(&image)) { + RecentErrorMessage::show(QStringLiteral("Failed to import tiles."), this); + return; + } this->refresh(); this->hasUnsavedChanges = true; } diff --git a/src/ui/tileseteditortileselector.cpp b/src/ui/tileseteditortileselector.cpp index 56c65073..31ab088e 100644 --- a/src/ui/tileseteditortileselector.cpp +++ b/src/ui/tileseteditortileselector.cpp @@ -12,53 +12,40 @@ QPoint TilesetEditorTileSelector::getSelectionDimensions() { } } -void TilesetEditorTileSelector::draw() { - if (!this->primaryTileset || !this->secondaryTileset) { - this->setPixmap(QPixmap()); +void TilesetEditorTileSelector::updateBasePixmap() { + if (!this->primaryTileset || !this->secondaryTileset || this->numTilesWide == 0) { + this->basePixmap = QPixmap(); + return; } int totalTiles = Project::getNumTilesTotal(); - int primaryLength = this->primaryTileset->tiles.length(); - int secondaryLength = this->secondaryTileset->tiles.length(); int height = totalTiles / this->numTilesWide; - QList palette = Tileset::getPalette(this->paletteId, this->primaryTileset, this->secondaryTileset, true); QImage image(this->numTilesWide * this->cellWidth, height * this->cellHeight, QImage::Format_RGBA8888); QPainter painter(&image); - for (uint16_t tile = 0; tile < totalTiles; tile++) { - QImage tileImage; - if (tile < primaryLength) { - tileImage = getPalettedTileImage(tile, this->primaryTileset, this->secondaryTileset, this->paletteId, true).scaled(this->cellWidth, this->cellHeight); - } else if (tile < Project::getNumTilesPrimary()) { - tileImage = QImage(this->cellWidth, this->cellHeight, QImage::Format_RGBA8888); - tileImage.fill(palette.at(0)); - } else if (tile < Project::getNumTilesPrimary() + secondaryLength) { - tileImage = getPalettedTileImage(tile, this->primaryTileset, this->secondaryTileset, this->paletteId, true).scaled(this->cellWidth, this->cellHeight); - } else { - tileImage = QImage(this->cellWidth, this->cellHeight, QImage::Format_RGBA8888); - QPainter painter(&tileImage); - painter.fillRect(0, 0, this->cellWidth, this->cellHeight, palette.at(0)); - } - - int y = tile / this->numTilesWide; - int x = tile % this->numTilesWide; - QPoint origin = QPoint(x * this->cellWidth, y * this->cellHeight); - painter.drawImage(origin, tileImage); + for (uint16_t tileId = 0; tileId < totalTiles; tileId++) { + QImage tileImage = getPalettedTileImage(tileId, this->primaryTileset, this->secondaryTileset, this->paletteId, true) + .scaled(this->cellWidth, this->cellHeight); + int x = (tileId % this->numTilesWide) * this->cellWidth; + int y = (tileId / this->numTilesWide) * this->cellHeight; + painter.drawImage(x, y, tileImage); } if (this->showDivider) { - int row = this->primaryTileset->tiles.length() / this->numTilesWide; - if (this->primaryTileset->tiles.length() % this->numTilesWide != 0) { - // Round up height for incomplete last row - row++; - } + 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->setPixmap(QPixmap::fromImage(image)); + this->basePixmap = QPixmap::fromImage(image); +} + +void TilesetEditorTileSelector::draw() { + if (this->basePixmap.isNull()) + updateBasePixmap(); + setPixmap(this->basePixmap); if (!this->externalSelection || (this->externalSelectionWidth == 1 && this->externalSelectionHeight == 1)) { this->drawSelection(); @@ -82,12 +69,14 @@ void TilesetEditorTileSelector::highlight(uint16_t tile) { void TilesetEditorTileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; + this->updateBasePixmap(); this->draw(); } void TilesetEditorTileSelector::setPaletteId(int paletteId) { this->paletteId = paletteId; this->paletteChanged = true; + this->updateBasePixmap(); this->draw(); } @@ -213,7 +202,7 @@ void TilesetEditorTileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { } QPoint TilesetEditorTileSelector::getTileCoords(uint16_t tile) { - if (tile >= Project::getNumTilesTotal()) + if (tile >= Project::getNumTilesTotal() || this->numTilesWide == 0) { // Invalid tile. return QPoint(0, 0); @@ -233,17 +222,20 @@ QImage TilesetEditorTileSelector::buildPrimaryTilesIndexedImage() { if (!this->primaryTileset) return QImage(); - return buildImage(0, this->primaryTileset->tiles.length()); + return buildImage(0, this->primaryTileset->numTiles()); } QImage TilesetEditorTileSelector::buildSecondaryTilesIndexedImage() { if (!this->secondaryTileset) return QImage(); - return buildImage(Project::getNumTilesPrimary(), this->secondaryTileset->tiles.length()); + return buildImage(Project::getNumTilesPrimary(), this->secondaryTileset->numTiles()); } QImage TilesetEditorTileSelector::buildImage(int tileIdStart, int numTiles) { + if (this->numTilesWide == 0) + return QImage(); + int height = qCeil(numTiles / static_cast(this->numTilesWide)); QImage image(this->numTilesWide * Tile::pixelWidth(), height * Tile::pixelHeight(), QImage::Format_RGBA8888); image.fill(0);