mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-25 18:16:57 -05:00
Parser define maps to hashes
This commit is contained in:
@@ -55,11 +55,12 @@ public:
|
||||
QString readCIncbin(const QString &text, const QString &label);
|
||||
QMap<QString, QString> readCIncbinMulti(const QString &filepath);
|
||||
QStringList readCIncbinArray(const QString &filename, const QString &label);
|
||||
QMap<QString, int> readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error = nullptr);
|
||||
QMap<QString, int> readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error = nullptr);
|
||||
QHash<QString, int> readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error = nullptr);
|
||||
QHash<QString, int> readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error = nullptr);
|
||||
QStringList readCDefineNames(const QString &filename, const QSet<QString> ®exList, QString *error = nullptr);
|
||||
void loadGlobalCDefinesFromFile(const QString &filename, QString *error = nullptr);
|
||||
void loadGlobalCDefines(const QMap<QString,QString> &defines);
|
||||
void loadGlobalCDefines(const QHash<QString,QString> &defines);
|
||||
void resetCDefines();
|
||||
OrderedMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString>& = {});
|
||||
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
||||
@@ -96,13 +97,13 @@ private:
|
||||
|
||||
// The maps of define names to values/expressions that are available while parsing C defines.
|
||||
// As the parser reads and evaluates more defines it will update these maps accordingly.
|
||||
QMap<QString, int> knownDefineValues;
|
||||
QMap<QString, QString> knownDefineExpressions;
|
||||
QHash<QString, int> knownDefineValues;
|
||||
QHash<QString, QString> knownDefineExpressions;
|
||||
|
||||
// Maps of special define names to values/expressions that take precedence over defines encountered while parsing.
|
||||
// Some (like 'TRUE'/'FALSE') are always present in these maps, others may be specified by the user with 'loadGlobalCDefines' / 'loadGlobalCDefinesFromFile'.
|
||||
QMap<QString, int> globalDefineValues;
|
||||
QMap<QString, QString> globalDefineExpressions;
|
||||
QHash<QString, int> globalDefineValues;
|
||||
QHash<QString, QString> globalDefineExpressions;
|
||||
|
||||
int evaluateDefine(const QString &identifier, bool *ok = nullptr);
|
||||
int evaluateExpression(const QString &expression);
|
||||
@@ -115,11 +116,11 @@ private:
|
||||
QString createErrorMessage(const QString &message, const QString &expression);
|
||||
|
||||
struct ParsedDefines {
|
||||
QMap<QString,QString> expressions; // Map of all define names encountered to their expressions
|
||||
QHash<QString,QString> expressions; // Map of all define names encountered to their expressions
|
||||
QStringList filteredNames; // List of define names that matched the search text, in the order that they were encountered
|
||||
};
|
||||
ParsedDefines readCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
QMap<QString, int> evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
QHash<QString, int> evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
bool defineNameMatchesFilter(const QString &name, const QSet<QString> &filterList) const;
|
||||
bool defineNameMatchesFilter(const QString &name, const QSet<QRegularExpression> &filterList) const;
|
||||
QString loadTextFile(const QString &path, QString *error = nullptr);
|
||||
|
||||
@@ -488,11 +488,11 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const
|
||||
}
|
||||
|
||||
// Read all the define names and their expressions in the specified file, then evaluate the ones matching the search text (and any they depend on).
|
||||
QMap<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error) {
|
||||
QHash<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error) {
|
||||
ParsedDefines defines = readCDefines(filename, filterList, useRegex, error);
|
||||
|
||||
// Evaluate defines
|
||||
QMap<QString, int> filteredValues;
|
||||
QHash<QString, int> filteredValues;
|
||||
this->errorMap.clear();
|
||||
while (!defines.filteredNames.isEmpty()) {
|
||||
this->curDefine = defines.filteredNames.takeFirst();
|
||||
@@ -504,12 +504,12 @@ QMap<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QS
|
||||
}
|
||||
|
||||
// Find and evaluate a specific set of defines with known names.
|
||||
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error) {
|
||||
QHash<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error) {
|
||||
return evaluateCDefines(filename, names, false, error);
|
||||
}
|
||||
|
||||
// Find and evaluate an unknown list of defines with a known name pattern.
|
||||
QMap<QString, int> ParseUtil::readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error) {
|
||||
QHash<QString, int> ParseUtil::readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error) {
|
||||
return evaluateCDefines(filename, regexList, true, error);
|
||||
}
|
||||
|
||||
@@ -526,12 +526,17 @@ void ParseUtil::loadGlobalCDefinesFromFile(const QString &filename, QString *err
|
||||
loadGlobalCDefines(readCDefines(filename, {}, false, error).expressions);
|
||||
}
|
||||
|
||||
void ParseUtil::loadGlobalCDefines(const QMap<QString,QString> &defines) {
|
||||
void ParseUtil::loadGlobalCDefines(const QHash<QString,QString> &defines) {
|
||||
this->globalDefineExpressions.insert(defines);
|
||||
}
|
||||
|
||||
void ParseUtil::loadGlobalCDefines(const QMap<QString,QString> &defines) {
|
||||
for (auto it = defines.constBegin(); it != defines.constEnd(); it++)
|
||||
this->globalDefineExpressions.insert(it.key(), it.value());
|
||||
}
|
||||
|
||||
void ParseUtil::resetCDefines() {
|
||||
static const QMap<QString, int> defaultDefineValues = {
|
||||
static const QHash<QString, int> defaultDefineValues = {
|
||||
{"FALSE", 0},
|
||||
{"TRUE", 1},
|
||||
{"SCHAR_MIN", SCHAR_MIN},
|
||||
|
||||
@@ -1481,7 +1481,7 @@ bool Project::readTilesetMetatileLabels() {
|
||||
fileWatcher.addPath(root + "/" + metatileLabelsFilename);
|
||||
|
||||
const QSet<QString> regexList = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix))};
|
||||
const QMap<QString, int> defines = parser.readCDefinesByRegex(metatileLabelsFilename, regexList);
|
||||
const auto defines = parser.readCDefinesByRegex(metatileLabelsFilename, regexList);
|
||||
for (auto i = defines.constBegin(); i != defines.constEnd(); i++) {
|
||||
QString label = i.key();
|
||||
uint32_t metatileId = i.value();
|
||||
@@ -2116,16 +2116,15 @@ bool Project::readFieldmapProperties() {
|
||||
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
const QMap<QString, int> defines = parser.readCDefinesByName(filename, {
|
||||
numTilesPrimaryName,
|
||||
numTilesTotalName,
|
||||
numMetatilesPrimaryName,
|
||||
numPalsPrimaryName,
|
||||
numPalsTotalName,
|
||||
maxMapSizeName,
|
||||
numTilesPerMetatileName,
|
||||
mapOffsetWidthName,
|
||||
mapOffsetHeightName,
|
||||
const auto defines = parser.readCDefinesByName(filename, { numTilesPrimaryName,
|
||||
numTilesTotalName,
|
||||
numMetatilesPrimaryName,
|
||||
numPalsPrimaryName,
|
||||
numPalsTotalName,
|
||||
maxMapSizeName,
|
||||
numTilesPerMetatileName,
|
||||
mapOffsetWidthName,
|
||||
mapOffsetHeightName,
|
||||
});
|
||||
|
||||
auto loadDefine = [defines](const QString name, int * dest, int min, int max) {
|
||||
@@ -2219,16 +2218,15 @@ bool Project::readFieldmapMasks() {
|
||||
const QString elevationMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_elevation);
|
||||
const QString behaviorMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_behavior);
|
||||
const QString layerTypeMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_layer);
|
||||
const QSet<QString> searchNames = {
|
||||
metatileIdMaskName,
|
||||
collisionMaskName,
|
||||
elevationMaskName,
|
||||
behaviorMaskName,
|
||||
layerTypeMaskName,
|
||||
};
|
||||
|
||||
const QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + globalFieldmap);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(globalFieldmap, searchNames);
|
||||
const auto defines = parser.readCDefinesByName(globalFieldmap, { metatileIdMaskName,
|
||||
collisionMaskName,
|
||||
elevationMaskName,
|
||||
behaviorMaskName,
|
||||
layerTypeMaskName,
|
||||
});
|
||||
|
||||
// These mask values are accessible via the settings editor for users who don't have these defines.
|
||||
// If users do have the defines we disable them in the settings editor and direct them to their project files.
|
||||
@@ -2239,8 +2237,8 @@ bool Project::readFieldmapMasks() {
|
||||
|
||||
// Read Block masks
|
||||
auto readBlockMask = [defines](const QString name, uint16_t *value) {
|
||||
auto it = defines.find(name);
|
||||
if (it == defines.end())
|
||||
auto it = defines.constFind(name);
|
||||
if (it == defines.constEnd())
|
||||
return false;
|
||||
*value = static_cast<uint16_t>(it.value());
|
||||
if (*value != it.value()){
|
||||
@@ -2314,7 +2312,7 @@ bool Project::readFieldmapMasks() {
|
||||
// Read #defines for encounter and terrain types to populate in the Tileset Editor dropdowns (if necessary)
|
||||
QString error;
|
||||
if (projectConfig.metatileEncounterTypeMask) {
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_encounter_types)}, &error);
|
||||
const auto defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_encounter_types)}, &error);
|
||||
if (!error.isEmpty()) {
|
||||
logWarn(QString("Failed to read encounter type constants from '%1': %2").arg(globalFieldmap).arg(error));
|
||||
error = QString();
|
||||
@@ -2325,7 +2323,7 @@ bool Project::readFieldmapMasks() {
|
||||
}
|
||||
}
|
||||
if (projectConfig.metatileTerrainTypeMask) {
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_terrain_types)}, &error);
|
||||
const auto defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_terrain_types)}, &error);
|
||||
if (!error.isEmpty()) {
|
||||
logWarn(QString("Failed to read terrain type constants from '%1': %2").arg(globalFieldmap).arg(error));
|
||||
error = QString();
|
||||
@@ -2673,7 +2671,7 @@ bool Project::readMetatileBehaviors() {
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_behaviors);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QString error;
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)}, &error);
|
||||
const auto defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)}, &error);
|
||||
if (defines.isEmpty() && projectConfig.metatileBehaviorMask) {
|
||||
// Not having any metatile behavior names is ok (their values will be displayed instead)
|
||||
// but if the user's metatiles can have nonzero values then warn them, as they likely want names.
|
||||
@@ -2710,9 +2708,14 @@ bool Project::readObjEventGfxConstants() {
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_events);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QString error;
|
||||
this->gfxDefines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)}, &error);
|
||||
const auto defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)}, &error);
|
||||
if (!error.isEmpty())
|
||||
logWarn(QString("Failed to read object event graphics constants from '%1': %2").arg(filename).arg(error));
|
||||
|
||||
this->gfxDefines.clear();
|
||||
for (auto it = defines.constBegin(); it != defines.constEnd(); it++)
|
||||
this->gfxDefines.insert(it.key(), it.value());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2720,7 +2723,7 @@ bool Project::readMiscellaneousConstants() {
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_global);
|
||||
const QString maxObjectEventsName = projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(filename, {maxObjectEventsName});
|
||||
const auto defines = parser.readCDefinesByName(filename, {maxObjectEventsName});
|
||||
|
||||
this->maxObjectEvents = 64; // Default value
|
||||
auto it = defines.find(maxObjectEventsName);
|
||||
@@ -2953,9 +2956,7 @@ QPixmap Project::getEventPixmap(const QString &gfxName, int frame, bool hFlip) {
|
||||
// Invalid gfx constant. If this is a number, try to use that instead.
|
||||
bool ok;
|
||||
int gfxNum = ParseUtil::gameStringToInt(gfxName, &ok);
|
||||
if (ok && gfxNum < this->gfxDefines.count()) {
|
||||
gfx = this->eventGraphicsMap.value(this->gfxDefines.key(gfxNum, "NULL"), nullptr);
|
||||
}
|
||||
if (ok) gfx = this->eventGraphicsMap.value(this->gfxDefines.key(gfxNum, "NULL"), nullptr);
|
||||
}
|
||||
if (gfx && !gfx->loaded) {
|
||||
// This is the first request for this event's sprite. We'll attempt to load it now.
|
||||
|
||||
Reference in New Issue
Block a user