diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui
index 3d7d733a..57b66a1d 100644
--- a/forms/tileseteditor.ui
+++ b/forms/tileseteditor.ui
@@ -337,6 +337,16 @@
-
+ -
+
+
+ Layer Type
+
+
+
+ -
+
+
@@ -354,8 +364,23 @@
21
+
+
+
+
+ Save Tileset
+
+
+ Ctrl+S
+
+
diff --git a/include/core/metatile.h b/include/core/metatile.h
index b5cb19d5..0a61f9fd 100644
--- a/include/core/metatile.h
+++ b/include/core/metatile.h
@@ -10,6 +10,8 @@ public:
Metatile();
public:
QList *tiles = nullptr;
+ uint8_t behavior;
+ uint8_t layerType;
static int getBlockIndex(int);
};
diff --git a/include/core/tileset.h b/include/core/tileset.h
index 82113e4b..dea009eb 100644
--- a/include/core/tileset.h
+++ b/include/core/tileset.h
@@ -17,8 +17,10 @@ public:
QString tiles_label;
QString palettes_label;
QString metatiles_label;
+ QString metatiles_path;
QString callback_label;
QString metatile_attrs_label;
+ QString metatile_attrs_path;
QList *tiles = nullptr;
QList *metatiles = nullptr;
diff --git a/include/project.h b/include/project.h
index 4efe58a6..856e3562 100644
--- a/include/project.h
+++ b/include/project.h
@@ -40,6 +40,8 @@ public:
QStringList *secretBaseIds = nullptr;
QStringList *bgEventFacingDirections = nullptr;
QStringList mapsWithConnections;
+ QMap metatileBehaviorMap;
+ QMap metatileBehaviorMapInverse;
QMap *map_cache;
Map* loadMap(QString);
@@ -83,6 +85,7 @@ public:
void saveMapGroupsTable();
void saveMapConstantsHeader();
void saveHealLocationStruct(Map*);
+ void saveTilesets(Tileset*, Tileset*);
QList* parseAsm(QString text);
QStringList getSongNames();
@@ -100,6 +103,7 @@ public:
void readCoordEventWeatherNames();
void readSecretBaseIds();
void readBgEventFacingDirections();
+ void readMetatileBehaviors();
void loadEventPixmaps(QList objects);
QMap getEventObjGfxConstants();
@@ -127,6 +131,8 @@ private:
QString getMapLayoutFilepath(QString);
void saveMapHeader(Map*);
void saveMapConnections(Map*);
+ void saveTilesetMetatileAttributes(Tileset*);
+ void saveTilesetMetatiles(Tileset*);
void updateMapsWithConnections(Map*);
void saveMapsWithConnections();
void saveMapLayoutsTable();
diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h
index 084d3af1..9126985c 100644
--- a/include/ui/tileseteditor.h
+++ b/include/ui/tileseteditor.h
@@ -34,6 +34,12 @@ private slots:
void on_checkBox_yFlip_stateChanged(int arg1);
+ void on_comboBox_metatileBehaviors_currentIndexChanged(const QString &arg1);
+
+ void on_comboBox_layerType_currentIndexChanged(int index);
+
+ void on_actionSave_Tileset_triggered();
+
private:
void initMetatileSelector();
void initTileSelector();
@@ -44,8 +50,8 @@ private:
TilesetEditorMetatileSelector *metatileSelector = nullptr;
TilesetEditorTileSelector *tileSelector = nullptr;
MetatileLayersItem *metatileLayersItem = nullptr;
- Project *project;
- Metatile *metatile;
+ Project *project = nullptr;
+ Metatile *metatile = nullptr;
int paletteId;
bool tileXFlip;
bool tileYFlip;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 9f77938d..bba152a7 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -406,6 +406,7 @@ void MainWindow::loadDataStructures() {
project->readSecretBaseIds();
project->readBgEventFacingDirections();
project->readMapsWithConnections();
+ project->readMetatileBehaviors();
project->readTilesetProperties();
}
diff --git a/src/project.cpp b/src/project.cpp
index 63899604..5fcd5b71 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -576,6 +576,49 @@ void Project::saveHealLocationStruct(Map *map) {
saveTextFile(root + "/include/constants/heal_locations.h", constants_text);
}
+void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
+ saveTilesetMetatileAttributes(primaryTileset);
+ saveTilesetMetatileAttributes(secondaryTileset);
+ saveTilesetMetatiles(primaryTileset);
+ saveTilesetMetatiles(secondaryTileset);
+}
+
+void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
+ QFile attrs_file(tileset->metatile_attrs_path);
+ if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ QByteArray data;
+ for (Metatile *metatile : *tileset->metatiles) {
+ data.append(static_cast(metatile->behavior));
+ data.append(static_cast((metatile->layerType << 4) & 0xF0));
+ }
+ attrs_file.write(data);
+ } else {
+ qDebug() << QString("Could not save tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path);
+ }
+}
+
+void Project::saveTilesetMetatiles(Tileset *tileset) {
+ QFile metatiles_file(tileset->metatiles_path);
+ if (metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ QByteArray data;
+ for (Metatile *metatile : *tileset->metatiles) {
+ for (int i = 0; i < 8; i++) {
+ Tile tile = metatile->tiles->at(i);
+ uint16_t value = static_cast((tile.tile & 0x3ff)
+ | ((tile.xflip & 1) << 10)
+ | ((tile.yflip & 1) << 11)
+ | ((tile.palette & 0xf) << 12));
+ data.append(static_cast(value & 0xff));
+ data.append(static_cast((value >> 8) & 0xff));
+ }
+ }
+ metatiles_file.write(data);
+ } else {
+ tileset->metatiles = new QList;
+ qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path);
+ }
+}
+
void Project::loadMapTilesets(Map* map) {
if (map->layout->has_unsaved_changes) {
return;
@@ -780,21 +823,19 @@ void Project::loadTilesetAssets(Tileset* tileset) {
}
}
- QString metatiles_path;
- QString metatile_attrs_path;
QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
QList *metatiles_macros = parser->parseAsm(metatiles_text);
QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
if (!metatiles_values->isEmpty()) {
- metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
+ tileset->metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
} else {
- metatiles_path = dir_path + "/metatiles.bin";
+ tileset->metatiles_path = dir_path + "/metatiles.bin";
}
QStringList *metatile_attrs_values = getLabelValues(metatiles_macros, tileset->metatile_attrs_label);
if (!metatile_attrs_values->isEmpty()) {
- metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1);
+ tileset->metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1);
} else {
- metatile_attrs_path = dir_path + "/metatile_attributes.bin";
+ tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin";
}
// tiles
@@ -813,7 +854,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
tileset->tiles = tiles;
// metatiles
- QFile metatiles_file(metatiles_path);
+ QFile metatiles_file(tileset->metatiles_path);
if (metatiles_file.open(QIODevice::ReadOnly)) {
QByteArray data = metatiles_file.readAll();
int num_metatiles = data.length() / 16;
@@ -837,11 +878,10 @@ void Project::loadTilesetAssets(Tileset* tileset) {
tileset->metatiles = metatiles;
} else {
tileset->metatiles = new QList;
- qDebug() << QString("Could not open '%1'").arg(metatiles_path);
+ qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path);
}
- QFile attrs_file(metatile_attrs_path);
- //qDebug() << metatile_attrs_path;
+ QFile attrs_file(tileset->metatile_attrs_path);
if (attrs_file.open(QIODevice::ReadOnly)) {
QByteArray data = attrs_file.readAll();
int num_metatiles = tileset->metatiles->count();
@@ -851,8 +891,13 @@ void Project::loadTilesetAssets(Tileset* tileset) {
if (num_metatiles > num_metatileAttrs)
num_metatiles = num_metatileAttrs;
}
+ for (int i = 0; i < num_metatileAttrs; i++) {
+ int value = (static_cast(data.at(i * 2 + 1)) << 8) | static_cast(data.at(i * 2));
+ tileset->metatiles->at(i)->behavior = value & 0xFF;
+ tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12;
+ }
} else {
- qDebug() << QString("Could not open '%1'").arg(metatile_attrs_path);
+ qDebug() << QString("Could not open tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path);
}
// palettes
@@ -1249,6 +1294,22 @@ void Project::readBgEventFacingDirections() {
readCDefinesSorted(filepath, prefixes, bgEventFacingDirections);
}
+void Project::readMetatileBehaviors() {
+ this->metatileBehaviorMap.clear();
+ this->metatileBehaviorMapInverse.clear();
+ QString filepath = root + "/include/constants/metatile_behaviors.h";
+ QString text = readTextFile(filepath);
+ if (!text.isNull()) {
+ QStringList prefixes = (QStringList() << "MB_");
+ this->metatileBehaviorMap = readCDefines(text, prefixes);
+ for (QString defineName : this->metatileBehaviorMap.keys()) {
+ this->metatileBehaviorMapInverse.insert(this->metatileBehaviorMap[defineName], defineName);
+ }
+ } else {
+ qDebug() << "Failed to read C defines file: " << filepath;
+ }
+}
+
void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
QString text = readTextFile(filepath);
if (!text.isNull()) {
diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp
index 14e6d95c..50e6afaa 100644
--- a/src/ui/metatilelayersitem.cpp
+++ b/src/ui/metatilelayersitem.cpp
@@ -1,7 +1,6 @@
#include "metatilelayersitem.h"
#include "imageproviders.h"
#include
-#include
void MetatileLayersItem::draw() {
const QList tileCoords = QList{
@@ -43,6 +42,5 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
int x = static_cast(pos.x()) / 16;
int y = static_cast(pos.y()) / 16;
int tileIndex = (x / 2 * 4) + (y * 2) + (x % 2);
- qDebug() << tileIndex;
emit this->tileChanged(tileIndex);
}
diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp
index 8fcf9117..06a889eb 100644
--- a/src/ui/tileseteditor.cpp
+++ b/src/ui/tileseteditor.cpp
@@ -16,8 +16,16 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr
this->primaryTilesetLabel = primaryTilesetLabel;
this->secondaryTilesetLabel = secondaryTilesetLabel;
- ui->spinBox_paletteSelector->setMinimum(0);
- ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
+ QList sortedBehaviors;
+ for (int num : project->metatileBehaviorMapInverse.keys()) {
+ this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num);
+ }
+ this->ui->comboBox_layerType->addItem("Normal - Middle/Top", 0);
+ this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", 1);
+ this->ui->comboBox_layerType->addItem("Split - Bottom/Top", 2);
+ this->ui->spinBox_paletteSelector->setMinimum(0);
+ this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
+
this->initMetatileSelector();
this->initMetatileLayersItem();
this->initTileSelector();
@@ -120,6 +128,8 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
this->metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset);
this->metatileLayersItem->setMetatile(metatile);
this->metatileLayersItem->draw();
+ this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior));
+ this->ui->comboBox_layerType->setCurrentIndex(this->ui->comboBox_layerType->findData(this->metatile->layerType));
}
void TilesetEditor::onHoveredTileChanged(uint16_t tile) {
@@ -165,3 +175,25 @@ void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked)
this->tileYFlip = checked;
this->drawSelectedTile();
}
+
+void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QString &metatileBehavior)
+{
+ if (this->metatile) {
+ this->metatile->behavior = static_cast(project->metatileBehaviorMap[metatileBehavior]);
+ }
+}
+
+
+void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType)
+{
+ if (this->metatile) {
+ this->metatile->layerType = static_cast(layerType);
+ }
+}
+
+void TilesetEditor::on_actionSave_Tileset_triggered()
+{
+ Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel);
+ Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel);
+ this->project->saveTilesets(primaryTileset, secondaryTileset);
+}