From c1fc2c8201155e92a18f4c1ce60432ede0bd2fae Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 4 Aug 2025 13:33:57 -0400 Subject: [PATCH] Fix bounds checking for external tile selections --- forms/tileseteditor.ui | 6 +++++ include/ui/tileseteditortileselector.h | 5 ++-- src/ui/tileseteditor.cpp | 17 +++++------- src/ui/tileseteditortileselector.cpp | 36 +++++++++++++++++++------- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 5f7a512f..3bab4ca2 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -743,6 +743,12 @@ QFrame::Shape::StyledPanel + + Qt::ScrollBarPolicy::ScrollBarAlwaysOff + + + Qt::ScrollBarPolicy::ScrollBarAlwaysOff + diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h index 8c4367e3..c98239be 100644 --- a/include/ui/tileseteditortileselector.h +++ b/include/ui/tileseteditortileselector.h @@ -27,7 +27,7 @@ public: void setPaletteId(int); void setTileFlips(bool, bool); QList getSelectedTiles(); - void setExternalSelection(int, int, QList, QList); + void setExternalSelection(int, int, const QList&); QPoint getTileCoordsOnWidget(uint16_t); QImage buildPrimaryTilesIndexedImage(); QImage buildSecondaryTilesIndexedImage(); @@ -49,7 +49,6 @@ private: int externalSelectionWidth; int externalSelectionHeight; QList externalSelectedTiles; - QList externalSelectedPos; QPoint prevCellPos = QPoint(-1,-1); Tileset *primaryTileset; @@ -64,7 +63,7 @@ private: uint16_t getTileId(int x, int y); QPoint getTileCoords(uint16_t); QList getCurPaletteTable(); - QList buildSelectedTiles(int, int, QList); + QList buildSelectedTiles(int, int, const QList&); QImage buildImage(int tileIdStart, int numTiles); void updateBasePixmap(); void drawUnused(); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 52eab755..99320682 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -260,6 +260,8 @@ void TilesetEditor::setMetatileLayerOrientation(Qt::Orientation orientation) { ui->graphicsView_selectedTile->setFixedSize(w, h); ui->graphicsView_MetatileLayers->setFixedSize(w, h); + drawSelectedTiles(); + // If the layers are laid out vertically then the orientation is obvious, no need to label them. // This also lets us give the vertical space of the label over to the layer view. ui->label_BottomTop->setVisible(horizontal); @@ -574,19 +576,14 @@ void TilesetEditor::paintSelectedLayerTiles(const QPoint &pos, bool paletteOnly) void TilesetEditor::onMetatileLayerSelectionChanged(const QPoint &selectionOrigin, const QSize &size) { QList tiles; - QList tileIdxs; - int maxTileIndex = projectConfig.getNumTilesInMetatile(); - for (int j = 0; j < size.height(); j++) { - for (int i = 0; i < size.width(); i++) { - int tileIndex = this->metatileLayersItem->posToTileIndex(selectionOrigin.x() + i, selectionOrigin.y() + j); - if (tileIndex < maxTileIndex) { - tiles.append(this->metatile ? this->metatile->tiles.value(tileIndex) : Tile()); - tileIdxs.append(tileIndex); - } + for (int y = 0; y < size.height(); y++) { + for (int x = 0; x < size.width(); x++) { + int tileIndex = this->metatileLayersItem->posToTileIndex(selectionOrigin.x() + x, selectionOrigin.y() + y); + tiles.append(this->metatile ? this->metatile->tiles.value(tileIndex) : Tile()); } } - this->tileSelector->setExternalSelection(size.width(), size.height(), tiles, tileIdxs); + this->tileSelector->setExternalSelection(size.width(), size.height(), tiles); if (size == QSize(1,1)) { setPaletteId(tiles[0].palette); this->tileSelector->highlight(tiles[0].tileId); diff --git a/src/ui/tileseteditortileselector.cpp b/src/ui/tileseteditortileselector.cpp index ec3caa83..e088cdee 100644 --- a/src/ui/tileseteditortileselector.cpp +++ b/src/ui/tileseteditortileselector.cpp @@ -13,8 +13,27 @@ QSize TilesetEditorTileSelector::getSelectionDimensions() const { } void TilesetEditorTileSelector::setMaxSelectionSize(int width, int height) { + width = qMax(1, width); + height = qMax(1, height); SelectablePixmapItem::setMaxSelectionSize(width, height); - updateSelectedTiles(); + if (this->externalSelection) { + if (this->externalSelectionWidth > this->maxSelectionWidth || this->externalSelectionHeight > this->maxSelectionHeight) { + // Crop external selection to new max size. + QList cropped; + int croppedWidth = qMin(this->externalSelectionWidth, this->maxSelectionWidth); + int croppedHeight = qMin(this->externalSelectionHeight, this->maxSelectionHeight); + for (int y = 0; y < croppedHeight; y++) + for (int x = 0; x < croppedWidth; x++) { + int index = y * this->externalSelectionWidth + x; + cropped.append(this->externalSelectedTiles.value(index)); + } + this->externalSelectionWidth = croppedWidth; + this->externalSelectionHeight = croppedHeight; + this->externalSelectedTiles = cropped; + } + } else { + updateSelectedTiles(); + } } void TilesetEditorTileSelector::updateBasePixmap() { @@ -118,7 +137,7 @@ QList TilesetEditorTileSelector::getSelectedTiles() { } } -QList TilesetEditorTileSelector::buildSelectedTiles(int width, int height, QList selected) { +QList TilesetEditorTileSelector::buildSelectedTiles(int width, int height, const QList &selected) { QList tiles; QList> tileMatrix; for (int j = 0; j < height; j++) { @@ -126,7 +145,7 @@ QList TilesetEditorTileSelector::buildSelectedTiles(int width, int height, QList layerRow; for (int i = 0; i < width; i++) { int index = i + j * width; - Tile tile = selected.at(index); + Tile tile = selected.value(index); tile.xflip ^= this->xFlip; tile.yflip ^= this->yFlip; if (this->paletteChanged) @@ -139,7 +158,7 @@ QList TilesetEditorTileSelector::buildSelectedTiles(int width, int height, // If we've completed a layer row, or its the last tile of an incompletely // selected layer, then append the layer row to the full row // If not an external selection, treat the whole row as 1 "layer" - if (i == width - 1 || (this->externalSelection && (this->externalSelectedPos.at(index) % Metatile::tilesPerLayer()) & 1)) { + if (i == width - 1) { row.append(layerRow); layerRow.clear(); } @@ -157,15 +176,14 @@ QList TilesetEditorTileSelector::buildSelectedTiles(int width, int height, return tiles; } -void TilesetEditorTileSelector::setExternalSelection(int width, int height, QList tiles, QList tileIdxs) { +void TilesetEditorTileSelector::setExternalSelection(int width, int height, const QList &tiles) { + width = qBound(1, width, this->maxSelectionWidth); + height = qBound(1, height, this->maxSelectionHeight); this->externalSelection = true; this->paletteChanged = false; this->externalSelectionWidth = width; this->externalSelectionHeight = height; - this->externalSelectedTiles.clear(); - this->externalSelectedTiles.append(tiles); - this->externalSelectedPos.clear(); - this->externalSelectedPos.append(tileIdxs); + this->externalSelectedTiles = tiles.mid(0, width * height); this->draw(); emit selectedTilesChanged(); }