Add identifier config settings

This commit is contained in:
GriffinR 2023-12-18 02:19:12 -05:00
parent bfb827b736
commit 6d995cee9b
20 changed files with 439 additions and 213 deletions

View file

@ -170,6 +170,61 @@ enum BaseGameVersion {
pokeemerald,
};
enum ProjectIdentifier {
symbol_facing_directions,
symbol_obj_event_gfx_pointers,
symbol_pokemon_icon_table,
symbol_wild_encounters,
symbol_heal_locations,
symbol_spawn_points,
symbol_spawn_maps,
symbol_spawn_npcs,
symbol_attribute_table,
symbol_tilesets_prefix,
define_obj_event_count,
define_min_level,
define_max_level,
define_tiles_primary,
define_tiles_total,
define_metatiles_primary,
define_pals_primary,
define_pals_total,
define_map_size,
define_mask_metatile,
define_mask_collision,
define_mask_elevation,
define_mask_behavior,
define_mask_layer,
define_attribute_behavior,
define_attribute_layer,
define_attribute_terrain,
define_attribute_encounter,
define_metatile_label_prefix,
define_heal_locations_prefix,
define_spawn_prefix,
define_map_prefix,
define_map_dynamic,
define_map_empty,
define_map_section_prefix,
define_map_section_empty,
define_map_section_count,
regex_behaviors,
regex_obj_event_gfx,
regex_items,
regex_flags,
regex_vars,
regex_movement_types,
regex_map_types,
regex_battle_scenes,
regex_weather,
regex_coord_event_weather,
regex_secret_bases,
regex_sign_facing_directions,
regex_trainer_types,
regex_music,
regex_species,
};
enum ProjectFilePath {
data_map_folders,
data_scripts_folders,
@ -250,11 +305,12 @@ public:
this->blockElevationMask = 0xF000;
this->warpBehaviors = defaultWarpBehaviors;
this->warpBehaviorWarningDisabled = false;
this->identifiers.clear();
this->readKeys.clear();
}
static const QMap<ProjectIdentifier, QPair<QString, QString>> defaultIdentifiers;
static const QMap<ProjectFilePath, std::pair<QString, QString>> defaultPaths;
static const QStringList versionStrings;
static const QStringList defaultWarpBehaviors;
void reset(BaseGameVersion baseGameVersion);
void setBaseGameVersion(BaseGameVersion baseGameVersion);
BaseGameVersion getBaseGameVersion();
@ -299,10 +355,16 @@ public:
QString getDefaultSecondaryTileset();
void setDefaultPrimaryTileset(QString tilesetName);
void setDefaultSecondaryTileset(QString tilesetName);
void setFilePath(QString pathId, QString path);
void setFilePath(ProjectFilePath pathId, QString path);
QString getFilePath(QString defaultPath, bool customOnly = false);
QString getFilePath(ProjectFilePath pathId, bool customOnly = false);
void setFilePath(const QString &pathId, const QString &path);
void setFilePath(ProjectFilePath pathId, const QString &path);
QString getCustomFilePath(ProjectFilePath pathId);
QString getCustomFilePath(const QString &pathId);
QString getFilePath(ProjectFilePath pathId);
void setIdentifier(ProjectIdentifier id, const QString &text);
void setIdentifier(const QString &id, const QString &text);
QString getCustomIdentifier(ProjectIdentifier id);
QString getCustomIdentifier(const QString &id);
QString getIdentifier(ProjectIdentifier id);
void setPrefabFilepath(QString filepath);
QString getPrefabFilepath();
void setPrefabImportPrompted(bool prompted);
@ -345,18 +407,6 @@ public:
void setWarpBehaviorWarningDisabled(bool disabled);
bool getWarpBehaviorWarningDisabled();
// TODO: Replace these once there's generic support for editing project names
static const QString metatileIdMaskName;
static const QString collisionMaskName;
static const QString elevationMaskName;
static const QString behaviorMaskName;
static const QString layerTypeMaskName;
static const QString behaviorTableName;
static const QString layerTypeTableName;
static const QString terrainTypeTableName;
static const QString encounterTypeTableName;
static const QString attrTableName;
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@ -364,8 +414,11 @@ protected:
virtual void onNewConfigFileCreated() override;
virtual void setUnreadKeys() override;
private:
static const QStringList defaultWarpBehaviors;
BaseGameVersion baseGameVersion;
QString projectDir;
QMap<ProjectIdentifier, QString> identifiers;
QMap<ProjectFilePath, QString> filePaths;
bool usePoryScript;
bool useCustomBorderSize;

View file

@ -71,7 +71,7 @@ public:
QList<int> metatileLayerOrder;
QList<float> metatileLayerOpacity;
void setName(QString mapName);
static QString mapConstantFromName(QString mapName);
static QString mapConstantFromName(QString mapName, bool includePrefix = true);
int getWidth();
int getHeight();
int getBorderWidth();

View file

@ -54,8 +54,8 @@ 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> readCDefinesByPrefix(const QString &filename, const QStringList &prefixes);
QMap<QString, int> readCDefinesByName(const QString &filename, const QStringList &defineNames);
QMap<QString, int> readCDefinesByPrefix(const QString &filename, QStringList prefixes);
QMap<QString, int> readCDefinesByName(const QString &filename, QStringList names);
QStringList readCDefineNames(const QString&, const QStringList&);
QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);

View file

@ -21,7 +21,10 @@ class Project;
struct LayoutSquare
{
LayoutSquare() : map_section("MAPSEC_NONE"), x(-1), y(-1), has_map(false) {}
LayoutSquare() : x(-1), y(-1), has_map(false) {
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix);
map_section = prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty);
}
QString map_section;
int x;
int y;
@ -144,6 +147,10 @@ public:
void emitDisplay();
const QString section_prefix;
const QString default_map_section;
const QString count_map_section;
signals:
void mapNeedsDisplaying();

View file

@ -26,8 +26,7 @@ struct EventGraphics
bool inanimate;
};
// The constant and displayed name of the special map value used by warps with multiple potential destinations
static QString DYNAMIC_MAP_CONSTANT = "MAP_DYNAMIC";
// The displayed name of the special map value used by warps with multiple potential destinations
static QString DYNAMIC_MAP_NAME = "Dynamic";
class Project : public QObject
@ -215,7 +214,7 @@ public:
QString getDefaultPrimaryTilesetLabel();
QString getDefaultSecondaryTilesetLabel();
QString getDynamicMapDefineName();
void updateTilesetMetatileLabels(Tileset *tileset);
QString buildMetatileLabelsText(const QMap<QString, int> defines);
QString findMetatileLabelsTileset(QString label);
@ -248,6 +247,7 @@ private:
void saveHealLocationsData(Map *map);
void saveHealLocationsConstants();
QString getHealLocationsTableName();
void ignoreWatchedFileTemporarily(QString filepath);

View file

@ -47,16 +47,64 @@ const QStringList ProjectConfig::defaultWarpBehaviors = {
"MB_BRIDGE_OVER_OCEAN",
};
const QString ProjectConfig::metatileIdMaskName = "MAPGRID_METATILE_ID_MASK";
const QString ProjectConfig::collisionMaskName = "MAPGRID_COLLISION_MASK";
const QString ProjectConfig::elevationMaskName = "MAPGRID_ELEVATION_MASK";
const QString ProjectConfig::behaviorMaskName = "METATILE_ATTR_BEHAVIOR_MASK";
const QString ProjectConfig::layerTypeMaskName = "METATILE_ATTR_LAYER_MASK";
const QString ProjectConfig::behaviorTableName = "METATILE_ATTRIBUTE_BEHAVIOR";
const QString ProjectConfig::layerTypeTableName = "METATILE_ATTRIBUTE_LAYER_TYPE";
const QString ProjectConfig::terrainTypeTableName = "METATILE_ATTRIBUTE_TERRAIN";
const QString ProjectConfig::encounterTypeTableName = "METATILE_ATTRIBUTE_ENCOUNTER_TYPE";
const QString ProjectConfig::attrTableName = "sMetatileAttrMasks";
// TODO: symbol_wild_encounters should ultimately be removed from the table below. We can determine this name when we read the project.
const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIdentifiers = {
// Symbols
{ProjectIdentifier::symbol_facing_directions, {"symbol_facing_directions", "gInitialMovementTypeFacingDirections"}},
{ProjectIdentifier::symbol_obj_event_gfx_pointers, {"symbol_obj_event_gfx_pointers", "gObjectEventGraphicsInfoPointers"}},
{ProjectIdentifier::symbol_pokemon_icon_table, {"symbol_pokemon_icon_table", "gMonIconTable"}},
{ProjectIdentifier::symbol_wild_encounters, {"symbol_wild_encounters", "gWildMonHeaders"}},
{ProjectIdentifier::symbol_heal_locations, {"symbol_heal_locations", "sHealLocations"}},
{ProjectIdentifier::symbol_spawn_points, {"symbol_spawn_points", "sSpawnPoints"}},
{ProjectIdentifier::symbol_spawn_maps, {"symbol_spawn_maps", "sWhiteoutRespawnHealCenterMapIdxs"}},
{ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "sWhiteoutRespawnHealerNpcIds"}},
{ProjectIdentifier::symbol_attribute_table, {"symbol_attribute_table", "sMetatileAttrMasks"}},
{ProjectIdentifier::symbol_tilesets_prefix, {"symbol_tilesets_prefix", "gTileset_"}},
// Defines
{ProjectIdentifier::define_obj_event_count, {"define_obj_event_count", "OBJECT_EVENT_TEMPLATES_COUNT"}},
{ProjectIdentifier::define_min_level, {"define_min_level", "MIN_LEVEL"}},
{ProjectIdentifier::define_max_level, {"define_max_level", "MAX_LEVEL"}},
{ProjectIdentifier::define_tiles_primary, {"define_tiles_primary", "NUM_TILES_IN_PRIMARY"}},
{ProjectIdentifier::define_tiles_total, {"define_tiles_total", "NUM_TILES_TOTAL"}},
{ProjectIdentifier::define_metatiles_primary, {"define_metatiles_primary", "NUM_METATILES_IN_PRIMARY"}},
{ProjectIdentifier::define_pals_primary, {"define_pals_primary", "NUM_PALS_IN_PRIMARY"}},
{ProjectIdentifier::define_pals_total, {"define_pals_total", "NUM_PALS_TOTAL"}},
{ProjectIdentifier::define_map_size, {"define_map_size", "MAX_MAP_DATA_SIZE"}},
{ProjectIdentifier::define_mask_metatile, {"define_mask_metatile", "MAPGRID_METATILE_ID_MASK"}},
{ProjectIdentifier::define_mask_collision, {"define_mask_collision", "MAPGRID_COLLISION_MASK"}},
{ProjectIdentifier::define_mask_elevation, {"define_mask_elevation", "MAPGRID_ELEVATION_MASK"}},
{ProjectIdentifier::define_mask_behavior, {"define_mask_behavior", "METATILE_ATTR_BEHAVIOR_MASK"}},
{ProjectIdentifier::define_mask_layer, {"define_mask_layer", "METATILE_ATTR_LAYER_MASK"}},
{ProjectIdentifier::define_attribute_behavior, {"define_attribute_behavior", "METATILE_ATTRIBUTE_BEHAVIOR"}},
{ProjectIdentifier::define_attribute_layer, {"define_attribute_layer", "METATILE_ATTRIBUTE_LAYER_TYPE"}},
{ProjectIdentifier::define_attribute_terrain, {"define_attribute_terrain", "METATILE_ATTRIBUTE_TERRAIN"}},
{ProjectIdentifier::define_attribute_encounter, {"define_attribute_encounter", "METATILE_ATTRIBUTE_ENCOUNTER_TYPE"}},
{ProjectIdentifier::define_metatile_label_prefix, {"define_metatile_label_prefix", "METATILE_"}},
{ProjectIdentifier::define_heal_locations_prefix, {"define_heal_locations_prefix", "HEAL_LOCATION_"}},
{ProjectIdentifier::define_spawn_prefix, {"define_spawn_prefix", "SPAWN_"}},
{ProjectIdentifier::define_map_prefix, {"define_map_prefix", "MAP_"}},
{ProjectIdentifier::define_map_dynamic, {"define_map_dynamic", "DYNAMIC"}},
{ProjectIdentifier::define_map_empty, {"define_map_empty", "UNDEFINED"}},
{ProjectIdentifier::define_map_section_prefix, {"define_map_section_prefix", "MAPSEC_"}},
{ProjectIdentifier::define_map_section_empty, {"define_map_section_empty", "NONE"}},
{ProjectIdentifier::define_map_section_count, {"define_map_section_count", "COUNT"}},
// Regex
{ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}},
{ProjectIdentifier::regex_obj_event_gfx, {"regex_obj_event_gfx", "\\bOBJ_EVENT_GFX_"}},
{ProjectIdentifier::regex_items, {"regex_items", "\\bITEM_(?!(B_)?USE_)"}}, // Exclude ITEM_USE_ and ITEM_B_USE_ constants
{ProjectIdentifier::regex_flags, {"regex_flags", "\\bFLAG_"}},
{ProjectIdentifier::regex_vars, {"regex_vars", "\\bVAR_"}},
{ProjectIdentifier::regex_movement_types, {"regex_movement_types", "\\bMOVEMENT_TYPE_"}},
{ProjectIdentifier::regex_map_types, {"regex_map_types", "\\bMAP_TYPE_"}},
{ProjectIdentifier::regex_battle_scenes, {"regex_battle_scenes", "\\bMAP_BATTLE_SCENE_"}},
{ProjectIdentifier::regex_weather, {"regex_weather", "\\bWEATHER_"}},
{ProjectIdentifier::regex_coord_event_weather, {"regex_coord_event_weather", "\\bCOORD_EVENT_WEATHER_"}},
{ProjectIdentifier::regex_secret_bases, {"regex_secret_bases", "\\bSECRET_BASE_[A-Za-z0-9_]*_[0-9]+"}},
{ProjectIdentifier::regex_sign_facing_directions, {"regex_sign_facing_directions", "\\bBG_EVENT_PLAYER_FACING_"}},
{ProjectIdentifier::regex_trainer_types, {"regex_trainer_types", "\\bTRAINER_TYPE_"}},
{ProjectIdentifier::regex_music, {"regex_music", "\\b(SE|MUS)_"}},
{ProjectIdentifier::regex_species, {"regex_species", "\\bSPECIES_"}},
};
const QMap<ProjectFilePath, std::pair<QString, QString>> ProjectConfig::defaultPaths = {
{ProjectFilePath::data_map_folders, { "data_map_folders", "data/maps/"}},
@ -108,6 +156,13 @@ const QMap<ProjectFilePath, std::pair<QString, QString>> ProjectConfig::defaultP
{ProjectFilePath::pokemon_gfx, { "pokemon_gfx", "graphics/pokemon/"}},
};
ProjectIdentifier reverseDefaultIdentifier(QString str) {
for (auto i = ProjectConfig::defaultIdentifiers.cbegin(), end = ProjectConfig::defaultIdentifiers.cend(); i != end; i++) {
if (i.value().first == str) return i.key();
}
return static_cast<ProjectIdentifier>(-1);
}
ProjectFilePath reverseDefaultPaths(QString str) {
for (auto it = ProjectConfig::defaultPaths.constKeyValueBegin(); it != ProjectConfig::defaultPaths.constKeyValueEnd(); ++it) {
if ((*it).second.first == str) return (*it).first;
@ -751,6 +806,13 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
} else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
}
} else if (key.startsWith("ident/")) {
auto identifierId = reverseDefaultIdentifier(key.mid(6));
if (identifierId != static_cast<ProjectIdentifier>(-1)) {
this->setIdentifier(identifierId, value);
} else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
}
} else if (key == "prefabs_filepath") {
this->prefabFilepath = value;
} else if (key == "prefabs_import_prompted") {
@ -863,6 +925,10 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
const QString path = i.value();
if (!path.isEmpty()) map.insert("pokemon_icon_path/" + i.key(), path);
}
for (auto i = this->identifiers.cbegin(), end = this->identifiers.cend(); i != end; i++) {
// TODO: Test to ensure empties aren't output in config
map.insert("ident/"+defaultIdentifiers.value(i.key()).first, i.value());
}
map.insert("collision_sheet_path", this->collisionSheetPath);
map.insert("collision_sheet_width", QString::number(this->collisionSheetWidth));
map.insert("collision_sheet_height", QString::number(this->collisionSheetHeight));
@ -909,7 +975,7 @@ QString ProjectConfig::getProjectDir() {
return this->projectDir;
}
void ProjectConfig::setFilePath(ProjectFilePath pathId, QString path) {
void ProjectConfig::setFilePath(ProjectFilePath pathId, const QString &path) {
if (!defaultPaths.contains(pathId)) return;
if (path.isEmpty()) {
this->filePaths.remove(pathId);
@ -918,18 +984,20 @@ void ProjectConfig::setFilePath(ProjectFilePath pathId, QString path) {
}
}
void ProjectConfig::setFilePath(QString defaultPath, QString newPath) {
this->setFilePath(reverseDefaultPaths(defaultPath), newPath);
void ProjectConfig::setFilePath(const QString &pathId, const QString &path) {
this->setFilePath(reverseDefaultPaths(pathId), path);
}
QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool customOnly) {
const QString customPath = this->filePaths.value(pathId);
QString ProjectConfig::getCustomFilePath(ProjectFilePath pathId) {
return this->filePaths.value(pathId);
}
// When reading custom filepaths for the settings editor we don't care
// about the default path or whether the custom path exists.
if (customOnly)
return customPath;
QString ProjectConfig::getCustomFilePath(const QString &pathId) {
return this->getCustomFilePath(reverseDefaultPaths(pathId));
}
QString ProjectConfig::getFilePath(ProjectFilePath pathId) {
const QString customPath = this->getCustomFilePath(pathId);
if (!customPath.isEmpty()) {
// A custom filepath has been specified. If the file/folder exists, use that.
const QString absCustomPath = this->projectDir + QDir::separator() + customPath;
@ -943,8 +1011,33 @@ QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool customOnly) {
}
QString ProjectConfig::getFilePath(QString defaultPath, bool customOnly) {
return this->getFilePath(reverseDefaultPaths(defaultPath), customOnly);
void ProjectConfig::setIdentifier(ProjectIdentifier id, const QString &text) {
if (!defaultIdentifiers.contains(id)) return;
QString copy(text);
if (copy.isEmpty()) {
this->identifiers.remove(id);
} else {
this->identifiers[id] = copy;
}
}
void ProjectConfig::setIdentifier(const QString &id, const QString &text) {
this->setIdentifier(reverseDefaultIdentifier(id), text);
}
QString ProjectConfig::getCustomIdentifier(ProjectIdentifier id) {
return this->identifiers.value(id);
}
QString ProjectConfig::getCustomIdentifier(const QString &id) {
return this->getCustomIdentifier(reverseDefaultIdentifier(id));
}
QString ProjectConfig::getIdentifier(ProjectIdentifier id) {
const QString customText = this->getCustomIdentifier(id);
if (!customText.isEmpty())
return customText;
return defaultIdentifiers.contains(id) ? defaultIdentifiers[id].second : QString();
}
void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) {

View file

@ -372,13 +372,14 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
this->setTargetID(ParseUtil::jsonToInt(json["target_local_id"]));
// Ensure the target map constant is valid before adding it to the events.
const QString dynamicMapConstant = project->getDynamicMapDefineName();
QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
if (project->mapConstantsToMapNames.contains(mapConstant)) {
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant));
} else if (mapConstant == DYNAMIC_MAP_CONSTANT) {
} else if (mapConstant == dynamicMapConstant) {
this->setTargetMap(DYNAMIC_MAP_NAME);
} else {
logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(DYNAMIC_MAP_CONSTANT));
logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
this->setTargetMap(DYNAMIC_MAP_NAME);
}
@ -483,13 +484,14 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
this->setDestinationWarpID(ParseUtil::jsonToQString(json["dest_warp_id"]));
// Ensure the warp destination map constant is valid before adding it to the warps.
const QString dynamicMapConstant = project->getDynamicMapDefineName();
QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
if (project->mapConstantsToMapNames.contains(mapConstant)) {
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant));
} else if (mapConstant == DYNAMIC_MAP_CONSTANT) {
} else if (mapConstant == dynamicMapConstant) {
this->setDestinationMap(DYNAMIC_MAP_NAME);
} else {
logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(DYNAMIC_MAP_CONSTANT));
logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
this->setDestinationMap(DYNAMIC_MAP_NAME);
}
@ -913,15 +915,16 @@ OrderedJson::object HealLocationEvent::buildEventJson(Project *) {
}
void HealLocationEvent::setDefaultValues(Project *) {
this->setElevation(3);
this->setElevation(projectConfig.getDefaultElevation());
if (!this->getMap())
return;
bool respawnEanbled = projectConfig.getHealLocationRespawnDataEnabled();
QString mapConstant = Map::mapConstantFromName(this->getMap()->name).remove(0,4);
QString prefix = respawnEanbled ? "SPAWN_" : "HEAL_LOCATION_";
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
const QString mapConstant = Map::mapConstantFromName(this->getMap()->name, false);
const QString prefix = projectConfig.getIdentifier(respawnEnabled ? ProjectIdentifier::define_spawn_prefix
: ProjectIdentifier::define_heal_locations_prefix);
this->setLocationName(mapConstant);
this->setIdName(prefix + mapConstant);
if (respawnEanbled) {
if (respawnEnabled) {
this->setRespawnMap(this->getMap()->name);
this->setRespawnNPC(1);
}

View file

@ -26,7 +26,7 @@ HealLocation HealLocation::fromEvent(Event *fromEvent) {
healLocation.y = event->getY();
if (projectConfig.getHealLocationRespawnDataEnabled()) {
healLocation.respawnNPC = event->getRespawnNPC();
healLocation.respawnMap = Map::mapConstantFromName(event->getRespawnMap()).remove(0,4);
healLocation.respawnMap = Map::mapConstantFromName(event->getRespawnMap(), false);
}
return healLocation;
}

View file

@ -29,11 +29,12 @@ void Map::setName(QString mapName) {
constantName = mapConstantFromName(mapName);
}
QString Map::mapConstantFromName(QString mapName) {
QString Map::mapConstantFromName(QString mapName, bool includePrefix) {
// Transform map names of the form 'GraniteCave_B1F` into map constants like 'MAP_GRANITE_CAVE_B1F'.
static const QRegularExpression caseChange("([a-z])([A-Z])");
QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2");
QString withMapAndUppercase = "MAP_" + nameWithUnderscores.toUpper();
const QString prefix = includePrefix ? projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) : "";
QString withMapAndUppercase = prefix + nameWithUnderscores.toUpper();
static const QRegularExpression underscores("_+");
QString constantName = withMapAndUppercase.replace(underscores, "_");

View file

@ -425,12 +425,14 @@ QMap<QString, int> ParseUtil::readCDefines(const QString &filename, const QStrin
}
// Find and evaluate an unknown list of defines with a known name prefix.
QMap<QString, int> ParseUtil::readCDefinesByPrefix(const QString &filename, const QStringList &prefixes) {
QMap<QString, int> ParseUtil::readCDefinesByPrefix(const QString &filename, QStringList prefixes) {
prefixes.removeDuplicates();
return this->readCDefines(filename, prefixes, false);
}
// Find and evaluate a specific set of defines with known names.
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QStringList &names) {
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, QStringList names) {
names.removeDuplicates();
return this->readCDefines(filename, names, true);
}

View file

@ -17,7 +17,11 @@ using std::make_shared;
RegionMap::RegionMap(Project *project) {
RegionMap::RegionMap(Project *project) :
section_prefix(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix)),
default_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty)),
count_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_count))
{
this->project = project;
}
@ -146,7 +150,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
LayoutSquare square;
square.map_section = square_section_name;
square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
square.has_map = (square_section_name != this->default_map_section && !square_section_name.isEmpty());
square.x = x;
square.y = y;
@ -204,7 +208,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
LayoutSquare square;
square.map_section = square_section_name;
square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
square.has_map = (square_section_name != this->default_map_section && !square_section_name.isEmpty());
square.x = x;
square.y = y;
layout.append(square);
@ -228,7 +232,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
this->layout_qualifiers = qualifiers + " " + type;
this->layout_array_label = label;
static const QRegularExpression reSec("(?<sec>MAPSEC_[A-Za-z0-9_]+)");
static const QRegularExpression reSec(QString("(?<sec>%1[A-Za-z0-9_]+)").arg(this->section_prefix));
QRegularExpressionMatchIterator k = reSec.globalMatch(text);
QList<LayoutSquare> layout;
@ -242,7 +246,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
LayoutSquare square;
square.map_section = sec;
square.has_map = (sec != "MAPSEC_NONE" && !sec.isEmpty());
square.has_map = (sec != this->default_map_section && !sec.isEmpty());
square.x = x;
square.y = y;
layout.append(square);
@ -283,7 +287,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
QString square_section_name = section.trimmed();
LayoutSquare square;
square.map_section = square_section_name;
square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
square.has_map = (square_section_name != this->default_map_section && !square_section_name.isEmpty());
square.x = x;
square.y = y;
layout.append(square);
@ -454,7 +458,7 @@ void RegionMap::saveLayout() {
}
void RegionMap::resetSquare(int index) {
this->layouts[this->current_layer][index].map_section = "MAPSEC_NONE";
this->layouts[this->current_layer][index].map_section = this->default_map_section;
this->layouts[this->current_layer][index].has_map = false;
}
@ -473,7 +477,7 @@ void RegionMap::replaceSection(QString oldSection, QString newSection) {
for (auto &square : this->layouts[this->current_layer]) {
if (square.map_section == oldSection) {
square.map_section = newSection;
square.has_map = (newSection != "MAPSEC_NONE");
square.has_map = (newSection != this->default_map_section);
}
}
}
@ -482,11 +486,11 @@ void RegionMap::swapSections(QString secA, QString secB) {
for (auto &square : this->layouts[this->current_layer]) {
if (square.map_section == secA) {
square.map_section = secB;
square.has_map = (square.map_section != "MAPSEC_NONE");
square.has_map = (square.map_section != this->default_map_section);
}
else if (square.map_section == secB) {
square.map_section = secA;
square.has_map = (square.map_section != "MAPSEC_NONE");
square.has_map = (square.map_section != this->default_map_section);
}
}
}
@ -725,7 +729,7 @@ void RegionMap::setSquareMapSection(int index, QString section) {
int layoutIndex = tilemapToLayoutIndex(index);
if (!(layoutIndex < 0 || !this->layouts.contains(this->current_layer))) {
this->layouts[this->current_layer][layoutIndex].map_section = section;
this->layouts[this->current_layer][layoutIndex].has_map = !(section == "MAPSEC_NONE" || section.isEmpty());
this->layouts[this->current_layer][layoutIndex].has_map = !(section == this->default_map_section || section.isEmpty());
}
}
@ -780,7 +784,7 @@ QString RegionMap::fixCase(QString caps) {
QString camel;
static const QRegularExpression re_braced("({.*})");
for (auto ch : caps.remove(re_braced).remove("MAPSEC")) {
for (auto ch : caps.remove(re_braced).remove(this->section_prefix)) {
if (ch == '_' || ch == ' ') {
big = true;
continue;

View file

@ -168,7 +168,10 @@ QString Tileset::getMetatileLabelPrefix()
QString Tileset::getMetatileLabelPrefix(const QString &name)
{
return QString("METATILE_%1_").arg(QString(name).replace("gTileset_", ""));
// Default is "gTileset_Name" --> "METATILE_Name_"
const QString tilesetPrefix = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix);
const QString labelPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix);
return QString("%1%2_").arg(labelPrefix).arg(QString(name).replace(tilesetPrefix, ""));
}
bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
@ -343,7 +346,8 @@ QString Tileset::getExpectedDir(QString tilesetName, bool isSecondary)
static const QRegularExpression re("([a-z])([A-Z0-9])");
const QString category = isSecondary ? "secondary" : "primary";
const QString basePath = projectConfig.getFilePath(ProjectFilePath::data_tilesets_folders) + category + "/";
return basePath + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower();
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix);
return basePath + tilesetName.replace(prefix, "").replace(re, "\\1_\\2").toLower();
}
// Get the expected positions of the members in struct Tileset.

View file

@ -1867,8 +1867,9 @@ void MainWindow::addNewEvent(Event::Type type) {
msgBox.setText("Failed to add new event");
if (Event::typeToGroup(type) == Event::Group::Object) {
msgBox.setInformativeText(QString("The limit for object events (%1) has been reached.\n\n"
"This limit can be adjusted with OBJECT_EVENT_TEMPLATES_COUNT in '%2'.")
"This limit can be adjusted with %2 in '%3'.")
.arg(editor->project->getMaxObjectEvents())
.arg(projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count))
.arg(projectConfig.getFilePath(ProjectFilePath::constants_global)));
}
msgBox.setDefaultButton(QMessageBox::Ok);

View file

@ -289,10 +289,12 @@ bool Project::loadMapData(Map* map) {
}
map->events[Event::Group::Heal].clear();
const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
for (auto it = healLocations.begin(); it != healLocations.end(); it++) {
HealLocation loc = *it;
//if TRUE map is flyable / has healing location
if (loc.mapName == QString(mapNamesToMapConstants.value(map->name)).remove(0,4)) {
if (loc.mapName == Map::mapConstantFromName(map->name, false)) {
HealLocationEvent *heal = new HealLocationEvent();
heal->setMap(map);
heal->setX(loc.x);
@ -301,12 +303,8 @@ bool Project::loadMapData(Map* map) {
heal->setLocationName(loc.mapName);
heal->setIdName(loc.idName);
heal->setIndex(loc.index);
// TODO: what is this
// heal->put("destination_map_name", mapConstantsToMapNames.value(map->name));
if (projectConfig.getHealLocationRespawnDataEnabled()) {
heal->setRespawnMap(mapConstantsToMapNames.value(QString("MAP_" + loc.respawnMap)));
heal->setRespawnMap(mapConstantsToMapNames.value(QString(mapPrefix + loc.respawnMap)));
heal->setRespawnNPC(loc.respawnNPC);
}
map->events[Event::Group::Heal].append(heal);
@ -630,9 +628,8 @@ void Project::saveWildMonData() {
OrderedJson::object wildEncountersObject;
OrderedJson::array wildEncounterGroups;
// gWildMonHeaders label is not mutable
OrderedJson::object monHeadersObject;
monHeadersObject["label"] = "gWildMonHeaders";
monHeadersObject["label"] = projectConfig.getIdentifier(ProjectIdentifier::symbol_wild_encounters);
monHeadersObject["for_maps"] = true;
OrderedJson::array fieldsInfoArray;
@ -751,6 +748,12 @@ void Project::saveHealLocations(Map *map) {
this->saveHealLocationsConstants();
}
QString Project::getHealLocationsTableName() {
if (projectConfig.getHealLocationRespawnDataEnabled())
return projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_points);
return projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations);
}
// Saves heal location maps/coords/respawn data in root + /src/data/heal_locations.h
void Project::saveHealLocationsData(Map *map) {
// Update heal locations from map
@ -774,20 +777,19 @@ void Project::saveHealLocationsData(Map *map) {
// Create the definition text for each data table
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
QString arrayName = respawnEnabled ? "sSpawnPoints" : "sHealLocations";
const QString qualifiers = QString(healLocationDataQualifiers.isStatic ? "static " : "")
+ QString(healLocationDataQualifiers.isConst ? "const " : "");
QString locationTableText = QString("%1struct HealLocation %2[] =\n{\n").arg(qualifiers).arg(arrayName);
QString locationTableText = QString("%1struct HealLocation %2[] =\n{\n").arg(qualifiers).arg(this->getHealLocationsTableName());
QString respawnMapTableText, respawnNPCTableText;
if (respawnEnabled) {
respawnMapTableText = QString("\n%1u16 sWhiteoutRespawnHealCenterMapIdxs[][2] =\n{\n").arg(qualifiers);
respawnNPCTableText = QString("\n%1u8 sWhiteoutRespawnHealerNpcIds[] =\n{\n").arg(qualifiers);
respawnMapTableText = QString("\n%1u16 %2[][2] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_maps));
respawnNPCTableText = QString("\n%1u8 %2[] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_npcs));
}
// Populate the data tables with the heal location data
int i = 0;
const QString emptyMapName = "UNDEFINED"; // TODO: Use a project-wide constant here?
const QString emptyMapName = projectConfig.getIdentifier(ProjectIdentifier::define_map_empty);
for (auto hl : this->healLocations) {
// Add numbered suffix for duplicate constants
if (healLocationsDupes.keys().contains(hl.idName)) {
@ -1505,7 +1507,7 @@ bool Project::readTilesetMetatileLabels() {
QString metatileLabelsFilename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_labels);
fileWatcher.addPath(root + "/" + metatileLabelsFilename);
static const QStringList prefixes = {"METATILE_"};
const QStringList prefixes = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix))};
QMap<QString, int> defines = parser.readCDefinesByPrefix(metatileLabelsFilename, prefixes);
for (QString label : defines.keys()) {
@ -1719,8 +1721,9 @@ bool Project::readMapGroups() {
}
}
mapConstantsToMapNames.insert(DYNAMIC_MAP_CONSTANT, DYNAMIC_MAP_NAME);
mapNamesToMapConstants.insert(DYNAMIC_MAP_NAME, DYNAMIC_MAP_CONSTANT);
const QString defineName = this->getDynamicMapDefineName();
mapConstantsToMapNames.insert(defineName, DYNAMIC_MAP_NAME);
mapNamesToMapConstants.insert(DYNAMIC_MAP_NAME, defineName);
maps.append(DYNAMIC_MAP_NAME);
groupNames = groups;
@ -1862,62 +1865,72 @@ bool Project::readTilesetLabels() {
return success;
}
// TODO: Names to config
bool Project::readTilesetProperties() {
static const QStringList names = {
"NUM_TILES_IN_PRIMARY",
"NUM_TILES_TOTAL",
"NUM_METATILES_IN_PRIMARY",
"NUM_PALS_IN_PRIMARY",
"NUM_PALS_TOTAL",
"MAX_MAP_DATA_SIZE",
const QString numTilesPrimaryName = projectConfig.getIdentifier(ProjectIdentifier::define_tiles_primary);
const QString numTilesTotalName = projectConfig.getIdentifier(ProjectIdentifier::define_tiles_total);
const QString numMetatilesPrimaryName = projectConfig.getIdentifier(ProjectIdentifier::define_metatiles_primary);
const QString numPalsPrimaryName = projectConfig.getIdentifier(ProjectIdentifier::define_pals_primary);
const QString numPalsTotalName = projectConfig.getIdentifier(ProjectIdentifier::define_pals_total);
const QString maxMapSizeName = projectConfig.getIdentifier(ProjectIdentifier::define_map_size);
const QStringList names = {
numTilesPrimaryName,
numTilesTotalName,
numMetatilesPrimaryName,
numPalsPrimaryName,
numPalsTotalName,
maxMapSizeName,
};
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap);
fileWatcher.addPath(root + "/" + filename);
QMap<QString, int> defines = parser.readCDefinesByName(filename, names);
auto it = defines.find("NUM_TILES_IN_PRIMARY");
auto it = defines.find(numTilesPrimaryName);
if (it != defines.end()) {
Project::num_tiles_primary = it.value();
}
else {
logWarn(QString("Value for tileset property 'NUM_TILES_IN_PRIMARY' not found. Using default (%1) instead.")
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
.arg(numTilesPrimaryName)
.arg(Project::num_tiles_primary));
}
it = defines.find("NUM_TILES_TOTAL");
it = defines.find(numTilesTotalName);
if (it != defines.end()) {
Project::num_tiles_total = it.value();
}
else {
logWarn(QString("Value for tileset property 'NUM_TILES_TOTAL' not found. Using default (%1) instead.")
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
.arg(numTilesTotalName)
.arg(Project::num_tiles_total));
}
it = defines.find("NUM_METATILES_IN_PRIMARY");
it = defines.find(numMetatilesPrimaryName);
if (it != defines.end()) {
Project::num_metatiles_primary = it.value();
}
else {
logWarn(QString("Value for tileset property 'NUM_METATILES_IN_PRIMARY' not found. Using default (%1) instead.")
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
.arg(numMetatilesPrimaryName)
.arg(Project::num_metatiles_primary));
}
it = defines.find("NUM_PALS_IN_PRIMARY");
it = defines.find(numPalsPrimaryName);
if (it != defines.end()) {
Project::num_pals_primary = it.value();
}
else {
logWarn(QString("Value for tileset property 'NUM_PALS_IN_PRIMARY' not found. Using default (%1) instead.")
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
.arg(numPalsPrimaryName)
.arg(Project::num_pals_primary));
}
it = defines.find("NUM_PALS_TOTAL");
it = defines.find(numPalsTotalName);
if (it != defines.end()) {
Project::num_pals_total = it.value();
}
else {
logWarn(QString("Value for tileset property 'NUM_PALS_TOTAL' not found. Using default (%1) instead.")
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
.arg(numPalsTotalName)
.arg(Project::num_pals_total));
}
it = defines.find("MAX_MAP_DATA_SIZE");
it = defines.find(maxMapSizeName);
if (it != defines.end()) {
int min = getMapDataSize(1, 1);
if (it.value() >= min) {
@ -1925,29 +1938,35 @@ bool Project::readTilesetProperties() {
calculateDefaultMapSize();
} else {
// must be large enough to support a 1x1 map
logWarn(QString("Value for map property 'MAX_MAP_DATA_SIZE' is %1, must be at least %2. Using default (%3) instead.")
logWarn(QString("Value for map property '%1' is %2, must be at least %3. Using default (%4) instead.")
.arg(maxMapSizeName)
.arg(it.value())
.arg(min)
.arg(Project::max_map_data_size));
}
}
else {
logWarn(QString("Value for map property 'MAX_MAP_DATA_SIZE' not found. Using default (%1) instead.")
logWarn(QString("Value for map property '%1' not found. Using default (%2) instead.")
.arg(maxMapSizeName)
.arg(Project::max_map_data_size));
}
return true;
}
// TODO: Update for config
// Read data masks for Blocks and metatile attributes.
bool Project::readFieldmapMasks() {
static const QStringList searchNames = {
ProjectConfig::metatileIdMaskName,
ProjectConfig::collisionMaskName,
ProjectConfig::elevationMaskName,
ProjectConfig::behaviorMaskName,
ProjectConfig::layerTypeMaskName,
const QString metatileIdMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_metatile);
const QString collisionMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_collision);
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 QStringList searchNames = {
metatileIdMaskName,
collisionMaskName,
elevationMaskName,
behaviorMaskName,
layerTypeMaskName,
};
QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
fileWatcher.addPath(root + "/" + globalFieldmap);
@ -1963,57 +1982,63 @@ bool Project::readFieldmapMasks() {
projectConfig.setSaveDisabled(true);
// Read Block masks
auto it = defines.find(ProjectConfig::metatileIdMaskName);
auto it = defines.find(metatileIdMaskName);
if (it != defines.end())
projectConfig.setBlockMetatileIdMask(static_cast<uint16_t>(it.value()));
it = defines.find(ProjectConfig::collisionMaskName);
it = defines.find(collisionMaskName);
if (it != defines.end())
projectConfig.setBlockCollisionMask(static_cast<uint16_t>(it.value()));
it = defines.find(ProjectConfig::elevationMaskName);
it = defines.find(elevationMaskName);
if (it != defines.end())
projectConfig.setBlockElevationMask(static_cast<uint16_t>(it.value()));
// Read RSE metatile attribute masks
it = defines.find(ProjectConfig::behaviorMaskName);
it = defines.find(behaviorMaskName);
if (it != defines.end())
projectConfig.setMetatileBehaviorMask(static_cast<uint32_t>(it.value()));
it = defines.find(ProjectConfig::layerTypeMaskName);
it = defines.find(layerTypeMaskName);
if (it != defines.end())
projectConfig.setMetatileLayerTypeMask(static_cast<uint32_t>(it.value()));
// pokefirered keeps its attribute masks in a separate table, parse this too.
QString srcFieldmap = projectConfig.getFilePath(ProjectFilePath::fieldmap);
const QMap<QString, QString> attrTable = parser.readNamedIndexCArray(srcFieldmap, ProjectConfig::attrTableName);
const QString attrTableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_attribute_table);
const QString srcFieldmap = projectConfig.getFilePath(ProjectFilePath::fieldmap);
const QMap<QString, QString> attrTable = parser.readNamedIndexCArray(srcFieldmap, attrTableName);
if (!attrTable.isEmpty()) {
const QString terrainTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_behavior);
const QString encounterTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_layer);
const QString behaviorTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_terrain);
const QString layerTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_encounter);
fileWatcher.addPath(root + "/" + srcFieldmap);
bool ok;
// Read terrain type mask
uint32_t mask = attrTable.value(ProjectConfig::terrainTypeTableName).toUInt(&ok, 0);
uint32_t mask = attrTable.value(terrainTypeTableName).toUInt(&ok, 0);
if (ok) {
projectConfig.setMetatileTerrainTypeMask(mask);
this->disabledSettingsNames.insert(ProjectConfig::terrainTypeTableName);
this->disabledSettingsNames.insert(terrainTypeTableName);
}
// Read encounter type mask
mask = attrTable.value(ProjectConfig::encounterTypeTableName).toUInt(&ok, 0);
mask = attrTable.value(encounterTypeTableName).toUInt(&ok, 0);
if (ok) {
projectConfig.setMetatileEncounterTypeMask(mask);
this->disabledSettingsNames.insert(ProjectConfig::encounterTypeTableName);
this->disabledSettingsNames.insert(encounterTypeTableName);
}
// If we haven't already parsed behavior and layer type then try those too
if (!this->disabledSettingsNames.contains(ProjectConfig::behaviorMaskName)) {
if (!this->disabledSettingsNames.contains(behaviorMaskName)) {
// Read behavior mask
mask = attrTable.value(ProjectConfig::behaviorTableName).toUInt(&ok, 0);
mask = attrTable.value(behaviorTableName).toUInt(&ok, 0);
if (ok) {
projectConfig.setMetatileBehaviorMask(mask);
this->disabledSettingsNames.insert(ProjectConfig::behaviorTableName);
this->disabledSettingsNames.insert(behaviorTableName);
}
}
if (!this->disabledSettingsNames.contains(ProjectConfig::layerTypeMaskName)) {
if (!this->disabledSettingsNames.contains(layerTypeMaskName)) {
// Read layer type mask
mask = attrTable.value(ProjectConfig::layerTypeTableName).toUInt(&ok, 0);
mask = attrTable.value(layerTypeTableName).toUInt(&ok, 0);
if (ok) {
projectConfig.setMetatileLayerTypeMask(mask);
this->disabledSettingsNames.insert(ProjectConfig::layerTypeTableName);
this->disabledSettingsNames.insert(layerTypeTableName);
}
}
}
@ -2025,7 +2050,7 @@ bool Project::readRegionMapSections() {
this->mapSectionNameToValue.clear();
this->mapSectionValueToName.clear();
static const QStringList prefixes = {"\\bMAPSEC_"};
const QStringList prefixes = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))};
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections);
fileWatcher.addPath(root + "/" + filename);
this->mapSectionNameToValue = parser.readCDefinesByPrefix(filename, prefixes);
@ -2043,7 +2068,10 @@ bool Project::readRegionMapSections() {
// Read the constants to preserve any "unused" heal locations when writing the file later
bool Project::readHealLocationConstants() {
this->healLocationNameToValue.clear();
static const QStringList prefixes = {"\\bSPAWN_", "\\bHEAL_LOCATION_"};
const QStringList prefixes = {
QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_heal_locations_prefix)),
QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_spawn_prefix))
};
QString constantsFilename = projectConfig.getFilePath(ProjectFilePath::constants_heal_locations);
fileWatcher.addPath(root + "/" + constantsFilename);
this->healLocationNameToValue = parser.readCDefinesByPrefix(constantsFilename, prefixes);
@ -2051,6 +2079,7 @@ bool Project::readHealLocationConstants() {
return true;
}
// TODO: Simplify using the new C struct parsing functions (and indexed array parsing functions)
bool Project::readHealLocations() {
this->healLocationDataQualifiers = {};
this->healLocations.clear();
@ -2069,11 +2098,12 @@ bool Project::readHealLocations() {
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
// Get data qualifiers for the location data table
QString tableName = respawnEnabled ? "sSpawnPoints" : "sHealLocations";
this->healLocationDataQualifiers = this->getDataQualifiers(text, tableName);
this->healLocationDataQualifiers = this->getDataQualifiers(text, this->getHealLocationsTableName());
// Create regex pattern for the constants (ex: "SPAWN_PALLET_TOWN" or "HEAL_LOCATION_PETALBURG_CITY")
static const QRegularExpression constantsExpr("(SPAWN|HEAL_LOCATION)_[A-Za-z0-9_]+");
const QString spawnPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_spawn_prefix);
const QString healLocPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_heal_locations_prefix);
const QRegularExpression constantsExpr(QString("\\b(%1|%2)[A-Za-z0-9_]+").arg(spawnPrefix).arg(healLocPrefix));
// Find all the unique heal location constants used in the data tables.
// Porymap doesn't care whether or not a constant appeared in the heal locations constants file.
@ -2133,8 +2163,8 @@ bool Project::readHealLocations() {
}
bool Project::readItemNames() {
QStringList prefixes("\\bITEM_(?!(B_)?USE_)"); // Exclude ITEM_USE_ and ITEM_B_USE_ constants
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_items)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items);
fileWatcher.addPath(root + "/" + filename);
itemNames = parser.readCDefineNames(filename, prefixes);
if (itemNames.isEmpty()) {
@ -2145,8 +2175,8 @@ bool Project::readItemNames() {
}
bool Project::readFlagNames() {
QStringList prefixes("\\bFLAG_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_flags)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
fileWatcher.addPath(root + "/" + filename);
flagNames = parser.readCDefineNames(filename, prefixes);
if (flagNames.isEmpty()) {
@ -2157,8 +2187,8 @@ bool Project::readFlagNames() {
}
bool Project::readVarNames() {
QStringList prefixes("\\bVAR_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_vars)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars);
fileWatcher.addPath(root + "/" + filename);
varNames = parser.readCDefineNames(filename, prefixes);
if (varNames.isEmpty()) {
@ -2169,8 +2199,8 @@ bool Project::readVarNames() {
}
bool Project::readMovementTypes() {
QStringList prefixes("\\bMOVEMENT_TYPE_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_movement_types)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement);
fileWatcher.addPath(root + "/" + filename);
movementTypes = parser.readCDefineNames(filename, prefixes);
if (movementTypes.isEmpty()) {
@ -2183,7 +2213,7 @@ bool Project::readMovementTypes() {
bool Project::readInitialFacingDirections() {
QString filename = projectConfig.getFilePath(ProjectFilePath::initial_facing_table);
fileWatcher.addPath(root + "/" + filename);
facingDirections = parser.readNamedIndexCArray(filename, "gInitialMovementTypeFacingDirections");
facingDirections = parser.readNamedIndexCArray(filename, projectConfig.getIdentifier(ProjectIdentifier::symbol_facing_directions));
if (facingDirections.isEmpty()) {
logError(QString("Failed to read initial movement type facing directions from %1").arg(filename));
return false;
@ -2192,8 +2222,8 @@ bool Project::readInitialFacingDirections() {
}
bool Project::readMapTypes() {
QStringList prefixes("\\bMAP_TYPE_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_map_types)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
fileWatcher.addPath(root + "/" + filename);
mapTypes = parser.readCDefineNames(filename, prefixes);
if (mapTypes.isEmpty()) {
@ -2204,8 +2234,8 @@ bool Project::readMapTypes() {
}
bool Project::readMapBattleScenes() {
QStringList prefixes("\\bMAP_BATTLE_SCENE_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_battle_scenes)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
fileWatcher.addPath(root + "/" + filename);
mapBattleScenes = parser.readCDefineNames(filename, prefixes);
if (mapBattleScenes.isEmpty()) {
@ -2216,8 +2246,8 @@ bool Project::readMapBattleScenes() {
}
bool Project::readWeatherNames() {
QStringList prefixes("\\bWEATHER_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_weather)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
fileWatcher.addPath(root + "/" + filename);
weatherNames = parser.readCDefineNames(filename, prefixes);
if (weatherNames.isEmpty()) {
@ -2231,8 +2261,8 @@ bool Project::readCoordEventWeatherNames() {
if (!projectConfig.getEventWeatherTriggerEnabled())
return true;
QStringList prefixes("\\bCOORD_EVENT_WEATHER_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_coord_event_weather)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
fileWatcher.addPath(root + "/" + filename);
coordEventWeatherNames = parser.readCDefineNames(filename, prefixes);
if (coordEventWeatherNames.isEmpty()) {
@ -2246,8 +2276,8 @@ bool Project::readSecretBaseIds() {
if (!projectConfig.getEventSecretBaseEnabled())
return true;
QStringList prefixes("\\bSECRET_BASE_[A-Za-z0-9_]*_[0-9]+");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_secret_bases)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases);
fileWatcher.addPath(root + "/" + filename);
secretBaseIds = parser.readCDefineNames(filename, prefixes);
if (secretBaseIds.isEmpty()) {
@ -2258,8 +2288,8 @@ bool Project::readSecretBaseIds() {
}
bool Project::readBgEventFacingDirections() {
QStringList prefixes("\\bBG_EVENT_PLAYER_FACING_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_sign_facing_directions)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg);
fileWatcher.addPath(root + "/" + filename);
bgEventFacingDirections = parser.readCDefineNames(filename, prefixes);
if (bgEventFacingDirections.isEmpty()) {
@ -2270,8 +2300,8 @@ bool Project::readBgEventFacingDirections() {
}
bool Project::readTrainerTypes() {
QStringList prefixes("\\bTRAINER_TYPE_");
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_trainer_types)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types);
fileWatcher.addPath(root + "/" + filename);
trainerTypes = parser.readCDefineNames(filename, prefixes);
if (trainerTypes.isEmpty()) {
@ -2285,7 +2315,7 @@ bool Project::readMetatileBehaviors() {
this->metatileBehaviorMap.clear();
this->metatileBehaviorMapInverse.clear();
static const QStringList prefixes = {"\\bMB_"};
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)};
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_behaviors);
fileWatcher.addPath(root + "/" + filename);
this->metatileBehaviorMap = parser.readCDefinesByPrefix(filename, prefixes);
@ -2312,22 +2342,22 @@ bool Project::readMetatileBehaviors() {
}
bool Project::readSongNames() {
QStringList songDefinePrefixes{ "\\bSE_", "\\bMUS_" };
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs);
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_music)};
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs);
fileWatcher.addPath(root + "/" + filename);
this->songNames = parser.readCDefineNames(filename, songDefinePrefixes);
this->defaultSong = this->songNames.value(0, "MUS_DUMMY");
this->songNames = parser.readCDefineNames(filename, prefixes);
if (this->songNames.isEmpty()) {
logError(QString("Failed to read song names from %1.").arg(filename));
return false;
}
this->defaultSong = this->songNames.value(0);
// Song names don't have a very useful order (esp. if we include SE_* values), so sort them alphabetically.
this->songNames.sort();
return true;
}
bool Project::readObjEventGfxConstants() {
static const QStringList prefixes = {"\\bOBJ_EVENT_GFX_"};
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)};
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_events);
fileWatcher.addPath(root + "/" + filename);
this->gfxDefines = parser.readCDefinesByPrefix(filename, prefixes);
@ -2338,33 +2368,37 @@ bool Project::readObjEventGfxConstants() {
return true;
}
// TODO: Names to config
bool Project::readMiscellaneousConstants() {
miscConstants.clear();
if (userConfig.getEncounterJsonActive()) {
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_pokemon);
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_pokemon);
const QString minLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_min_level);
const QString maxLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_max_level);
fileWatcher.addPath(root + "/" + filename);
QMap<QString, int> pokemonDefines = parser.readCDefinesByName(filename, {"MIN_LEVEL", "MAX_LEVEL"});
miscConstants.insert("max_level_define", pokemonDefines.value("MAX_LEVEL") > pokemonDefines.value("MIN_LEVEL") ? pokemonDefines.value("MAX_LEVEL") : 100);
miscConstants.insert("min_level_define", pokemonDefines.value("MIN_LEVEL") < pokemonDefines.value("MAX_LEVEL") ? pokemonDefines.value("MIN_LEVEL") : 1);
QMap<QString, int> pokemonDefines = parser.readCDefinesByName(filename, {minLevelName, maxLevelName});
miscConstants.insert("max_level_define", pokemonDefines.value(maxLevelName) > pokemonDefines.value(minLevelName) ? pokemonDefines.value(maxLevelName) : 100);
miscConstants.insert("min_level_define", pokemonDefines.value(minLevelName) < pokemonDefines.value(maxLevelName) ? pokemonDefines.value(minLevelName) : 1);
}
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_global);
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, {"OBJECT_EVENT_TEMPLATES_COUNT"});
QMap<QString, int> defines = parser.readCDefinesByName(filename, {maxObjectEventsName});
auto it = defines.find("OBJECT_EVENT_TEMPLATES_COUNT");
auto it = defines.find(maxObjectEventsName);
if (it != defines.end()) {
if (it.value() > 0) {
Project::max_object_events = it.value();
} else {
logWarn(QString("Value for 'OBJECT_EVENT_TEMPLATES_COUNT' is %1, must be greater than 0. Using default (%2) instead.")
logWarn(QString("Value for '%1' is %2, must be greater than 0. Using default (%3) instead.")
.arg(maxObjectEventsName)
.arg(it.value())
.arg(Project::max_object_events));
}
}
else {
logWarn(QString("Value for 'OBJECT_EVENT_TEMPLATES_COUNT' not found. Using default (%1) instead.")
logWarn(QString("Value for '%1' not found. Using default (%2) instead.")
.arg(maxObjectEventsName)
.arg(Project::max_object_events));
}
@ -2471,7 +2505,9 @@ bool Project::readEventGraphics() {
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables)
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx));
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray(projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers), "gObjectEventGraphicsInfoPointers");
const QString pointersFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers);
const QString pointersName = projectConfig.getIdentifier(ProjectIdentifier::symbol_obj_event_gfx_pointers);
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray(pointersFilepath, pointersName);
qDeleteAll(eventGraphicsMap);
eventGraphicsMap.clear();
@ -2479,7 +2515,7 @@ bool Project::readEventGraphics() {
// The positions of each of the required members for the gfx info struct.
// For backwards compatibility if the struct doesn't use initializers.
const auto gfxInfoMemberMap = QHash<int, QString>{
static const auto gfxInfoMemberMap = QHash<int, QString>{
{8, "inanimate"},
{11, "oam"},
{12, "subspriteTables"},
@ -2546,21 +2582,23 @@ bool Project::readSpeciesIconPaths() {
// Read map of species constants to icon names
const QString srcfilename = projectConfig.getFilePath(ProjectFilePath::pokemon_icon_table);
fileWatcher.addPath(root + "/" + srcfilename);
const QMap<QString, QString> monIconNames = parser.readNamedIndexCArray(srcfilename, "gMonIconTable");
const QString tableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_pokemon_icon_table);
const QMap<QString, QString> monIconNames = parser.readNamedIndexCArray(srcfilename, tableName);
// Read map of icon names to filepaths. These are spread between two different files
// Read map of icon names to filepaths
const QString incfilename = projectConfig.getFilePath(ProjectFilePath::data_pokemon_gfx);
fileWatcher.addPath(root + "/" + incfilename);
const QMap<QString, QString> iconIncbins = parser.readCIncbinMulti(incfilename);
// Read species constants. If this fails we can get them from the icon table (but we shouldn't rely on it).
static const QStringList prefixes("\\bSPECIES_");
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_species)};
const QString constantsFilename = projectConfig.getFilePath(ProjectFilePath::constants_species);
fileWatcher.addPath(root + "/" + constantsFilename);
QStringList speciesNames = parser.readCDefineNames(constantsFilename, prefixes);
if (speciesNames.isEmpty())
speciesNames = monIconNames.keys();
// For each species, use the information gathered above to find the icon image.
bool missingIcons = false;
for (auto species : speciesNames) {
QString path = QString();
@ -2705,7 +2743,8 @@ bool Project::calculateDefaultMapSize(){
// x^2 + 29x + (210 - max), then complete the square and simplify
default_map_size = qFloor((qSqrt(4 * getMaxMapDataSize() + 1) - 29) / 2);
} else {
logError(QString("'MAX_MAP_DATA_SIZE' of %1 is too small to support a 1x1 map. Must be at least %2.")
logError(QString("'%1' of %2 is too small to support a 1x1 map. Must be at least %3.")
.arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_size))
.arg(max)
.arg(getMapDataSize(1, 1)));
return false;
@ -2718,6 +2757,11 @@ int Project::getMaxObjectEvents()
return Project::max_object_events;
}
QString Project::getDynamicMapDefineName() {
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
}
void Project::setImportExportPath(QString filename)
{
this->importExportPath = QFileInfo(filename).absolutePath();

View file

@ -94,9 +94,10 @@ void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
emit editor->warpEventDoubleClicked(clone->getTargetMap(), clone->getTargetID(), Event::Group::Object);
}
else if (eventType == Event::Type::SecretBase) {
const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
SecretBaseEvent *base = dynamic_cast<SecretBaseEvent *>(this->event);
QString baseId = base->getBaseID();
QString destMap = editor->project->mapConstantsToMapNames.value("MAP_" + baseId.left(baseId.lastIndexOf("_")));
QString destMap = editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_")));
emit editor->warpEventDoubleClicked(destMap, 0, Event::Group::Warp);
}
}

View file

@ -258,9 +258,9 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
newMap->location = this->ui->comboBox_NewMap_Location->currentText();
newMap->song = this->ui->comboBox_NewMap_Song->currentText();
newMap->requiresFlash = false;
newMap->weather = this->project->weatherNames.value(0, "WEATHER_NONE");
newMap->weather = this->project->weatherNames.value(0);
newMap->show_location = this->ui->checkBox_NewMap_Show_Location->isChecked();
newMap->battle_scene = this->project->mapBattleScenes.value(0, "MAP_BATTLE_SCENE_NORMAL");
newMap->battle_scene = this->project->mapBattleScenes.value(0);
if (this->existingLayout) {
layout = this->project->mapLayouts.value(this->layoutId);

View file

@ -38,7 +38,7 @@ void NewTilesetDialog::SecondaryChanged(){
void NewTilesetDialog::NameOrSecondaryChanged() {
this->friendlyName = this->ui->nameLineEdit->text();
this->fullSymbolName = "gTileset_" + this->friendlyName;
this->fullSymbolName = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix) + this->friendlyName;
this->ui->symbolNameLineEdit->setText(this->fullSymbolName);
this->path = Tileset::getExpectedDir(this->fullSymbolName, this->isSecondary);
this->ui->pathLineEdit->setText(this->path);

View file

@ -135,32 +135,42 @@ void ProjectSettingsEditor::initUi() {
if (project) {
const QString maskFilepath = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
const QString attrTableFilepath = projectConfig.getFilePath(ProjectFilePath::fieldmap);
const QString metatileIdMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_metatile);
const QString collisionMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_collision);
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 QString terrainTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_behavior);
const QString encounterTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_layer);
const QString behaviorTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_terrain);
const QString layerTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_encounter);
const QString attrTableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_attribute_table);
// Block masks
if (project->disabledSettingsNames.contains(ProjectConfig::metatileIdMaskName))
this->disableParsedSetting(ui->spinBox_MetatileIdMask, ProjectConfig::metatileIdMaskName, maskFilepath);
if (project->disabledSettingsNames.contains(ProjectConfig::collisionMaskName))
this->disableParsedSetting(ui->spinBox_CollisionMask, ProjectConfig::collisionMaskName, maskFilepath);
if (project->disabledSettingsNames.contains(ProjectConfig::elevationMaskName))
this->disableParsedSetting(ui->spinBox_ElevationMask, ProjectConfig::elevationMaskName, maskFilepath);
if (project->disabledSettingsNames.contains(metatileIdMaskName))
this->disableParsedSetting(ui->spinBox_MetatileIdMask, metatileIdMaskName, maskFilepath);
if (project->disabledSettingsNames.contains(collisionMaskName))
this->disableParsedSetting(ui->spinBox_CollisionMask, collisionMaskName, maskFilepath);
if (project->disabledSettingsNames.contains(elevationMaskName))
this->disableParsedSetting(ui->spinBox_ElevationMask, elevationMaskName, maskFilepath);
// Behavior mask
if (project->disabledSettingsNames.contains(ProjectConfig::behaviorMaskName))
this->disableParsedSetting(ui->spinBox_BehaviorMask, ProjectConfig::behaviorMaskName, maskFilepath);
else if (project->disabledSettingsNames.contains(ProjectConfig::behaviorTableName))
this->disableParsedSetting(ui->spinBox_BehaviorMask, ProjectConfig::attrTableName, attrTableFilepath);
if (project->disabledSettingsNames.contains(behaviorMaskName))
this->disableParsedSetting(ui->spinBox_BehaviorMask, behaviorMaskName, maskFilepath);
else if (project->disabledSettingsNames.contains(behaviorTableName))
this->disableParsedSetting(ui->spinBox_BehaviorMask, attrTableName, attrTableFilepath);
// Layer type mask
if (project->disabledSettingsNames.contains(ProjectConfig::layerTypeMaskName))
this->disableParsedSetting(ui->spinBox_LayerTypeMask, ProjectConfig::layerTypeMaskName, maskFilepath);
else if (project->disabledSettingsNames.contains(ProjectConfig::layerTypeTableName))
this->disableParsedSetting(ui->spinBox_LayerTypeMask, ProjectConfig::attrTableName, attrTableFilepath);
if (project->disabledSettingsNames.contains(layerTypeMaskName))
this->disableParsedSetting(ui->spinBox_LayerTypeMask, layerTypeMaskName, maskFilepath);
else if (project->disabledSettingsNames.contains(layerTypeTableName))
this->disableParsedSetting(ui->spinBox_LayerTypeMask, attrTableName, attrTableFilepath);
// Encounter and terrain type masks
if (project->disabledSettingsNames.contains(ProjectConfig::terrainTypeTableName))
this->disableParsedSetting(ui->spinBox_TerrainTypeMask, ProjectConfig::attrTableName, attrTableFilepath);
if (project->disabledSettingsNames.contains(ProjectConfig::encounterTypeTableName))
this->disableParsedSetting(ui->spinBox_EncounterTypeMask, ProjectConfig::attrTableName, attrTableFilepath);
if (project->disabledSettingsNames.contains(terrainTypeTableName))
this->disableParsedSetting(ui->spinBox_TerrainTypeMask, attrTableName, attrTableFilepath);
if (project->disabledSettingsNames.contains(encounterTypeTableName))
this->disableParsedSetting(ui->spinBox_EncounterTypeMask, attrTableName, attrTableFilepath);
}
}
@ -440,7 +450,7 @@ void ProjectSettingsEditor::refresh() {
ui->lineEdit_BGsIcon->setText(projectConfig.getEventIconPath(Event::Group::Bg));
ui->lineEdit_HealspotsIcon->setText(projectConfig.getEventIconPath(Event::Group::Heal));
for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>())
lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true));
lineEdit->setText(projectConfig.getCustomFilePath(lineEdit->objectName()));
this->setWarpBehaviorsList(projectConfig.getWarpBehaviors());
this->refreshing = false; // Allow signals

View file

@ -796,14 +796,17 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
if (!this->region_map->layoutEnabled()) return;
bool enabled = ((section != "MAPSEC_NONE") && (section != "MAPSEC_COUNT")) && (this->region_map_entries.contains(section));
bool isSpecialSection = (section == this->region_map->default_map_section
|| section == this->region_map->count_map_section);
bool enabled = (!isSpecialSection && this->region_map_entries.contains(section));
this->ui->lineEdit_RM_MapName->setEnabled(enabled);
this->ui->spinBox_RM_Entry_x->setEnabled(enabled);
this->ui->spinBox_RM_Entry_y->setEnabled(enabled);
this->ui->spinBox_RM_Entry_width->setEnabled(enabled);
this->ui->spinBox_RM_Entry_height->setEnabled(enabled);
this->ui->pushButton_entryActivate->setEnabled(section != "MAPSEC_NONE" && section != "MAPSEC_COUNT");
this->ui->pushButton_entryActivate->setEnabled(!isSpecialSection);
this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add");
this->ui->lineEdit_RM_MapName->blockSignals(true);
@ -831,7 +834,7 @@ void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
void RegionMapEditor::on_pushButton_entryActivate_clicked() {
QString section = this->ui->comboBox_RM_Entry_MapSection->currentText();
if (section == "MAPSEC_NONE") return;
if (section == this->region_map->default_map_section) return;
if (this->region_map_entries.contains(section)) {
// disable
@ -1297,7 +1300,7 @@ void RegionMapEditor::on_action_RegionMap_ClearLayout_triggered() {
QMessageBox::StandardButton result = QMessageBox::question(
this,
"WARNING",
"This action will reset the entire map layout to MAPSEC_NONE, continue?",
QString("This action will reset the entire map layout to %1, continue?").arg(this->region_map->default_map_section),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Yes
);

View file

@ -8,7 +8,7 @@ void RegionMapEntriesPixmapItem::draw() {
int entry_x, entry_y, entry_w, entry_h;
if (!entry.valid || entry.name == "MAPSEC_NONE") {
if (!entry.valid || entry.name == region_map->default_map_section) {
entry_x = entry_y = 0;
entry_w = entry_h = 1;
} else {