Fix bounds checking for external tile selections

This commit is contained in:
GriffinR 2025-08-04 13:33:57 -04:00
parent db9ecd744f
commit c1fc2c8201
4 changed files with 42 additions and 22 deletions

View File

@ -743,6 +743,12 @@
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
</property>
</widget>
</item>
<item>

View File

@ -27,7 +27,7 @@ public:
void setPaletteId(int);
void setTileFlips(bool, bool);
QList<Tile> getSelectedTiles();
void setExternalSelection(int, int, QList<Tile>, QList<int>);
void setExternalSelection(int, int, const QList<Tile>&);
QPoint getTileCoordsOnWidget(uint16_t);
QImage buildPrimaryTilesIndexedImage();
QImage buildSecondaryTilesIndexedImage();
@ -49,7 +49,6 @@ private:
int externalSelectionWidth;
int externalSelectionHeight;
QList<Tile> externalSelectedTiles;
QList<int> 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<QRgb> getCurPaletteTable();
QList<Tile> buildSelectedTiles(int, int, QList<Tile>);
QList<Tile> buildSelectedTiles(int, int, const QList<Tile>&);
QImage buildImage(int tileIdStart, int numTiles);
void updateBasePixmap();
void drawUnused();

View File

@ -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<Tile> tiles;
QList<int> 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);

View File

@ -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<Tile> 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<Tile> TilesetEditorTileSelector::getSelectedTiles() {
}
}
QList<Tile> TilesetEditorTileSelector::buildSelectedTiles(int width, int height, QList<Tile> selected) {
QList<Tile> TilesetEditorTileSelector::buildSelectedTiles(int width, int height, const QList<Tile> &selected) {
QList<Tile> tiles;
QList<QList<Tile>> tileMatrix;
for (int j = 0; j < height; j++) {
@ -126,7 +145,7 @@ QList<Tile> TilesetEditorTileSelector::buildSelectedTiles(int width, int height,
QList<Tile> 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<Tile> 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<Tile> TilesetEditorTileSelector::buildSelectedTiles(int width, int height,
return tiles;
}
void TilesetEditorTileSelector::setExternalSelection(int width, int height, QList<Tile> tiles, QList<int> tileIdxs) {
void TilesetEditorTileSelector::setExternalSelection(int width, int height, const QList<Tile> &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();
}