diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui
index edb0f306..90b0cc15 100644
--- a/forms/tileseteditor.ui
+++ b/forms/tileseteditor.ui
@@ -7,7 +7,7 @@
0
0
700
- 600
+ 700
@@ -198,6 +198,16 @@
false
+ -
+
+
+ Metatile Label (Optional)
+
+
+
+ -
+
+
-
diff --git a/include/core/metatile.h b/include/core/metatile.h
index 955c4264..b1be4d75 100644
--- a/include/core/metatile.h
+++ b/include/core/metatile.h
@@ -3,6 +3,7 @@
#include "tile.h"
#include
+#include
class Metatile
{
@@ -12,6 +13,7 @@ public:
QList *tiles = nullptr;
uint8_t behavior;
uint8_t layerType;
+ QString label;
Metatile *copy();
void copyInPlace(Metatile*);
diff --git a/include/project.h b/include/project.h
index 7669632f..da0ea2b0 100644
--- a/include/project.h
+++ b/include/project.h
@@ -91,6 +91,7 @@ public:
void loadTilesetAssets(Tileset*);
void loadTilesetTiles(Tileset*, QImage);
void loadTilesetMetatiles(Tileset*);
+ void loadTilesetMetatileLabels(Tileset*);
void saveLayoutBlockdata(Map*);
void saveLayoutBorder(Map*);
@@ -103,6 +104,7 @@ public:
void saveMapConstantsHeader();
void saveHealLocationStruct(Map*);
void saveTilesets(Tileset*, Tileset*);
+ void saveTilesetMetatileLabels(Tileset*, Tileset*);
void saveTilesetMetatileAttributes(Tileset*);
void saveTilesetMetatiles(Tileset*);
void saveTilesetTilesImage(Tileset*);
diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h
index 6e3ed3df..1095b0be 100644
--- a/include/ui/tileseteditor.h
+++ b/include/ui/tileseteditor.h
@@ -73,6 +73,8 @@ private slots:
void on_comboBox_metatileBehaviors_activated(const QString &arg1);
+ void on_lineEdit_metatileLabel_editingFinished();
+
void on_comboBox_layerType_activated(int arg1);
void on_actionExport_Primary_Tiles_Image_triggered();
@@ -93,6 +95,7 @@ private:
void importTilesetTiles(Tileset*, bool);
void importTilesetMetatiles(Tileset*, bool);
void refresh();
+ void saveMetatileLabel();
Ui::TilesetEditor *ui;
History metatileHistory;
TilesetEditorMetatileSelector *metatileSelector = nullptr;
diff --git a/src/core/metatile.cpp b/src/core/metatile.cpp
index e239085d..c35a7fcf 100644
--- a/src/core/metatile.cpp
+++ b/src/core/metatile.cpp
@@ -12,6 +12,7 @@ Metatile* Metatile::copy() {
copy->behavior = this->behavior;
copy->layerType = this->layerType;
copy->tiles = new QList;
+ copy->label = this->label;
for (Tile tile : *this->tiles) {
copy->tiles->append(tile);
}
@@ -21,6 +22,7 @@ Metatile* Metatile::copy() {
void Metatile::copyInPlace(Metatile *other) {
this->behavior = other->behavior;
this->layerType = other->layerType;
+ this->label = other->label;
for (int i = 0; i < this->tiles->length(); i++) {
(*this->tiles)[i] = other->tiles->at(i);
}
diff --git a/src/editor.cpp b/src/editor.cpp
index fb062005..06361e30 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -349,8 +349,14 @@ void Editor::onHoveredMovementPermissionCleared() {
}
void Editor::onHoveredMetatileSelectionChanged(uint16_t metatileId) {
- QString message = QString("Metatile: 0x%1")
- .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper());
+ Metatile *metatile = Tileset::getMetatile(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary);
+ QString message;
+ QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper();
+ if (metatile && metatile->label.size() != 0) {
+ message = QString("Metatile: 0x%1 \"%2\"").arg(hexString, metatile->label);
+ } else {
+ message = QString("Metatile: 0x%1").arg(hexString);
+ }
this->ui->statusBar->showMessage(message);
}
diff --git a/src/project.cpp b/src/project.cpp
index 477ba1a3..bd0c74aa 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -621,6 +621,7 @@ void Project::saveHealLocationStruct(Map *map) {
}
void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
+ saveTilesetMetatileLabels(primaryTileset, secondaryTileset);
saveTilesetMetatileAttributes(primaryTileset);
saveTilesetMetatileAttributes(secondaryTileset);
saveTilesetMetatiles(primaryTileset);
@@ -631,6 +632,90 @@ void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
saveTilesetPalettes(secondaryTileset, false);
}
+void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *secondaryTileset) {
+ QString filepath = root + "/include/constants/metatile_labels.h";
+ QString originalText = readTextFile(filepath);
+
+ QString primaryPrefix = QString("METATILE_%1_").arg(QString(primaryTileset->name).replace("gTileset_", ""));
+ QString secondaryPrefix = QString("METATILE_%1_").arg(QString(secondaryTileset->name).replace("gTileset_", ""));
+
+ QMap defines;
+ bool definesFileModified = false;
+ if (!originalText.isNull()) {
+ defines = readCDefines(originalText, (QStringList() << "METATILE_"));
+
+ // Purge old entries from the file.
+ QStringList definesToRemove;
+ for (QString defineName : defines.keys()) {
+ if (defineName.startsWith(primaryPrefix) || defineName.startsWith(secondaryPrefix)) {
+ definesToRemove << defineName;
+ }
+ }
+ for (QString defineName : definesToRemove) {
+ defines.remove(defineName);
+ definesFileModified = true;
+ }
+ }
+
+ // Add the new labels.
+ for (int i = 0; i < primaryTileset->metatiles->size(); i++) {
+ Metatile *metatile = primaryTileset->metatiles->at(i);
+ if (metatile->label.size() != 0) {
+ QString defineName = QString("%1%2").arg(primaryPrefix, metatile->label);
+ defines.insert(defineName, i);
+ definesFileModified = true;
+ }
+ }
+ for (int i = 0; i < secondaryTileset->metatiles->size(); i++) {
+ Metatile *metatile = secondaryTileset->metatiles->at(i);
+ if (metatile->label.size() != 0) {
+ QString defineName = QString("%1%2").arg(secondaryPrefix, metatile->label);
+ defines.insert(defineName, i + Project::num_tiles_primary);
+ definesFileModified = true;
+ }
+ }
+
+ if (!definesFileModified) {
+ return;
+ }
+
+ auto getTilesetFromLabel = [](QString labelName) {
+ return QRegularExpression("METATILE_(?[A-Za-z0-9]+)_").match(labelName).captured("tileset");
+ };
+
+ QString outputText = "#ifndef GUARD_METATILE_LABELS_H\n";
+ outputText += "#define GUARD_METATILE_LABELS_H\n";
+
+ for (int i = 0; i < defines.size();) {
+ QString defineName = defines.keys()[i];
+ QString currentTileset = getTilesetFromLabel(defineName);
+ outputText += QString("\n// gTileset_%1\n").arg(currentTileset);
+
+ int j = 0, longestLength = 0;
+ QMap definesOut;
+
+ // Setup for pretty formatting.
+ while (i + j < defines.size() && getTilesetFromLabel(defines.keys()[i + j]) == currentTileset) {
+ defineName = defines.keys()[i + j];
+ if (defineName.size() > longestLength)
+ longestLength = defineName.size();
+ definesOut.insert(defineName, defines[defineName]);
+ j++;
+ }
+ for (QString defineName : definesOut.keys()) {
+ int value = defines[defineName];
+ QString line = QString("#define %1 0x%2\n")
+ .arg(defineName, -1 * longestLength)
+ .arg(QString("%1").arg(value, 3, 16, QChar('0')).toUpper());
+ outputText += line;
+ }
+ i += j;
+ }
+
+ outputText += "\n#endif // GUARD_METATILE_LABELS_H\n";
+ saveTextFile(filepath, outputText);
+}
+
void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
QFile attrs_file(tileset->metatile_attrs_path);
if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
@@ -1040,6 +1125,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
QImage image = QImage(tileset->tilesImagePath);
this->loadTilesetTiles(tileset, image);
this->loadTilesetMetatiles(tileset);
+ this->loadTilesetMetatileLabels(tileset);
// palettes
QList> *palettes = new QList>;
@@ -1142,6 +1228,30 @@ void Project::loadTilesetMetatiles(Tileset* tileset) {
}
}
+void Project::loadTilesetMetatileLabels(Tileset* tileset) {
+ QString filepath = root + "/include/constants/metatile_labels.h";
+ QString text = readTextFile(filepath);
+
+ if (!text.isNull()) {
+ QString tilesetPrefix = QString("METATILE_%1_").arg(QString(tileset->name).replace("gTileset_", ""));
+ QMap labels = readCDefines(text, QStringList() << tilesetPrefix);
+
+ for (QString labelName : labels.keys()) {
+ int metatileId = labels[labelName];
+ // subtract Project::num_tiles_primary from secondary metatiles
+ Metatile *metatile = Tileset::getMetatile(metatileId - (tileset->is_secondary == "TRUE" ? Project::num_tiles_primary : 0), tileset, nullptr);
+ if (metatile) {
+ metatile->label = labelName.replace(tilesetPrefix, "");
+ } else {
+ QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper();
+ logError(QString("Metatile 0x%1 cannot be found in tileset '%2'").arg(hexString, tileset->name));
+ }
+ }
+ } else {
+ logError(QString("Failed to read C defines file: '%1'").arg(filepath));
+ }
+}
+
Blockdata* Project::readBlockdata(QString path) {
Blockdata *blockdata = new Blockdata;
QFile file(path);
diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp
index 50dd760c..85b94c35 100644
--- a/src/ui/tileseteditor.cpp
+++ b/src/ui/tileseteditor.cpp
@@ -61,6 +61,11 @@ void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString
this->ui->spinBox_paletteSelector->setMinimum(0);
this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
+ //only allow characters valid for a symbol
+ QRegExp expression("[_A-Za-z0-9]*$");
+ QRegExpValidator *validator = new QRegExpValidator(expression);
+ this->ui->lineEdit_metatileLabel->setValidator(validator);
+
this->initMetatileSelector();
this->initMetatileLayersItem();
this->initTileSelector();
@@ -179,8 +184,14 @@ void TilesetEditor::initMetatileLayersItem() {
}
void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) {
- QString message = QString("Metatile: 0x%1")
- .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper());
+ Metatile *metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
+ QString message;
+ QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper();
+ if (metatile && metatile->label.size() != 0) {
+ message = QString("Metatile: 0x%1 \"%2\"").arg(hexString, metatile->label);
+ } else {
+ message = QString("Metatile: 0x%1").arg(hexString);
+ }
this->ui->statusbar->showMessage(message);
}
@@ -193,6 +204,7 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
this->metatileLayersItem->setMetatile(metatile);
this->metatileLayersItem->draw();
this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior));
+ this->ui->lineEdit_metatileLabel->setText(this->metatile->label);
this->ui->comboBox_layerType->setCurrentIndex(this->ui->comboBox_layerType->findData(this->metatile->layerType));
}
@@ -317,6 +329,22 @@ void TilesetEditor::on_comboBox_metatileBehaviors_activated(const QString &metat
}
}
+void TilesetEditor::on_lineEdit_metatileLabel_editingFinished()
+{
+ saveMetatileLabel();
+}
+
+void TilesetEditor::saveMetatileLabel()
+{
+ // Only commit if the field has changed.
+ if (this->metatile && this->metatile->label != this->ui->lineEdit_metatileLabel->text()) {
+ Metatile *prevMetatile = this->metatile->copy();
+ this->metatile->label = this->ui->lineEdit_metatileLabel->text();
+ MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy());
+ metatileHistory.push(commit);
+ }
+}
+
void TilesetEditor::on_comboBox_layerType_activated(int layerType)
{
if (this->metatile) {
@@ -329,6 +357,8 @@ void TilesetEditor::on_comboBox_layerType_activated(int layerType)
void TilesetEditor::on_actionSave_Tileset_triggered()
{
+ saveMetatileLabel();
+
this->project->saveTilesets(this->primaryTileset, this->secondaryTileset);
emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name);
if (this->paletteEditor) {
@@ -680,7 +710,7 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
msgBox.exec();
return;
}
-\
+
// TODO: This is crude because it makes a history entry for every newly-imported metatile.
// Revisit this when tiles and num metatiles are added to tileset editory history.
int metatileIdBase = primary ? 0 : Project::getNumMetatilesPrimary();