Merge pull request #108 from Phlosioneer/metatile-labels
Add a way to name metatiles, for use in c code
This commit is contained in:
commit
22fe92840f
8 changed files with 171 additions and 6 deletions
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>600</height>
|
||||
<height>700</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
|
@ -198,6 +198,16 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Metatile Label (Optional)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_metatileLabel"/>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "tile.h"
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
|
||||
class Metatile
|
||||
{
|
||||
|
@ -12,6 +13,7 @@ public:
|
|||
QList<Tile> *tiles = nullptr;
|
||||
uint8_t behavior;
|
||||
uint8_t layerType;
|
||||
QString label;
|
||||
|
||||
Metatile *copy();
|
||||
void copyInPlace(Metatile*);
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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<MetatileHistoryItem*> metatileHistory;
|
||||
TilesetEditorMetatileSelector *metatileSelector = nullptr;
|
||||
|
|
|
@ -12,6 +12,7 @@ Metatile* Metatile::copy() {
|
|||
copy->behavior = this->behavior;
|
||||
copy->layerType = this->layerType;
|
||||
copy->tiles = new QList<Tile>;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
110
src/project.cpp
110
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<QString, int> 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_(?<tileset>[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<QString, int> 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<QList<QRgb>> *palettes = new QList<QList<QRgb>>;
|
||||
|
@ -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<QString, int> 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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue