Read tileset graphics paths from C

This commit is contained in:
GriffinR 2022-10-07 11:47:05 -04:00 committed by Marcus Huderle
parent 70528bbc56
commit 9b4c55106b
4 changed files with 55 additions and 14 deletions

View file

@ -48,8 +48,10 @@ public:
QStringList readCArray(const QString &text, const QString &label);
QMap<QString, QString> readNamedIndexCArray(const QString &text, const QString &label);
QString readCIncbin(const QString &text, const QString &label);
QStringList readCIncbinArray(const QString &filename, const QString &label);
QMap<QString, int> readCDefines(const QString &filename, const QStringList &prefixes, QMap<QString, int> = { });
QStringList readCDefinesSorted(const QString&, const QStringList&, const QMap<QString, int>& = { });
QMap<QString, QMap<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
QStringList getLabelValues(const QList<QStringList>&, const QString&);
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath);
@ -70,7 +72,6 @@ public:
static QStringList splitShellCommand(QStringView command);
static bool gameStringToBool(QString gameString);
static QMap<QString, QMap<QString, QString>> readCStructs(const QString &filePath, const QString &target = "", const QHash<int, QString> memberMap = { });
private:
QString root;

View file

@ -270,6 +270,30 @@ QString ParseUtil::readCIncbin(const QString &filename, const QString &label) {
return path;
}
QStringList ParseUtil::readCIncbinArray(const QString &filename, const QString &label) {
QStringList paths;
if (label.isNull()) {
return paths;
}
this->text = readTextFile(this->root + "/" + filename);
// Get the text starting after the label all the way to the definition's end
QRegularExpression re(QString("\\b%1\\b(.*?)};").arg(label), QRegularExpression::DotMatchesEverythingOption);
QRegularExpressionMatch arrayMatch = re.match(this->text);
if (!arrayMatch.hasMatch())
return paths;
// Extract incbin paths from the array
re.setPattern("INCBIN_[US][0-9][0-9]?\\(\\s*\"([^\"]*)\"\\s*\\)");
QRegularExpressionMatchIterator iter = re.globalMatch(arrayMatch.captured(1));
while (iter.hasNext()) {
paths.append(iter.next().captured(1));
}
return paths;
}
QMap<QString, int> ParseUtil::readCDefines(const QString &filename,
const QStringList &prefixes,
QMap<QString, int> allDefines)
@ -389,14 +413,15 @@ bool ParseUtil::gameStringToBool(QString gameString) {
return num != 0;
}
QMap<QString, QMap<QString, QString>> ParseUtil::readCStructs(const QString &filePath, const QString &target, const QHash<int, QString> memberMap) {
QMap<QString, QMap<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> memberMap) {
QString filePath = this->root + "/" + filename;
auto cParser = fex::Parser();
auto tokens = fex::Lexer().LexFile(filePath.toStdString());
auto structs = cParser.ParseTopLevelObjects(tokens);
QMap<QString, QMap<QString, QString>> structMaps;
for (auto it = structs.begin(); it != structs.end(); it++) {
QString structLabel = QString::fromStdString(it->first);
if (!target.isEmpty() && target != structLabel) continue; // Speed up parsing if only looking for a particular symbol
if (!label.isEmpty() && label != structLabel) continue; // Speed up parsing if only looking for a particular symbol
QMap<QString, QString> values;
int i = 0;
for (const fex::ArrayValue &v : it->second.values()) {

View file

@ -169,6 +169,7 @@ bool Tileset::appendToHeaders(QString root, QString friendlyName, bool usingAsm)
}
// TODO: Interpet isSecondary to remove primary argument here and below
// TODO: friendlyName.toLower() is not the usual format for tileset folders
bool Tileset::appendToGraphics(QString root, QString friendlyName, bool primary, bool usingAsm) {
QString graphicsFile = root + "/" + (usingAsm ? projectConfig.getFilePath(ProjectFilePath::tilesets_graphics_asm)
: projectConfig.getFilePath(ProjectFilePath::tilesets_graphics));

View file

@ -1153,7 +1153,7 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) {
}
} else {
// Read C tileset header
QMap<QString, QMap<QString, QString>> structs = ParseUtil::readCStructs(this->root + "/" + projectConfig.getFilePath(ProjectFilePath::tilesets_headers), label);
QMap<QString, QMap<QString, QString>> structs = parser.readCStructs(projectConfig.getFilePath(ProjectFilePath::tilesets_headers), label);
if (!structs.contains(label)) {
return nullptr;
}
@ -1519,12 +1519,26 @@ void Project::readTilesetPaths(Tileset* tileset) {
tileset->metatiles_path = root + '/' + metatiles_values.value(0).section('"', 1, 1);
if (!metatile_attrs_values.isEmpty())
tileset->metatile_attrs_path = root + '/' + metatile_attrs_values.value(0).section('"', 1, 1);
for (const auto &value : palettes_values) {
for (const auto &value : palettes_values)
tileset->palettePaths.append(this->fixPalettePath(root + '/' + value.section('"', 1, 1)));
}
} else {
// Read C tileset data files
// TODO
const QString graphicsFile = projectConfig.getFilePath(ProjectFilePath::tilesets_graphics);
const QString metatilesFile = projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles);
const QString tilesImagePath = parser.readCIncbin(graphicsFile, tileset->tiles_label);
const QStringList palettePaths = parser.readCIncbinArray(graphicsFile, tileset->palettes_label);
const QString metatilesPath = parser.readCIncbin(metatilesFile, tileset->metatiles_label);
const QString metatileAttrsPath = parser.readCIncbin(metatilesFile, tileset->metatile_attrs_label);
if (!tilesImagePath.isEmpty())
tileset->tilesImagePath = this->fixGraphicPath(root + '/' + tilesImagePath);
if (!metatilesPath.isEmpty())
tileset->metatiles_path = root + '/' + metatilesPath;
if (!metatileAttrsPath.isEmpty())
tileset->metatile_attrs_path = root + '/' + metatileAttrsPath;
for (const auto &path : palettePaths)
tileset->palettePaths.append(this->fixPalettePath(root + '/' + path));
}
// Construct the expected path of the tileset's graphics, in case Porymap couldn't find any paths.
@ -1934,13 +1948,13 @@ bool Project::readTilesetLabels() {
this->tilesetLabels.insert("secondary", secondaryTilesets);
this->tilesetLabelsOrdered.clear();
QString filename = this->root + "/" + projectConfig.getFilePath(ProjectFilePath::tilesets_headers);
QFileInfo fileInfo(filename);
QString filename = projectConfig.getFilePath(ProjectFilePath::tilesets_headers);
QFileInfo fileInfo(this->root + "/" + filename);
if (!fileInfo.exists() || !fileInfo.isFile()) {
// If the tileset headers file is missing, the user may still have the old assembly format.
this->usingAsmTilesets = true;
QString asm_filename = this->root + "/" + projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm);
QString text = parser.readTextFile(asm_filename);
QString asm_filename = projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm);
QString text = parser.readTextFile(this->root + "/" + asm_filename);
if (text.isEmpty()) {
logError(QString("Failed to read tileset labels from '%1' or '%2'.").arg(filename).arg(asm_filename));
return false;
@ -1959,7 +1973,7 @@ bool Project::readTilesetLabels() {
filename = asm_filename; // For error reporting further down
} else {
this->usingAsmTilesets = false;
QMap<QString, QMap<QString, QString>> structs = ParseUtil::readCStructs(filename);
QMap<QString, QMap<QString, QString>> structs = parser.readCStructs(filename);
QStringList labels = structs.keys();
for (const auto tilesetLabel : labels) {
if (tilesetLabel.isEmpty()) continue;
@ -2525,8 +2539,8 @@ bool Project::readEventGraphics() {
{14, "images"},
};
QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
QMap<QString, QMap<QString, QString>> gfxInfos = ParseUtil::readCStructs(filepath, "", gfxInfoMemberMap);
QString filepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
QMap<QString, QMap<QString, QString>> gfxInfos = parser.readCStructs(filepath, "", gfxInfoMemberMap);
for (QString gfxName : gfxNames) {
EventGraphics * eventGraphics = new EventGraphics;