Add setting to change metatile selector width

This commit is contained in:
GriffinR 2025-07-23 12:22:03 -04:00
parent c45598f6c4
commit be9728523e
12 changed files with 56 additions and 36 deletions

View File

@ -852,7 +852,7 @@
<x>0</x>
<y>0</y>
<width>570</width>
<height>798</height>
<height>837</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
@ -973,6 +973,27 @@
</layout>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_MetatileSelectorWidth">
<item row="0" column="0">
<widget class="QLabel" name="label_MetatileSelectorWidth">
<property name="text">
<string>Metatile Selector Width</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="NoScrollSpinBox" name="spinBox_MetatileSelectorWidth">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The width (in metatiles) of the metatile selectors on the Map tab and in the Tileset Editor.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="frame_WarningTilesetsTab">
<property name="styleSheet">
@ -1873,16 +1894,6 @@
<extends>QComboBox</extends>
<header>noscrollcombobox.h</header>
</customwidget>
<customwidget>
<class>NoScrollSpinBox</class>
<extends>QSpinBox</extends>
<header>noscrollspinbox.h</header>
</customwidget>
<customwidget>
<class>NoScrollTextEdit</class>
<extends>QTextEdit</extends>
<header>noscrolltextedit.h</header>
</customwidget>
<customwidget>
<class>UIntSpinBox</class>
<extends>QAbstractSpinBox</extends>
@ -1893,6 +1904,16 @@
<extends>UIntSpinBox</extends>
<header location="global">uintspinbox.h</header>
</customwidget>
<customwidget>
<class>NoScrollSpinBox</class>
<extends>QSpinBox</extends>
<header>noscrollspinbox.h</header>
</customwidget>
<customwidget>
<class>NoScrollTextEdit</class>
<extends>QTextEdit</extends>
<header>noscrolltextedit.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/images.qrc"/>

View File

@ -325,6 +325,7 @@ public:
this->unusedTileSplit = 0x0000;
this->maxEventsPerGroup = 255;
this->forcedMajorVersion = 0;
this->metatileSelectorWidth = 8;
this->globalConstantsFilepaths.clear();
this->globalConstants.clear();
this->identifiers.clear();
@ -404,6 +405,7 @@ public:
QList<uint32_t> warpBehaviors;
int maxEventsPerGroup;
int forcedMajorVersion;
int metatileSelectorWidth;
QStringList globalConstantsFilepaths;
QMap<QString,QString> globalConstants;

View File

@ -52,7 +52,7 @@ public:
};
uint16_t metatileStart = 0;
uint16_t metatileEnd = 0xFFFF;
uint16_t numMetatilesWide = 8;
uint16_t numMetatilesWide = projectConfig.metatileSelectorWidth;
bool usePrimaryTileset = true;
bool useSecondaryTileset = false;
bool renderPlaceholders = false;

View File

@ -31,10 +31,12 @@ struct MetatileSelection
class MetatileSelector: public SelectablePixmapItem {
Q_OBJECT
public:
MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(Metatile::pixelSize()) {
MetatileSelector(int numMetatilesWide, Layout *layout)
: SelectablePixmapItem(Metatile::pixelSize()),
numMetatilesWide(qMax(numMetatilesWide, 1))
{
this->externalSelection = false;
this->prefabSelection = false;
this->numMetatilesWide = numMetatilesWide;
this->layout = layout;
this->selection = MetatileSelection{};
this->cellPos = QPoint(-1, -1);
@ -65,10 +67,10 @@ protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent*) override;
void drawSelection() override;
private:
const int numMetatilesWide;
QPixmap basePixmap;
bool externalSelection;
bool prefabSelection;
int numMetatilesWide;
Layout *layout;
int externalSelectionWidth;
int externalSelectionHeight;

View File

@ -9,7 +9,7 @@ class Layout;
class TilesetEditorMetatileSelector: public SelectablePixmapItem {
Q_OBJECT
public:
TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout);
TilesetEditorMetatileSelector(int numMetatilesWide, Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout);
Layout *layout = nullptr;
void draw() override;
@ -36,13 +36,12 @@ protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent*) override;
private:
const int numMetatilesWide;
QImage baseImage;
QPixmap basePixmap;
Tileset *primaryTileset = nullptr;
Tileset *secondaryTileset = nullptr;
uint16_t selectedMetatileId;
int numMetatilesWide;
int numMetatilesHigh;
void updateBasePixmap();
uint16_t posToMetatileId(int x, int y, bool *ok = nullptr) const;
uint16_t posToMetatileId(const QPoint &pos, bool *ok = nullptr) const;

View File

@ -1007,6 +1007,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
this->maxEventsPerGroup = getConfigInteger(key, value, 1, INT_MAX, 255);
} else if (key == "forced_major_version") {
this->forcedMajorVersion = getConfigInteger(key, value);
} else if (key == "metatile_selector_width") {
this->metatileSelectorWidth = getConfigInteger(key, value, 1, INT_MAX, 8);
} else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->filepath()).arg(key));
}
@ -1116,6 +1118,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
map.insert("warp_behaviors", warpBehaviorStrs.join(","));
map.insert("max_events_per_group", QString::number(this->maxEventsPerGroup));
map.insert("forced_major_version", QString::number(this->forcedMajorVersion));
map.insert("metatile_selector_width", QString::number(this->metatileSelectorWidth));
return map;
}

View File

@ -1646,7 +1646,7 @@ void Editor::displayMetatileSelector() {
scene_metatiles = new QGraphicsScene;
if (!metatile_selector_item) {
metatile_selector_item = new MetatileSelector(8, this->layout);
metatile_selector_item = new MetatileSelector(projectConfig.metatileSelectorWidth, this->layout);
connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionChanged,
this, &Editor::onHoveredMetatileSelectionChanged);
connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionCleared,

View File

@ -191,7 +191,7 @@ QImage getMetatileSheetImage(Tileset *primaryTileset,
const QSize &metatileSize,
bool useTruePalettes)
{
if (metatileIdEnd < metatileIdStart || numMetatilesWide == 0)
if (metatileIdEnd < metatileIdStart || numMetatilesWide <= 0)
return QImage();
int numMetatilesToDraw = metatileIdEnd - metatileIdStart + 1;

View File

@ -213,7 +213,7 @@ uint16_t MetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
// then the metatiles we used to round the primary tileset would have the index of valid secondary metatiles.
// These need to be ignored, or they'll appear to be duplicates of the subseqeunt secondary metatiles.
int numPrimaryRounded = numPrimaryMetatilesRounded();
int firstSecondaryRow = numPrimaryRounded / qMax(this->numMetatilesWide, 1);
int firstSecondaryRow = numPrimaryRounded / this->numMetatilesWide;
metatileId = static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimaryRounded);
if (secondaryTileset() && secondaryTileset()->contains(metatileId) && y >= firstSecondaryRow) {
return metatileId;
@ -224,11 +224,6 @@ uint16_t MetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
}
QPoint MetatileSelector::metatileIdToPos(uint16_t metatileId, bool *ok) const {
if (this->numMetatilesWide == 0) {
if (ok) *ok = false;
return QPoint(0,0);
}
if (primaryTileset() && primaryTileset()->contains(metatileId)) {
if (ok) *ok = true;
int index = metatileId;

View File

@ -161,6 +161,7 @@ void ProjectSettingsEditor::initUi() {
ui->spinBox_PlayerViewDistance_North->setMaximum(INT_MAX);
ui->spinBox_PlayerViewDistance_East->setMaximum(INT_MAX);
ui->spinBox_PlayerViewDistance_South->setMaximum(INT_MAX);
ui->spinBox_MetatileSelectorWidth->setMaximum(maxMetatileId + 1);
// The values for some of the settings we provide in this window can be determined using constants in the user's projects.
// If the user has these constants we disable these settings in the UI -- they can modify them using their constants.
@ -503,6 +504,7 @@ void ProjectSettingsEditor::refresh() {
ui->spinBox_PlayerViewDistance_North->setValue(projectConfig.playerViewDistance.top());
ui->spinBox_PlayerViewDistance_East->setValue(projectConfig.playerViewDistance.right());
ui->spinBox_PlayerViewDistance_South->setValue(projectConfig.playerViewDistance.bottom());
ui->spinBox_MetatileSelectorWidth->setValue(projectConfig.metatileSelectorWidth);
// Set (and sync) border metatile IDs
this->setBorderMetatileIds(false, projectConfig.newMapBorderMetatileIds);
@ -598,6 +600,7 @@ void ProjectSettingsEditor::save() {
ui->spinBox_PlayerViewDistance_North->value(),
ui->spinBox_PlayerViewDistance_East->value(),
ui->spinBox_PlayerViewDistance_South->value());
projectConfig.metatileSelectorWidth = ui->spinBox_MetatileSelectorWidth->value();
// Save line edit settings
projectConfig.prefabFilepath = ui->lineEdit_PrefabsPath->text();

View File

@ -215,7 +215,7 @@ void TilesetEditor::setRawAttributesVisible(bool visible) {
void TilesetEditor::initMetatileSelector()
{
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->layout);
this->metatileSelector = new TilesetEditorMetatileSelector(projectConfig.metatileSelectorWidth, this->primaryTileset, this->secondaryTileset, this->layout);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileChanged,
this, &TilesetEditor::onHoveredMetatileChanged);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileCleared,

View File

@ -6,11 +6,11 @@
// TODO: This class has a decent bit of overlap with the MetatileSelector class.
// They should be refactored to inherit from a single parent class.
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout)
: SelectablePixmapItem(32, 32, 1, 1) {
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(int numMetatilesWide, Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout)
: SelectablePixmapItem(32, 32, 1, 1),
numMetatilesWide(qMax(numMetatilesWide, 1)) {
this->primaryTileset = primaryTileset;
this->secondaryTileset = secondaryTileset;
this->numMetatilesWide = 8;
this->layout = layout;
setAcceptHoverEvents(true);
this->usedMetatiles.resize(Project::getNumMetatilesTotal());
@ -169,7 +169,7 @@ uint16_t TilesetEditorMetatileSelector::posToMetatileId(int x, int y, bool *ok)
// then the metatiles we used to round the primary tileset would have the index of valid secondary metatiles.
// These need to be ignored, or they'll appear to be duplicates of the subseqeunt secondary metatiles.
int numPrimaryRounded = numPrimaryMetatilesRounded();
int firstSecondaryRow = numPrimaryRounded / qMax(this->numMetatilesWide, 1);
int firstSecondaryRow = numPrimaryRounded / this->numMetatilesWide;
metatileId = static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimaryRounded);
if (this->secondaryTileset && this->secondaryTileset->contains(metatileId) && y >= firstSecondaryRow) {
return metatileId;
@ -180,11 +180,6 @@ uint16_t TilesetEditorMetatileSelector::posToMetatileId(int x, int y, bool *ok)
}
QPoint TilesetEditorMetatileSelector::metatileIdToPos(uint16_t metatileId, bool *ok) const {
if (this->numMetatilesWide == 0) {
if (ok) *ok = false;
return QPoint(0,0);
}
if (this->primaryTileset && this->primaryTileset->contains(metatileId)) {
if (ok) *ok = true;
int index = metatileId;