Skip to content

Commit

Permalink
Merge pull request #531 from GriffinRichards/fix-label-saving
Browse files Browse the repository at this point in the history
Fix metatile label saving
  • Loading branch information
GriffinRichards authored Dec 17, 2023
2 parents b88d62e + c42909d commit 144b835
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d

### Fixed
- Fix text boxes in the Palette Editor calculating color incorrectly.
- Fix metatile labels being sorted incorrectly for tileset names with multiple underscores.
- Fix default object sprites retaining dimensions and transparency of the previous sprite.
- Fix connections not being deleted when the map name text box is cleared.
- Fix the map border not updating when a tileset is changed.
Expand Down
5 changes: 5 additions & 0 deletions include/project.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Project : public QObject
QStringList trainerTypes;
QStringList globalScriptLabels;
QMap<QString, QMap<QString, int>> metatileLabelsMap;
QMap<QString, int> unusedMetatileLabels;
QMap<QString, int> metatileBehaviorMap;
QMap<int, QString> metatileBehaviorMapInverse;
QMap<QString, QString> facingDirections;
Expand Down Expand Up @@ -216,6 +217,10 @@ class Project : public QObject
QString getDefaultPrimaryTilesetLabel();
QString getDefaultSecondaryTilesetLabel();

void updateTilesetMetatileLabels(Tileset *tileset);
QString buildMetatileLabelsText(const QMap<QString, int> defines);
QString findMetatileLabelsTileset(QString label);

void setImportExportPath(QString filename);

static int getNumTilesPrimary();
Expand Down
143 changes: 70 additions & 73 deletions src/project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,86 +885,71 @@ void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
saveTilesetPalettes(secondaryTileset);
}

void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *secondaryTileset) {
QString primaryPrefix = primaryTileset->getMetatileLabelPrefix();
QString secondaryPrefix = secondaryTileset->getMetatileLabelPrefix();

QMap<QString, int> defines;
bool definesFileModified = false;
void Project::updateTilesetMetatileLabels(Tileset *tileset) {
// Erase old labels, then repopulate with new labels
const QString prefix = tileset->getMetatileLabelPrefix();
metatileLabelsMap[tileset->name].clear();
for (int metatileId : tileset->metatileLabels.keys()) {
if (tileset->metatileLabels[metatileId].isEmpty())
continue;
QString label = prefix + tileset->metatileLabels[metatileId];
metatileLabelsMap[tileset->name][label] = metatileId;
}
}

QString metatileLabelsFilename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_labels);
defines = parser.readCDefines(metatileLabelsFilename, (QStringList() << "METATILE_"));
// Given a map of define names to define values, returns a formatted list of #defines
QString Project::buildMetatileLabelsText(const QMap<QString, int> defines) {
QStringList labels = defines.keys();

// 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;
// Setup for pretty formatting.
int longestLength = 0;
for (QString label : labels) {
if (label.size() > longestLength)
longestLength = label.size();
}

// Add the new labels.
for (int metatileId : primaryTileset->metatileLabels.keys()) {
QString label = primaryTileset->metatileLabels.value(metatileId);
if (label.isEmpty()) continue;
QString defineName = QString("%1%2").arg(primaryPrefix, label);
defines.insert(defineName, metatileId);
definesFileModified = true;
}
for (int metatileId : secondaryTileset->metatileLabels.keys()) {
QString label = secondaryTileset->metatileLabels.value(metatileId);
if (label.isEmpty()) continue;
QString defineName = QString("%1%2").arg(secondaryPrefix, label);
defines.insert(defineName, metatileId);
definesFileModified = true;
// Generate defines text
QString output = QString();
for (QString label : labels) {
QString line = QString("#define %1 %2\n")
.arg(label, -1 * longestLength)
.arg(Metatile::getMetatileIdString(defines[label]));
output += line;
}
return output;
}

if (!definesFileModified) {
void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *secondaryTileset) {
// Skip writing the file if there are no labels in both the new and old sets
if (metatileLabelsMap[primaryTileset->name].size() == 0 && primaryTileset->metatileLabels.size() == 0
&& metatileLabelsMap[secondaryTileset->name].size() == 0 && secondaryTileset->metatileLabels.size() == 0)
return;
}

auto getTilesetFromLabel = [](QString labelName) {
static const QRegularExpression re_tilesetName("METATILE_(?<tileset>[A-Za-z0-9]+)_");
return re_tilesetName.match(labelName).captured("tileset");
};

QString outputText = "#ifndef GUARD_METATILE_LABELS_H\n";
outputText += "#define GUARD_METATILE_LABELS_H\n";
updateTilesetMetatileLabels(primaryTileset);
updateTilesetMetatileLabels(secondaryTileset);

for (int i = 0; i < defines.size();) {
QString defineName = defines.keys()[i];
QString currentTileset = getTilesetFromLabel(defineName);
outputText += QString("\n// gTileset_%1\n").arg(currentTileset);
// Recreate metatile labels file
const QString guardName = "GUARD_METATILE_LABELS_H";
QString outputText = QString("#ifndef %1\n#define %1\n").arg(guardName);

int j = 0, longestLength = 0;
QMap<QString, int> definesOut;
for (QString tilesetName : metatileLabelsMap.keys()) {
if (metatileLabelsMap[tilesetName].size() == 0)
continue;
outputText += QString("\n// %1\n").arg(tilesetName);
outputText += buildMetatileLabelsText(metatileLabelsMap[tilesetName]);
}

// 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 %2\n")
.arg(defineName, -1 * longestLength)
.arg(Metatile::getMetatileIdString(value));
outputText += line;
}
i += j;
if (unusedMetatileLabels.size() != 0) {
// Append any defines originally read from the file that aren't associated with any tileset.
outputText += QString("\n// Other\n");
outputText += buildMetatileLabelsText(unusedMetatileLabels);
}

outputText += "\n#endif // GUARD_METATILE_LABELS_H\n";
outputText += QString("\n#endif // %1\n").arg(guardName);

ignoreWatchedFileTemporarily(root + "/" + metatileLabelsFilename);
saveTextFile(root + "/" + metatileLabelsFilename, outputText);
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_labels);
ignoreWatchedFileTemporarily(root + "/" + filename);
saveTextFile(root + "/" + filename, outputText);
}

void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
Expand Down Expand Up @@ -1505,20 +1490,32 @@ void Project::loadTilesetMetatiles(Tileset* tileset) {
}
}

QString Project::findMetatileLabelsTileset(QString label) {
for (QString tilesetName : this->tilesetLabelsOrdered) {
QString metatileLabelPrefix = Tileset::getMetatileLabelPrefix(tilesetName);
if (label.startsWith(metatileLabelPrefix))
return tilesetName;
}
return QString();
}

bool Project::readTilesetMetatileLabels() {
metatileLabelsMap.clear();
unusedMetatileLabels.clear();

QString metatileLabelsFilename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_labels);
fileWatcher.addPath(root + "/" + metatileLabelsFilename);

QMap<QString, int> labels = parser.readCDefines(metatileLabelsFilename, QStringList() << "METATILE_");
QMap<QString, int> defines = parser.readCDefines(metatileLabelsFilename, QStringList() << "METATILE_");

for (QString tilesetLabel : this->tilesetLabelsOrdered) {
QString metatileLabelPrefix = Tileset::getMetatileLabelPrefix(tilesetLabel);
for (QString key : labels.keys()) {
if (key.startsWith(metatileLabelPrefix)) {
metatileLabelsMap[tilesetLabel][key] = labels[key];
}
for (QString label : defines.keys()) {
QString tilesetName = findMetatileLabelsTileset(label);
if (!tilesetName.isEmpty()) {
metatileLabelsMap[tilesetName][label] = defines[label];
} else {
// This #define name does not match any existing tileset.
// Save it separately to be outputted later.
unusedMetatileLabels[label] = defines[label];
}
}

Expand Down

0 comments on commit 144b835

Please sign in to comment.