Add metatile attribute editing, and add tileset saving
This commit is contained in:
parent
322238c7b8
commit
428548b7e1
9 changed files with 150 additions and 17 deletions
|
@ -337,6 +337,16 @@
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QComboBox" name="comboBox_metatileBehaviors"/>
|
<widget class="QComboBox" name="comboBox_metatileBehaviors"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Layer Type</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QComboBox" name="comboBox_layerType"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -354,8 +364,23 @@
|
||||||
<height>21</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionSave_Tileset"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<action name="actionSave_Tileset">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save Tileset</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+S</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -10,6 +10,8 @@ public:
|
||||||
Metatile();
|
Metatile();
|
||||||
public:
|
public:
|
||||||
QList<Tile> *tiles = nullptr;
|
QList<Tile> *tiles = nullptr;
|
||||||
|
uint8_t behavior;
|
||||||
|
uint8_t layerType;
|
||||||
|
|
||||||
static int getBlockIndex(int);
|
static int getBlockIndex(int);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,8 +17,10 @@ public:
|
||||||
QString tiles_label;
|
QString tiles_label;
|
||||||
QString palettes_label;
|
QString palettes_label;
|
||||||
QString metatiles_label;
|
QString metatiles_label;
|
||||||
|
QString metatiles_path;
|
||||||
QString callback_label;
|
QString callback_label;
|
||||||
QString metatile_attrs_label;
|
QString metatile_attrs_label;
|
||||||
|
QString metatile_attrs_path;
|
||||||
|
|
||||||
QList<QImage> *tiles = nullptr;
|
QList<QImage> *tiles = nullptr;
|
||||||
QList<Metatile*> *metatiles = nullptr;
|
QList<Metatile*> *metatiles = nullptr;
|
||||||
|
|
|
@ -40,6 +40,8 @@ public:
|
||||||
QStringList *secretBaseIds = nullptr;
|
QStringList *secretBaseIds = nullptr;
|
||||||
QStringList *bgEventFacingDirections = nullptr;
|
QStringList *bgEventFacingDirections = nullptr;
|
||||||
QStringList mapsWithConnections;
|
QStringList mapsWithConnections;
|
||||||
|
QMap<QString, int> metatileBehaviorMap;
|
||||||
|
QMap<int, QString> metatileBehaviorMapInverse;
|
||||||
|
|
||||||
QMap<QString, Map*> *map_cache;
|
QMap<QString, Map*> *map_cache;
|
||||||
Map* loadMap(QString);
|
Map* loadMap(QString);
|
||||||
|
@ -83,6 +85,7 @@ public:
|
||||||
void saveMapGroupsTable();
|
void saveMapGroupsTable();
|
||||||
void saveMapConstantsHeader();
|
void saveMapConstantsHeader();
|
||||||
void saveHealLocationStruct(Map*);
|
void saveHealLocationStruct(Map*);
|
||||||
|
void saveTilesets(Tileset*, Tileset*);
|
||||||
|
|
||||||
QList<QStringList>* parseAsm(QString text);
|
QList<QStringList>* parseAsm(QString text);
|
||||||
QStringList getSongNames();
|
QStringList getSongNames();
|
||||||
|
@ -100,6 +103,7 @@ public:
|
||||||
void readCoordEventWeatherNames();
|
void readCoordEventWeatherNames();
|
||||||
void readSecretBaseIds();
|
void readSecretBaseIds();
|
||||||
void readBgEventFacingDirections();
|
void readBgEventFacingDirections();
|
||||||
|
void readMetatileBehaviors();
|
||||||
|
|
||||||
void loadEventPixmaps(QList<Event*> objects);
|
void loadEventPixmaps(QList<Event*> objects);
|
||||||
QMap<QString, int> getEventObjGfxConstants();
|
QMap<QString, int> getEventObjGfxConstants();
|
||||||
|
@ -127,6 +131,8 @@ private:
|
||||||
QString getMapLayoutFilepath(QString);
|
QString getMapLayoutFilepath(QString);
|
||||||
void saveMapHeader(Map*);
|
void saveMapHeader(Map*);
|
||||||
void saveMapConnections(Map*);
|
void saveMapConnections(Map*);
|
||||||
|
void saveTilesetMetatileAttributes(Tileset*);
|
||||||
|
void saveTilesetMetatiles(Tileset*);
|
||||||
void updateMapsWithConnections(Map*);
|
void updateMapsWithConnections(Map*);
|
||||||
void saveMapsWithConnections();
|
void saveMapsWithConnections();
|
||||||
void saveMapLayoutsTable();
|
void saveMapLayoutsTable();
|
||||||
|
|
|
@ -34,6 +34,12 @@ private slots:
|
||||||
|
|
||||||
void on_checkBox_yFlip_stateChanged(int arg1);
|
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:
|
private:
|
||||||
void initMetatileSelector();
|
void initMetatileSelector();
|
||||||
void initTileSelector();
|
void initTileSelector();
|
||||||
|
@ -44,8 +50,8 @@ private:
|
||||||
TilesetEditorMetatileSelector *metatileSelector = nullptr;
|
TilesetEditorMetatileSelector *metatileSelector = nullptr;
|
||||||
TilesetEditorTileSelector *tileSelector = nullptr;
|
TilesetEditorTileSelector *tileSelector = nullptr;
|
||||||
MetatileLayersItem *metatileLayersItem = nullptr;
|
MetatileLayersItem *metatileLayersItem = nullptr;
|
||||||
Project *project;
|
Project *project = nullptr;
|
||||||
Metatile *metatile;
|
Metatile *metatile = nullptr;
|
||||||
int paletteId;
|
int paletteId;
|
||||||
bool tileXFlip;
|
bool tileXFlip;
|
||||||
bool tileYFlip;
|
bool tileYFlip;
|
||||||
|
|
|
@ -406,6 +406,7 @@ void MainWindow::loadDataStructures() {
|
||||||
project->readSecretBaseIds();
|
project->readSecretBaseIds();
|
||||||
project->readBgEventFacingDirections();
|
project->readBgEventFacingDirections();
|
||||||
project->readMapsWithConnections();
|
project->readMapsWithConnections();
|
||||||
|
project->readMetatileBehaviors();
|
||||||
project->readTilesetProperties();
|
project->readTilesetProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -576,6 +576,49 @@ void Project::saveHealLocationStruct(Map *map) {
|
||||||
saveTextFile(root + "/include/constants/heal_locations.h", constants_text);
|
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<char>(metatile->behavior));
|
||||||
|
data.append(static_cast<char>((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<uint16_t>((tile.tile & 0x3ff)
|
||||||
|
| ((tile.xflip & 1) << 10)
|
||||||
|
| ((tile.yflip & 1) << 11)
|
||||||
|
| ((tile.palette & 0xf) << 12));
|
||||||
|
data.append(static_cast<char>(value & 0xff));
|
||||||
|
data.append(static_cast<char>((value >> 8) & 0xff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metatiles_file.write(data);
|
||||||
|
} else {
|
||||||
|
tileset->metatiles = new QList<Metatile*>;
|
||||||
|
qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Project::loadMapTilesets(Map* map) {
|
void Project::loadMapTilesets(Map* map) {
|
||||||
if (map->layout->has_unsaved_changes) {
|
if (map->layout->has_unsaved_changes) {
|
||||||
return;
|
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");
|
QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
|
||||||
QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
|
QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
|
||||||
QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
|
QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
|
||||||
if (!metatiles_values->isEmpty()) {
|
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 {
|
} 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);
|
QStringList *metatile_attrs_values = getLabelValues(metatiles_macros, tileset->metatile_attrs_label);
|
||||||
if (!metatile_attrs_values->isEmpty()) {
|
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 {
|
} else {
|
||||||
metatile_attrs_path = dir_path + "/metatile_attributes.bin";
|
tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin";
|
||||||
}
|
}
|
||||||
|
|
||||||
// tiles
|
// tiles
|
||||||
|
@ -813,7 +854,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
||||||
tileset->tiles = tiles;
|
tileset->tiles = tiles;
|
||||||
|
|
||||||
// metatiles
|
// metatiles
|
||||||
QFile metatiles_file(metatiles_path);
|
QFile metatiles_file(tileset->metatiles_path);
|
||||||
if (metatiles_file.open(QIODevice::ReadOnly)) {
|
if (metatiles_file.open(QIODevice::ReadOnly)) {
|
||||||
QByteArray data = metatiles_file.readAll();
|
QByteArray data = metatiles_file.readAll();
|
||||||
int num_metatiles = data.length() / 16;
|
int num_metatiles = data.length() / 16;
|
||||||
|
@ -837,11 +878,10 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
||||||
tileset->metatiles = metatiles;
|
tileset->metatiles = metatiles;
|
||||||
} else {
|
} else {
|
||||||
tileset->metatiles = new QList<Metatile*>;
|
tileset->metatiles = new QList<Metatile*>;
|
||||||
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);
|
QFile attrs_file(tileset->metatile_attrs_path);
|
||||||
//qDebug() << metatile_attrs_path;
|
|
||||||
if (attrs_file.open(QIODevice::ReadOnly)) {
|
if (attrs_file.open(QIODevice::ReadOnly)) {
|
||||||
QByteArray data = attrs_file.readAll();
|
QByteArray data = attrs_file.readAll();
|
||||||
int num_metatiles = tileset->metatiles->count();
|
int num_metatiles = tileset->metatiles->count();
|
||||||
|
@ -851,8 +891,13 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
||||||
if (num_metatiles > num_metatileAttrs)
|
if (num_metatiles > num_metatileAttrs)
|
||||||
num_metatiles = num_metatileAttrs;
|
num_metatiles = num_metatileAttrs;
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < num_metatileAttrs; i++) {
|
||||||
|
int value = (static_cast<unsigned char>(data.at(i * 2 + 1)) << 8) | static_cast<unsigned char>(data.at(i * 2));
|
||||||
|
tileset->metatiles->at(i)->behavior = value & 0xFF;
|
||||||
|
tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12;
|
||||||
|
}
|
||||||
} else {
|
} 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
|
// palettes
|
||||||
|
@ -1249,6 +1294,22 @@ void Project::readBgEventFacingDirections() {
|
||||||
readCDefinesSorted(filepath, prefixes, bgEventFacingDirections);
|
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) {
|
void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
|
||||||
QString text = readTextFile(filepath);
|
QString text = readTextFile(filepath);
|
||||||
if (!text.isNull()) {
|
if (!text.isNull()) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "metatilelayersitem.h"
|
#include "metatilelayersitem.h"
|
||||||
#include "imageproviders.h"
|
#include "imageproviders.h"
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
void MetatileLayersItem::draw() {
|
void MetatileLayersItem::draw() {
|
||||||
const QList<QPoint> tileCoords = QList<QPoint>{
|
const QList<QPoint> tileCoords = QList<QPoint>{
|
||||||
|
@ -43,6 +42,5 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
int x = static_cast<int>(pos.x()) / 16;
|
int x = static_cast<int>(pos.x()) / 16;
|
||||||
int y = static_cast<int>(pos.y()) / 16;
|
int y = static_cast<int>(pos.y()) / 16;
|
||||||
int tileIndex = (x / 2 * 4) + (y * 2) + (x % 2);
|
int tileIndex = (x / 2 * 4) + (y * 2) + (x % 2);
|
||||||
qDebug() << tileIndex;
|
|
||||||
emit this->tileChanged(tileIndex);
|
emit this->tileChanged(tileIndex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,16 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr
|
||||||
this->primaryTilesetLabel = primaryTilesetLabel;
|
this->primaryTilesetLabel = primaryTilesetLabel;
|
||||||
this->secondaryTilesetLabel = secondaryTilesetLabel;
|
this->secondaryTilesetLabel = secondaryTilesetLabel;
|
||||||
|
|
||||||
ui->spinBox_paletteSelector->setMinimum(0);
|
QList<QString> sortedBehaviors;
|
||||||
ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
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->initMetatileSelector();
|
||||||
this->initMetatileLayersItem();
|
this->initMetatileLayersItem();
|
||||||
this->initTileSelector();
|
this->initTileSelector();
|
||||||
|
@ -120,6 +128,8 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
|
||||||
this->metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset);
|
this->metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset);
|
||||||
this->metatileLayersItem->setMetatile(metatile);
|
this->metatileLayersItem->setMetatile(metatile);
|
||||||
this->metatileLayersItem->draw();
|
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) {
|
void TilesetEditor::onHoveredTileChanged(uint16_t tile) {
|
||||||
|
@ -165,3 +175,25 @@ void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked)
|
||||||
this->tileYFlip = checked;
|
this->tileYFlip = checked;
|
||||||
this->drawSelectedTile();
|
this->drawSelectedTile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QString &metatileBehavior)
|
||||||
|
{
|
||||||
|
if (this->metatile) {
|
||||||
|
this->metatile->behavior = static_cast<uint8_t>(project->metatileBehaviorMap[metatileBehavior]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType)
|
||||||
|
{
|
||||||
|
if (this->metatile) {
|
||||||
|
this->metatile->layerType = static_cast<uint8_t>(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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue