diff --git a/include/core/metatile.h b/include/core/metatile.h index 0b4b8a60..f606dcdb 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -8,6 +8,8 @@ #include #include +class Project; + enum { METATILE_LAYER_MIDDLE_TOP, METATILE_LAYER_BOTTOM_MIDDLE, @@ -91,7 +93,7 @@ public: static int getIndexInTileset(int); static QPoint coordFromPixmapCoord(const QPointF &pixelCoord); static int getDefaultAttributesSize(BaseGameVersion version); - static void setCustomLayout(); + static void setCustomLayout(Project*); private: // Stores how each attribute should be laid out for all metatiles, according to the user's config diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index e671564f..fcdd3bed 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -85,7 +85,7 @@ private slots: void on_actionRedo_triggered(); - void on_comboBox_metatileBehaviors_textActivated(const QString &arg1); + void on_comboBox_metatileBehaviors_currentTextChanged(const QString &arg1); void on_lineEdit_metatileLabel_editingFinished(); diff --git a/src/core/metatile.cpp b/src/core/metatile.cpp index d48fbbac..160b0c42 100644 --- a/src/core/metatile.cpp +++ b/src/core/metatile.cpp @@ -95,7 +95,7 @@ bool Metatile::isMaskTooSmall(MetatileAttr * attr, int max) { uint32_t n = log2(max); // Get a mask for all values 0 to max. - // This may fail for n=31, but that's not a concern here. + // This may fail for n > 30, but that's not possible here. uint32_t rangeMask = (1 << (n + 1)) - 1; return attr->getClamped(rangeMask) != rangeMask; @@ -110,7 +110,7 @@ bool Metatile::doMasksOverlap(QList masks) { return false; } -void Metatile::setCustomLayout() { +void Metatile::setCustomLayout(Project * project) { // Get the maximum size of any attribute mask const QHash maxMasks = { {1, 0xFF}, @@ -135,9 +135,13 @@ void Metatile::setCustomLayout() { logWarn("Metatile attribute masks are overlapping. This may result in unexpected attribute values."); } - // The available options in the Tileset Editor for Terrain Type, Encounter Type, and Layer Type are hard-coded. - // Warn the user if they have set a nonzero mask that is too small to contain these options. - // They'll be allowed to select them, but they'll be truncated to a different value when revisited. + // Warn the user if they have set a nonzero mask that is too small to contain its available options. + // They'll be allowed to select the options, but they'll be truncated to a different value when revisited. + if (!project->metatileBehaviorMapInverse.isEmpty()) { + int maxBehavior = project->metatileBehaviorMapInverse.lastKey(); + if (isMaskTooSmall(&Metatile::behaviorAttr, maxBehavior)) + logWarn(QString("Metatile Behavior mask is too small to contain all %1 available options.").arg(maxBehavior)); + } if (isMaskTooSmall(&Metatile::terrainTypeAttr, NUM_METATILE_TERRAIN_TYPES - 1)) logWarn(QString("Metatile Terrain Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_TERRAIN_TYPES)); if (isMaskTooSmall(&Metatile::encounterTypeAttr, NUM_METATILE_ENCOUNTER_TYPES - 1)) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2dc0dc0b..135b819f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -505,7 +505,6 @@ bool MainWindow::openProject(QString dir) { userConfig.load(); projectConfig.setProjectDir(dir); projectConfig.load(); - Metatile::setCustomLayout(); this->closeSupplementaryWindows(); this->setProjectSpecificUIVisibility(); @@ -914,6 +913,7 @@ bool MainWindow::loadDataStructures() { && project->readEventGraphics() && project->readSongNames(); + Metatile::setCustomLayout(project); Scripting::populateGlobalObject(this); return success && loadProjectCombos(); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index df130d5b..d45c65c7 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -503,11 +503,26 @@ void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked) this->metatileLayersItem->clearLastModifiedCoords(); } -void TilesetEditor::on_comboBox_metatileBehaviors_textActivated(const QString &metatileBehavior) +void TilesetEditor::on_comboBox_metatileBehaviors_currentTextChanged(const QString &metatileBehavior) { if (this->metatile) { + int behavior; + if (project->metatileBehaviorMap.contains(metatileBehavior)) { + behavior = project->metatileBehaviorMap[metatileBehavior]; + } else { + // Check if user has entered a number value instead + bool ok; + behavior = metatileBehavior.toInt(&ok); + if (!ok) return; + } + + // This function can also be called when the user selects + // a different metatile. Stop this from being considered a change. + if (this->metatile->behavior == static_cast(behavior)) + return; + Metatile *prevMetatile = new Metatile(*this->metatile); - this->metatile->setBehavior(project->metatileBehaviorMap[metatileBehavior]); + this->metatile->setBehavior(behavior); MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), prevMetatile, new Metatile(*this->metatile)); metatileHistory.push(commit);