Merge pull request #761 from GriffinRichards/tileset-editor

Add some Tileset Editor requests
This commit is contained in:
GriffinR
2025-08-06 10:31:50 -04:00
committed by GitHub
38 changed files with 1461 additions and 677 deletions

View File

@@ -43,7 +43,8 @@ public:
bool getSingleTileMode() const { return m_singleTileMode; }
void updateLocation(int x, int y);
void updateSelectionSize(int width, int height);
void updateSelectionSize(const QSize &size);
void updateSelectionSize(int width, int height) { updateSelectionSize(QSize(width, height)); }
private:
const QSize m_tileSize;

View File

@@ -61,17 +61,17 @@ public:
void magicFill(
int initialX,
int initialY,
QPoint selectionDimensions,
QList<MetatileSelectionItem> selectedMetatiles,
QList<CollisionSelectionItem> selectedCollisions,
const QSize &selectionDimensions,
const QList <MetatileSelectionItem> &selectedMetatiles,
const QList <CollisionSelectionItem> &selectedCollisions,
bool fromScriptCall = false);
void floodFill(int x, int y, bool fromScriptCall = false);
void floodFill(int x, int y, uint16_t metatileId, bool fromScriptCall = false);
void floodFill(int initialX,
int initialY,
QPoint selectionDimensions,
QList<MetatileSelectionItem> selectedMetatiles,
QList<CollisionSelectionItem> selectedCollisions,
const QSize &selectionDimensions,
const QList<MetatileSelectionItem> &selectedMetatiles,
const QList<CollisionSelectionItem> &selectedCollisions,
bool fromScriptCall = false);
void floodFillSmartPath(int initialX, int initialY, bool fromScriptCall = false);

View File

@@ -9,23 +9,40 @@
class MetatileLayersItem: public SelectablePixmapItem {
Q_OBJECT
public:
MetatileLayersItem(Metatile *metatile, Tileset *primaryTileset, Tileset *secondaryTileset);
MetatileLayersItem(Metatile *metatile,
Tileset *primaryTileset,
Tileset *secondaryTileset,
Qt::Orientation orientation = Qt::Horizontal);
void draw();
void setTilesets(Tileset*, Tileset*);
void setMetatile(Metatile*);
void clearLastModifiedCoords();
void clearLastHoveredCoords();
QPoint tileIndexToPos(int index) const { return this->tilePositions.value(index); }
int posToTileIndex(const QPoint &pos) const { return this->tilePositions.indexOf(pos); }
int posToTileIndex(int x, int y) const { return posToTileIndex(QPoint(x, y)); }
void setOrientation(Qt::Orientation orientation);
bool showGrid;
private:
Metatile* metatile;
Tileset *primaryTileset;
Tileset *secondaryTileset;
Qt::Orientation orientation;
QPoint prevChangedPos;
QPoint prevHoveredPos;
QList<QPoint> tilePositions;
QPoint getBoundedPos(const QPointF &);
void updateSelection();
void hover(const QPoint &pos);
signals:
void tileChanged(int, int);
void selectedTilesChanged(QPoint, int, int);
void tileChanged(const QPoint &pos);
void paletteChanged(const QPoint &pos);
void selectedTilesChanged(const QPoint &pos, const QSize &dimensions);
void hoveredTileChanged(const Tile &tile);
void hoveredTileCleared();
protected:

View File

@@ -22,7 +22,7 @@ struct CollisionSelectionItem
struct MetatileSelection
{
QPoint dimensions;
QSize dimensions;
bool hasCollision;
QList<MetatileSelectionItem> metatileItems;
QList<CollisionSelectionItem> collisionItems;
@@ -43,7 +43,7 @@ public:
setAcceptHoverEvents(true);
}
QPoint getSelectionDimensions() const override;
QSize getSelectionDimensions() const override;
void draw() override;
void refresh();

View File

@@ -44,7 +44,7 @@ private:
Tileset *secondaryTileset;
QList<ColorInputWidget*> colorInputs;
QList<History<PaletteHistoryItem*>> palettesHistory;
QMap<int, History<PaletteHistoryItem*>> palettesHistory;
QMap<int,QSet<int>> unusedColorCache;
QPointer<PaletteColorSearch> colorSearchWindow;
@@ -53,6 +53,7 @@ private:
void refreshPaletteId();
void commitEditHistory();
void commitEditHistory(int paletteId);
void updateEditHistoryActions();
void restoreWindowState();
void invalidateCache();
void closeEvent(QCloseEvent*);

View File

@@ -19,9 +19,15 @@ public:
selectionOffsetX(0),
selectionOffsetY(0)
{}
virtual QPoint getSelectionDimensions() const;
virtual QSize getSelectionDimensions() const { return QSize(abs(this->selectionOffsetX) + 1, abs(this->selectionOffsetY) + 1); }
virtual void draw() = 0;
virtual void setMaxSelectionSize(const QSize &size) { setMaxSelectionSize(size.width(), size.height()); }
virtual void setMaxSelectionSize(int width, int height);
QSize maxSelectionSize() { return QSize(this->maxSelectionWidth, this->maxSelectionHeight); }
void setSelectionStyle(Qt::PenStyle style);
protected:
int cellWidth;
int cellHeight;
@@ -33,17 +39,28 @@ protected:
int selectionOffsetY;
QPoint getSelectionStart();
void select(int x, int y, int width = 0, int height = 0);
void select(const QPoint &pos, const QSize &size = QSize(0,0)) { select(pos.x(), pos.y(), size.width(), size.height()); }
void updateSelection(int, int);
QPoint getCellPos(QPointF);
void select(const QPoint &pos, const QSize &size = QSize(1,1));
void select(int x, int y, int width = 1, int height = 1) { select(QPoint(x, y), QSize(width, height)); }
void updateSelection(const QPoint &pos);
QPoint getCellPos(const QPointF &itemPos);
int getBoundedWidth(int width) const { return qBound(1, width, this->maxSelectionWidth); }
int getBoundedHeight(int height) const { return qBound(1, height, this->maxSelectionHeight); }
virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override;
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent*) override;
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override;
virtual void drawSelectionRect(const QPoint &, const QSize &, Qt::PenStyle style = Qt::SolidLine);
virtual void drawSelection();
virtual int cellsWide() const { return this->cellWidth ? (pixmap().width() / this->cellWidth) : 0; }
virtual int cellsTall() const { return this->cellHeight ? (pixmap().height() / this->cellHeight) : 0; }
signals:
void selectionChanged(int, int, int, int);
void selectionChanged(const QPoint&, const QSize&);
private:
QPoint prevCellPos = QPoint(-1,-1);
Qt::PenStyle selectionStyle = Qt::SolidLine;
void setSelection(const QPoint &pos, const QSize &size);
};
#endif // SELECTABLEPIXMAPITEM_H

View File

@@ -20,6 +20,7 @@ class TilesetEditor;
class MetatileHistoryItem {
public:
MetatileHistoryItem() {};
MetatileHistoryItem(uint16_t metatileId, Metatile *prevMetatile, Metatile *newMetatile, QString prevLabel, QString newLabel) {
this->metatileId = metatileId;
this->prevMetatile = prevMetatile;
@@ -27,15 +28,24 @@ public:
this->prevLabel = prevLabel;
this->newLabel = newLabel;
}
MetatileHistoryItem(uint16_t metatileIdA, uint16_t metatileIdB) {
this->metatileId = metatileIdA;
this->swapMetatileId = metatileIdB;
this->isSwap = true;
}
~MetatileHistoryItem() {
delete this->prevMetatile;
delete this->newMetatile;
}
uint16_t metatileId;
Metatile *prevMetatile;
Metatile *newMetatile;
uint16_t metatileId = 0;
Metatile *prevMetatile = nullptr;
Metatile *newMetatile = nullptr;
QString prevLabel;
QString newLabel;
uint16_t swapMetatileId = 0;
bool isSwap = false;
};
class TilesetEditor : public QMainWindow
@@ -69,8 +79,7 @@ private slots:
void onHoveredTileChanged(const Tile&);
void onHoveredTileChanged(uint16_t);
void onHoveredTileCleared();
void onMetatileLayerTileChanged(int, int);
void onMetatileLayerSelectionChanged(QPoint, int, int);
void onMetatileLayerSelectionChanged(const QPoint&, const QSize&);
void onPaletteEditorChangedPaletteColor();
void on_actionChange_Metatiles_Count_triggered();
@@ -87,9 +96,7 @@ private slots:
void on_actionUndo_triggered();
void on_actionRedo_triggered();
void on_lineEdit_metatileLabel_editingFinished();
void on_copyButton_metatileLabel_clicked();
void on_copyButton_MetatileLabel_clicked();
void on_actionCut_triggered();
void on_actionCopy_triggered();
@@ -123,8 +130,8 @@ private:
void countMetatileUsage();
void countTileUsage();
void copyMetatile(bool cut);
void pasteMetatile(const Metatile * toPaste, QString label);
bool replaceMetatile(uint16_t metatileId, const Metatile * src, QString label);
void pasteMetatile(const Metatile &toPaste, QString label);
bool replaceMetatile(uint16_t metatileId, const Metatile &src, QString label);
void commitMetatileChange(Metatile * prevMetatile);
void commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel);
uint32_t attributeNameToValue(Metatile::Attr attribute, const QString &text, bool *ok);
@@ -135,9 +142,19 @@ private:
void commitEncounterType();
void commitTerrainType();
void commitLayerType();
void commit(MetatileHistoryItem *item);
void updateEditHistoryActions();
void setRawAttributesVisible(bool visible);
void refreshTileFlips();
void refreshPaletteId();
void paintSelectedLayerTiles(const QPoint &pos, bool paletteOnly = false);
void setMetatileLayerOrientation(Qt::Orientation orientation);
void commitMetatileSwap(uint16_t metatileIdA, uint16_t metatileIdB);
bool swapMetatiles(uint16_t metatileIdA, uint16_t metatileIdB);
void applyMetatileSwapToLayouts(uint16_t metatileIdA, uint16_t metatileIdB);
void applyMetatileSwapsToLayouts();
void rebuildMetatilePropertiesFrame();
void addWidgetToMetatileProperties(QWidget *w, int *row, int rowSpan);
Ui::TilesetEditor *ui;
History<MetatileHistoryItem*> metatileHistory;
@@ -161,6 +178,8 @@ private:
bool lockSelection = false;
QSet<uint16_t> metatileReloadQueue;
MetatileImageExporter::Settings *metatileImageExportSettings = nullptr;
QList<QPair<uint16_t,uint16_t>> metatileIdSwaps;
int numLayerViewRows;
bool save();

View File

@@ -19,9 +19,13 @@ public:
bool select(uint16_t metatileId);
void setTilesets(Tileset*, Tileset*);
uint16_t getSelectedMetatileId() const { return this->selectedMetatileId; }
void updateSelectedMetatile();
QPoint getMetatileIdCoordsOnWidget(uint16_t metatileId) const;
void setSwapMode(bool enabeled);
void addToSwapSelection(uint16_t metatileId);
void removeFromSwapSelection(uint16_t metatileId);
void clearSwapSelection();
QVector<uint16_t> usedMetatiles;
bool selectorShowUnused = false;
bool selectorShowCounts = false;
@@ -41,12 +45,18 @@ private:
QPixmap basePixmap;
Tileset *primaryTileset = nullptr;
Tileset *secondaryTileset = nullptr;
uint16_t selectedMetatileId;
uint16_t selectedMetatileId = 0;
QPoint prevCellPos = QPoint(-1,-1);
QList<uint16_t> swapMetatileIds;
uint16_t lastHoveredMetatileId = 0;
bool inSwapMode = false;
void updateBasePixmap();
uint16_t posToMetatileId(int x, int y, bool *ok = nullptr) const;
uint16_t posToMetatileId(const QPoint &pos, bool *ok = nullptr) const;
QPoint metatileIdToPos(uint16_t metatileId, bool *ok = nullptr) const;
bool shouldAcceptEvent(QGraphicsSceneMouseEvent*);
bool isValidMetatileId(uint16_t metatileId) const;
int numRows(int numMetatiles) const;
int numRows() const;
void drawGrid();
@@ -60,6 +70,7 @@ signals:
void hoveredMetatileChanged(uint16_t);
void hoveredMetatileCleared();
void selectedMetatileChanged(uint16_t);
void swapRequested(uint16_t, uint16_t);
};
#endif // TILESETEDITORMETATILESELECTOR_H

View File

@@ -7,8 +7,8 @@
class TilesetEditorTileSelector: public SelectablePixmapItem {
Q_OBJECT
public:
TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, int numLayers)
: SelectablePixmapItem(16, 16, numLayers * Metatile::tileWidth(), Metatile::tileHeight()) {
TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset)
: SelectablePixmapItem(16, 16, Metatile::tileWidth(), Metatile::tileWidth()) {
this->primaryTileset = primaryTileset;
this->secondaryTileset = secondaryTileset;
this->numTilesWide = 16;
@@ -18,7 +18,8 @@ public:
this->paletteChanged = false;
setAcceptHoverEvents(true);
}
QPoint getSelectionDimensions() const override;
QSize getSelectionDimensions() const override;
void setMaxSelectionSize(int width, int height) override;
void draw() override;
void select(uint16_t metatileId);
void highlight(uint16_t metatileId);
@@ -26,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();
@@ -48,7 +49,7 @@ private:
int externalSelectionWidth;
int externalSelectionHeight;
QList<Tile> externalSelectedTiles;
QList<int> externalSelectedPos;
QPoint prevCellPos = QPoint(-1,-1);
Tileset *primaryTileset;
Tileset *secondaryTileset;
@@ -62,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();