Add color search feature

This commit is contained in:
GriffinR
2025-07-25 13:21:46 -04:00
parent 2f2f71948a
commit 6eaeee5f57
26 changed files with 776 additions and 249 deletions

View File

@@ -61,7 +61,7 @@ public:
static int getDefaultAttributesSize(BaseGameVersion version);
static void setLayout(Project*);
static QString getMetatileIdString(uint16_t metatileId);
static QString getMetatileIdStrings(const QList<uint16_t> metatileIds);
static QString getMetatileIdStrings(const QList<uint16_t> &metatileIds);
static QString getLayerName(int layerNum);
static constexpr int tileWidth() { return 2; }

View File

@@ -37,10 +37,14 @@ public:
QList<QList<QRgb>> palettePreviews;
static QString stripPrefix(const QString &fullName);
static Tileset* getPaletteTileset(int, Tileset*, Tileset*);
static const Tileset* getPaletteTileset(int, const Tileset*, const Tileset*);
static Tileset* getMetatileTileset(int, Tileset*, Tileset*);
static const Tileset* getMetatileTileset(int, const Tileset*, const Tileset*);
static Tileset* getTileTileset(int, Tileset*, Tileset*);
static const Tileset* getTileTileset(int, const Tileset*, const Tileset*);
static Metatile* getMetatile(int, Tileset*, Tileset*);
static const Metatile* getMetatile(int, const Tileset*, const Tileset*);
static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*);
static QString getMetatileLabel(int, Tileset *, Tileset *);
static QString getOwnedMetatileLabel(int, Tileset *, Tileset *);
@@ -48,9 +52,9 @@ public:
static bool setMetatileLabel(int, QString, Tileset *, Tileset *);
QString getMetatileLabelPrefix();
static QString getMetatileLabelPrefix(const QString &name);
static QList<QList<QRgb>> getBlockPalettes(Tileset*, Tileset*, bool useTruePalettes = false);
static QList<QRgb> getPalette(int, Tileset*, Tileset*, bool useTruePalettes = false);
static bool metatileIsValid(uint16_t metatileId, Tileset *, Tileset *);
static QList<QList<QRgb>> getBlockPalettes(const Tileset*, const Tileset*, bool useTruePalettes = false);
static QList<QRgb> getPalette(int, const Tileset*, const Tileset*, bool useTruePalettes = false);
static bool metatileIsValid(uint16_t metatileId, const Tileset*, const Tileset*);
static QHash<int, QString> getHeaderMemberMap(bool usingAsm);
static QString getExpectedDir(QString tilesetName, bool isSecondary);
QString getExpectedDir();
@@ -93,7 +97,8 @@ public:
QImage tileImage(uint16_t tileId) const { return m_tiles.value(Tile::getIndexInTileset(tileId)); }
QSet<int> getUnusedColorIds(int paletteId, Tileset *pairedTileset, const QSet<int> &searchColors = {}) const;
QSet<int> getUnusedColorIds(int paletteId, const Tileset *pairedTileset, const QSet<int> &searchColors = {}) const;
QList<uint16_t> findMetatilesUsingColor(int paletteId, int colorId, const Tileset *pairedTileset) const;
static constexpr int maxPalettes() { return 16; }
static constexpr int numColorsPerPalette() { return 16; }

View File

@@ -16,6 +16,7 @@ namespace Util {
QString replaceExtension(const QString &path, const QString &newExtension);
void setErrorStylesheet(QLineEdit *lineEdit, bool isError);
QString toStylesheetString(const QFont &font);
void show(QWidget *w);
}
#endif // UTILITY_H

View File

@@ -67,8 +67,6 @@ public:
bool setLayout(QString layoutName);
void unsetMap();
Tileset *getCurrentMapPrimaryTileset();
bool displayMap();
bool displayLayout();

View File

@@ -385,7 +385,6 @@ private:
void openDuplicateMapOrLayoutDialog();
void openNewMapGroupDialog();
void openNewLocationDialog();
void openSubWindow(QWidget * window);
void scrollMapList(MapTree *list, const QString &itemName);
void scrollMapListToCurrentMap(MapTree *list);
void scrollMapListToCurrentLayout(MapTree *list);

View File

@@ -104,12 +104,11 @@ public:
bool load();
QMap<QString, Tileset*> tilesetCache;
Tileset* loadTileset(QString, Tileset *tileset = nullptr);
Tileset* getTileset(QString, bool forceLoad = false);
Tileset* getTileset(const QString&, bool forceLoad = false);
QStringList primaryTilesetLabels;
QStringList secondaryTilesetLabels;
QStringList tilesetLabelsOrdered;
QSet<QString> getPairedTilesetLabels(Tileset *tileset) const;
QSet<QString> getPairedTilesetLabels(const Tileset *tileset) const;
bool readMapGroups();
void addNewMapGroup(const QString &groupName);
@@ -343,6 +342,7 @@ private:
void resetFileCache();
void resetFileWatcher();
void logFileWatchStatus();
void cacheTileset(const QString &label, Tileset *tileset);
bool saveMapLayouts();
bool saveMapGroups();

View File

@@ -11,14 +11,14 @@ class Layout;
QImage getCollisionMetatileImage(Block);
QImage getCollisionMetatileImage(int, int);
QImage getMetatileImage(uint16_t, Layout*, bool useTruePalettes = false);
QImage getMetatileImage(Metatile*, Layout*, bool useTruePalettes = false);
QImage getMetatileImage(uint16_t, Tileset*, Tileset*, const QList<int>&, const QList<float>& = {}, bool useTruePalettes = false);
QImage getMetatileImage(Metatile*, Tileset*, Tileset*, const QList<int>&, const QList<float>& = {}, bool useTruePalettes = false);
QImage getMetatileImage(uint16_t, const Layout*, bool useTruePalettes = false);
QImage getMetatileImage(const Metatile*, const Layout*, bool useTruePalettes = false);
QImage getMetatileImage(uint16_t, const Tileset*, const Tileset*, const QList<int>& = {0,1,2}, const QList<float>& = {}, bool useTruePalettes = false);
QImage getMetatileImage(const Metatile*, const Tileset*, const Tileset*, const QList<int>& = {0,1,2}, const QList<float>& = {}, bool useTruePalettes = false);
QImage getMetatileSheetImage(Layout *layout, int numMetatilesWIde, bool useTruePalettes = false);
QImage getMetatileSheetImage(Tileset *primaryTileset,
Tileset *secondaryTileset,
QImage getMetatileSheetImage(const Layout *layout, int numMetatilesWIde, bool useTruePalettes = false);
QImage getMetatileSheetImage(const Tileset *primaryTileset,
const Tileset *secondaryTileset,
uint16_t metatileIdStart,
uint16_t metatileIdEnd,
int numMetatilesWIde,
@@ -26,8 +26,8 @@ QImage getMetatileSheetImage(Tileset *primaryTileset,
const QList<float> &layerOpacity = {},
const QSize &metatileSize = Metatile::pixelSize(),
bool useTruePalettes = false);
QImage getMetatileSheetImage(Tileset *primaryTileset,
Tileset *secondaryTileset,
QImage getMetatileSheetImage(const Tileset *primaryTileset,
const Tileset *secondaryTileset,
int numMetatilesWide,
const QList<int> &layerOrder,
const QList<float> &layerOpacity = {},
@@ -36,9 +36,9 @@ QImage getMetatileSheetImage(Tileset *primaryTileset,
QImage getTileImage(uint16_t, const Tileset*, const Tileset*);
QImage getPalettedTileImage(uint16_t, Tileset*, Tileset*, int, bool useTruePalettes = false);
QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, const QList<QRgb> &palette);
QImage getGreyscaleTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset);
QImage getPalettedTileImage(uint16_t, const Tileset*, const Tileset*, int, bool useTruePalettes = false);
QImage getColoredTileImage(uint16_t tileId, const Tileset *, const Tileset *, const QList<QRgb> &palette);
QImage getGreyscaleTileImage(uint16_t tileId, const Tileset *, const Tileset *);
void flattenTo4bppImage(QImage * image);

View File

@@ -0,0 +1,20 @@
#ifndef NUMERICSORTTABLEITEM_H
#define NUMERICSORTTABLEITEM_H
#include <QTableWidgetItem>
#include <QCollator>
class NumericSortTableItem : public QTableWidgetItem
{
public:
explicit NumericSortTableItem(const QString &text) : QTableWidgetItem(text) {};
protected:
virtual bool operator<(const QTableWidgetItem &other) const override {
QCollator collator;
collator.setNumericMode(true);
return collator.compare(text(), other.text()) < 0;
}
};
#endif // NUMERICSORTTABLEITEM_H

View File

@@ -0,0 +1,67 @@
#ifndef PALETTECOLORSEARCH_H
#define PALETTECOLORSEARCH_H
#include <QDialog>
#include <QIcon>
#include <QMap>
class Tileset;
class Project;
namespace Ui {
class PaletteColorSearch;
}
class PaletteColorSearch : public QDialog
{
Q_OBJECT
public:
explicit PaletteColorSearch(Project *project,
const Tileset *primaryTileset,
const Tileset *secondaryTileset,
QWidget *parent = nullptr);
~PaletteColorSearch();
void setPaletteId(int paletteId);
int currentPaletteId() const;
void setColorId(int colorId);
int currentColorId() const;
void setTilesets(const Tileset *primaryTileset, const Tileset *secondaryTileset);
const Tileset* currentTileset() const;
signals:
void metatileSelected(uint16_t metatileId);
void paletteIdChanged(int paletteId);
private:
struct RowData {
QString tilesetName;
QString pairedTilesetName;
QString metatileId;
QIcon metatileIcon;
};
enum ResultsColumn {
TilesetName,
Metatile,
};
Ui::PaletteColorSearch *ui;
Project *m_project;
const Tileset *m_primaryTileset;
const Tileset *m_secondaryTileset;
QMap<QString,QList<RowData>> m_resultsCache;
void addTableEntry(const RowData &rowData);
QList<RowData> search(int colorId) const;
QList<RowData> search(int colorId, const Tileset *tileset, const Tileset *pairedTileset) const;
void refresh();
void updateResults();
void cellDoubleClicked(int row, int col);
};
#endif // PALETTECOLORSEARCH_H

View File

@@ -2,10 +2,12 @@
#define PALETTEEDITOR_H
#include <QMainWindow>
#include <QPointer>
#include "colorinputwidget.h"
#include "project.h"
#include "history.h"
#include "palettecolorsearch.h"
namespace Ui {
class PaletteEditor;
@@ -32,27 +34,31 @@ public:
bool showingUnusedColors() const;
signals:
void metatileSelected(uint16_t metatileId);
private:
Ui::PaletteEditor *ui;
Project *project = nullptr;
QList<ColorInputWidget*> colorInputs;
Project *project;
Tileset *primaryTileset;
Tileset *secondaryTileset;
QList<ColorInputWidget*> colorInputs;
QList<History<PaletteHistoryItem*>> palettesHistory;
QMap<int,QSet<int>> unusedColorCache;
QPointer<PaletteColorSearch> colorSearchWindow;
Tileset* getTileset(int paletteId) const;
void refreshColorInputs();
void refreshPaletteId();
void commitEditHistory();
void commitEditHistory(int paletteId);
void restoreWindowState();
void onWindowActivated();
void invalidateCache();
void closeEvent(QCloseEvent*);
void setColorInputTitles(bool show);
QSet<int> getUnusedColorIds() const;
QSet<int> getUnusedColorIds();
void openColorSearch();
void setRgb(int index, QRgb rgb);
void setPalette(int paletteId, const QList<QRgb> &palette);
@@ -67,7 +73,6 @@ signals:
void changedPaletteColor();
void changedPalette(int);
private slots:
void on_spinBox_PaletteId_valueChanged(int arg1);
void on_actionUndo_triggered();
void on_actionRedo_triggered();
void on_actionImport_Palette_triggered();

View File

@@ -2,6 +2,7 @@
#define TILESETEDITOR_H
#include <QMainWindow>
#include <QPointer>
#include "project.h"
#include "history.h"
#include "paletteeditor.h"
@@ -54,6 +55,9 @@ public:
QObjectList shortcutableObjects() const;
void setPaletteId(int paletteId);
int paletteId() const;
public slots:
void applyUserShortcuts();
void onSelectedMetatileChanged(uint16_t);
@@ -65,13 +69,9 @@ private slots:
void onHoveredTileChanged(const Tile&);
void onHoveredTileChanged(uint16_t);
void onHoveredTileCleared();
void onSelectedTilesChanged();
void onMetatileLayerTileChanged(int, int);
void onMetatileLayerSelectionChanged(QPoint, int, int);
void onPaletteEditorChangedPaletteColor();
void onPaletteEditorChangedPalette(int);
void on_spinBox_paletteSelector_valueChanged(int arg1);
void on_actionChange_Metatiles_Count_triggered();
@@ -136,23 +136,20 @@ private:
void commitTerrainType();
void commitLayerType();
void setRawAttributesVisible(bool visible);
void setXFlip(bool enabled);
void setYFlip(bool enabled);
void refreshTileFlips();
void refreshPaletteId();
Ui::TilesetEditor *ui;
History<MetatileHistoryItem*> metatileHistory;
TilesetEditorMetatileSelector *metatileSelector = nullptr;
TilesetEditorTileSelector *tileSelector = nullptr;
MetatileLayersItem *metatileLayersItem = nullptr;
PaletteEditor *paletteEditor = nullptr;
QPointer<PaletteEditor> paletteEditor = nullptr;
Project *project = nullptr;
Layout *layout = nullptr;
Metatile *metatile = nullptr;
Metatile *copiedMetatile = nullptr;
QString copiedMetatileLabel;
int paletteId;
bool tileXFlip;
bool tileYFlip;
bool hasUnsavedChanges;
Tileset *primaryTileset = nullptr;
Tileset *secondaryTileset = nullptr;

View File

@@ -2,24 +2,11 @@
#define WILDMONSEARCH_H
#include <QDialog>
#include <QTableWidgetItem>
#include <QCollator>
#include "numericsorttableitem.h"
class Project;
class NumericSortTableItem : public QTableWidgetItem
{
public:
explicit NumericSortTableItem(const QString &text) : QTableWidgetItem(text) {};
protected:
virtual bool operator<(const QTableWidgetItem &other) const override {
QCollator collator;
collator.setNumericMode(true);
return collator.compare(text(), other.text()) < 0;
}
};
namespace Ui {
class WildMonSearch;
}