mirror of
https://github.com/huderlem/porymap.git
synced 2026-07-18 16:32:15 -05:00
Clean up new map dialog redesign
This commit is contained in:
parent
4f8224359e
commit
7d7db3857d
|
|
@ -92,6 +92,7 @@ In addition to these files, there are some specific symbol and macro names that
|
|||
``symbol_spawn_npcs``, ``u8 sWhiteoutRespawnHealerNpcIds``, the type and table name for Heal Location ``Respawn NPC`` values
|
||||
``symbol_attribute_table``, ``sMetatileAttrMasks``, optionally read to get settings on ``Tilesets`` tab
|
||||
``symbol_tilesets_prefix``, ``gTileset_``, for new tileset names and to extract base tileset names
|
||||
``symbol_dynamic_map_name``, ``Dynamic``, reserved map name to display for ``define_map_dynamic``
|
||||
``define_obj_event_count``, ``OBJECT_EVENT_TEMPLATES_COUNT``, to limit total Object Events
|
||||
``define_min_level``, ``MIN_LEVEL``, minimum wild encounters level
|
||||
``define_max_level``, ``MAX_LEVEL``, maximum wild encounters level
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ enum ProjectIdentifier {
|
|||
symbol_spawn_npcs,
|
||||
symbol_attribute_table,
|
||||
symbol_tilesets_prefix,
|
||||
symbol_dynamic_map_name,
|
||||
define_obj_event_count,
|
||||
define_min_level,
|
||||
define_max_level,
|
||||
|
|
@ -323,7 +324,7 @@ public:
|
|||
QString getCustomFilePath(ProjectFilePath pathId);
|
||||
QString getCustomFilePath(const QString &pathId);
|
||||
QString getFilePath(ProjectFilePath pathId);
|
||||
void setIdentifier(ProjectIdentifier id, const QString &text);
|
||||
void setIdentifier(ProjectIdentifier id, QString text);
|
||||
void setIdentifier(const QString &id, const QString &text);
|
||||
QString getCustomIdentifier(ProjectIdentifier id);
|
||||
QString getCustomIdentifier(const QString &id);
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@
|
|||
#include <QVariant>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
// TODO: Expose to config
|
||||
// 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
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -80,6 +76,7 @@ public:
|
|||
QMap<QString, qint64> modifiedFileTimestamps;
|
||||
bool usingAsmTilesets;
|
||||
QSet<QString> disabledSettingsNames;
|
||||
QSet<QString> topLevelMapFields;
|
||||
int pokemonMinLevel;
|
||||
int pokemonMaxLevel;
|
||||
int maxEncounterRate;
|
||||
|
|
@ -145,7 +142,7 @@ public:
|
|||
bool hasUnsavedChanges();
|
||||
bool hasUnsavedDataChanges = false;
|
||||
|
||||
QSet<QString> getTopLevelMapFields();
|
||||
void initTopLevelMapFields();
|
||||
bool readMapJson(const QString &mapName, QJsonDocument * out);
|
||||
bool loadMapData(Map*);
|
||||
bool readMapLayouts();
|
||||
|
|
@ -219,7 +216,6 @@ public:
|
|||
|
||||
QString getDefaultPrimaryTilesetLabel();
|
||||
QString getDefaultSecondaryTilesetLabel();
|
||||
QString getDynamicMapDefineName();
|
||||
void updateTilesetMetatileLabels(Tileset *tileset);
|
||||
QString buildMetatileLabelsText(const QMap<QString, uint16_t> defines);
|
||||
QString findMetatileLabelsTileset(QString label);
|
||||
|
|
@ -227,6 +223,8 @@ public:
|
|||
static QString getExistingFilepath(QString filepath);
|
||||
void applyParsedLimits();
|
||||
|
||||
static QString getDynamicMapDefineName();
|
||||
static QString getDynamicMapName();
|
||||
static int getNumTilesPrimary();
|
||||
static int getNumTilesTotal();
|
||||
static int getNumMetatilesPrimary();
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "u8 sWhiteoutRespawnHealerNpcIds"}},
|
||||
{ProjectIdentifier::symbol_attribute_table, {"symbol_attribute_table", "sMetatileAttrMasks"}},
|
||||
{ProjectIdentifier::symbol_tilesets_prefix, {"symbol_tilesets_prefix", "gTileset_"}},
|
||||
{ProjectIdentifier::symbol_dynamic_map_name, {"symbol_dynamic_map_name", "Dynamic"}},
|
||||
// Defines
|
||||
{ProjectIdentifier::define_obj_event_count, {"define_obj_event_count", "OBJECT_EVENT_TEMPLATES_COUNT"}},
|
||||
{ProjectIdentifier::define_min_level, {"define_min_level", "MIN_LEVEL"}},
|
||||
|
|
@ -941,13 +942,25 @@ QString ProjectConfig::getFilePath(ProjectFilePath pathId) {
|
|||
|
||||
}
|
||||
|
||||
void ProjectConfig::setIdentifier(ProjectIdentifier id, const QString &text) {
|
||||
if (!defaultIdentifiers.contains(id)) return;
|
||||
QString copy(text);
|
||||
if (copy.isEmpty()) {
|
||||
void ProjectConfig::setIdentifier(ProjectIdentifier id, QString text) {
|
||||
if (!defaultIdentifiers.contains(id))
|
||||
return;
|
||||
|
||||
if (text.isEmpty()) {
|
||||
this->identifiers.remove(id);
|
||||
} else {
|
||||
this->identifiers[id] = copy;
|
||||
const QString idName = defaultIdentifiers.value(id).first;
|
||||
if (idName.startsWith("define_") || idName.startsWith("symbol_")) {
|
||||
// Validate the input for the identifier, depending on the type.
|
||||
static const QRegularExpression re("[A-Za-z_]+[\\w]*");
|
||||
auto validator = QRegularExpressionValidator(re);
|
||||
int temp = 0;
|
||||
if (validator.validate(text, temp) != QValidator::Acceptable) {
|
||||
logError(QString("The name '%1' for project identifier '%2' is invalid. It must only contain word characters, and cannot start with a digit.").arg(text).arg(idName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->identifiers[id] = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -404,17 +404,11 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
this->setGfx(ParseUtil::jsonToQString(json["graphics_id"]));
|
||||
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 == dynamicMapConstant) {
|
||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||
} else {
|
||||
logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
|
||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||
}
|
||||
// Log a warning if "target_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Target Map constant '%1' is invalid.").arg(mapConstant));
|
||||
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
|
||||
this->readCustomValues(json);
|
||||
|
||||
|
|
@ -516,17 +510,11 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
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 == dynamicMapConstant) {
|
||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||
} else {
|
||||
logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
|
||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||
}
|
||||
// Log a warning if "dest_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Destination Map constant '%1' is invalid.").arg(mapConstant));
|
||||
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
|
||||
this->readCustomValues(json);
|
||||
|
||||
|
|
|
|||
|
|
@ -850,10 +850,10 @@ bool MainWindow::userSetMap(QString map_name) {
|
|||
if (editor->map && editor->map->name() == map_name)
|
||||
return true; // Already set
|
||||
|
||||
if (map_name == DYNAMIC_MAP_NAME) {
|
||||
if (map_name == editor->project->getDynamicMapName()) {
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("The map '%1' can't be opened, it's a placeholder to indicate the specified map will be set programmatically.").arg(map_name);
|
||||
msgBox.critical(nullptr, "Error Opening Map", errorMsg);
|
||||
msgBox.warning(nullptr, "Cannot Open Map", errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -870,14 +870,13 @@ bool MainWindow::userSetMap(QString map_name) {
|
|||
}
|
||||
|
||||
bool MainWindow::setMap(QString map_name) {
|
||||
if (map_name.isEmpty() || map_name == DYNAMIC_MAP_NAME) {
|
||||
logInfo(QString("Cannot set map to '%1'").arg(map_name));
|
||||
if (!editor || !editor->project || map_name.isEmpty() || map_name == editor->project->getDynamicMapName()) {
|
||||
logWarn(QString("Ignored setting map to '%1'").arg(map_name));
|
||||
return false;
|
||||
}
|
||||
|
||||
logInfo(QString("Setting map to '%1'").arg(map_name));
|
||||
|
||||
if (!editor || !editor->setMap(map_name)) {
|
||||
if (!editor->setMap(map_name)) {
|
||||
logWarn(QString("Failed to set map to '%1'").arg(map_name));
|
||||
return false;
|
||||
}
|
||||
|
|
@ -996,12 +995,6 @@ void MainWindow::refreshMapScene() {
|
|||
}
|
||||
|
||||
void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) {
|
||||
// Ensure valid destination map name.
|
||||
if (!editor->project->mapNames.contains(map_name)) {
|
||||
logError(QString("Invalid map name '%1'").arg(map_name));
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the destination map.
|
||||
if (!userSetMap(map_name))
|
||||
return;
|
||||
|
|
@ -2780,15 +2773,11 @@ void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() {
|
|||
}
|
||||
|
||||
void MainWindow::on_button_OpenDiveMap_clicked() {
|
||||
const QString mapName = ui->comboBox_DiveMap->currentText();
|
||||
if (editor->project->mapNames.contains(mapName))
|
||||
userSetMap(mapName);
|
||||
userSetMap(ui->comboBox_DiveMap->currentText());
|
||||
}
|
||||
|
||||
void MainWindow::on_button_OpenEmergeMap_clicked() {
|
||||
const QString mapName = ui->comboBox_EmergeMap->currentText();
|
||||
if (editor->project->mapNames.contains(mapName))
|
||||
userSetMap(mapName);
|
||||
userSetMap(ui->comboBox_EmergeMap->currentText());
|
||||
}
|
||||
|
||||
void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) {
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ void Project::clearTilesetCache() {
|
|||
}
|
||||
|
||||
Map* Project::loadMap(QString mapName) {
|
||||
if (mapName == DYNAMIC_MAP_NAME)
|
||||
if (mapName == getDynamicMapName())
|
||||
return nullptr;
|
||||
|
||||
Map *map;
|
||||
|
|
@ -148,7 +148,6 @@ Map* Project::loadMap(QString mapName) {
|
|||
} else {
|
||||
map = new Map;
|
||||
map->setName(mapName);
|
||||
map->setConstantName(this->mapNamesToMapConstants.value(mapName)); // TODO: How should we handle if !mapNamesToMapConstants.contains(mapName) here
|
||||
}
|
||||
|
||||
if (!(loadMapData(map) && loadMapLayout(map))){
|
||||
|
|
@ -161,38 +160,36 @@ Map* Project::loadMap(QString mapName) {
|
|||
return map;
|
||||
}
|
||||
|
||||
const QSet<QString> defaultTopLevelMapFields = {
|
||||
"id",
|
||||
"name",
|
||||
"layout",
|
||||
"music",
|
||||
"region_map_section",
|
||||
"requires_flash",
|
||||
"weather",
|
||||
"map_type",
|
||||
"show_map_name",
|
||||
"battle_scene",
|
||||
"connections",
|
||||
"object_events",
|
||||
"warp_events",
|
||||
"coord_events",
|
||||
"bg_events",
|
||||
"shared_events_map",
|
||||
"shared_scripts_map",
|
||||
};
|
||||
|
||||
QSet<QString> Project::getTopLevelMapFields() {
|
||||
QSet<QString> topLevelMapFields = defaultTopLevelMapFields;
|
||||
void Project::initTopLevelMapFields() {
|
||||
static const QSet<QString> defaultTopLevelMapFields = {
|
||||
"id",
|
||||
"name",
|
||||
"layout",
|
||||
"music",
|
||||
"region_map_section",
|
||||
"requires_flash",
|
||||
"weather",
|
||||
"map_type",
|
||||
"show_map_name",
|
||||
"battle_scene",
|
||||
"connections",
|
||||
"object_events",
|
||||
"warp_events",
|
||||
"coord_events",
|
||||
"bg_events",
|
||||
"heal_locations",
|
||||
"shared_events_map",
|
||||
"shared_scripts_map",
|
||||
};
|
||||
this->topLevelMapFields = defaultTopLevelMapFields;
|
||||
if (projectConfig.mapAllowFlagsEnabled) {
|
||||
topLevelMapFields.insert("allow_cycling");
|
||||
topLevelMapFields.insert("allow_escaping");
|
||||
topLevelMapFields.insert("allow_running");
|
||||
this->topLevelMapFields.insert("allow_cycling");
|
||||
this->topLevelMapFields.insert("allow_escaping");
|
||||
this->topLevelMapFields.insert("allow_running");
|
||||
}
|
||||
|
||||
if (projectConfig.floorNumberEnabled) {
|
||||
topLevelMapFields.insert("floor_number");
|
||||
this->topLevelMapFields.insert("floor_number");
|
||||
}
|
||||
return topLevelMapFields;
|
||||
}
|
||||
|
||||
bool Project::readMapJson(const QString &mapName, QJsonDocument * out) {
|
||||
|
|
@ -215,6 +212,11 @@ bool Project::loadMapData(Map* map) {
|
|||
|
||||
QJsonObject mapObj = mapDoc.object();
|
||||
|
||||
// We should already know the map constant ID from the initial project launch, but we'll ensure it's correct here anyway.
|
||||
map->setConstantName(ParseUtil::jsonToQString(mapObj["id"]));
|
||||
this->mapNamesToMapConstants.insert(map->name(), map->constantName());
|
||||
this->mapConstantsToMapNames.insert(map->constantName(), map->name());
|
||||
|
||||
map->setSong(ParseUtil::jsonToQString(mapObj["music"]));
|
||||
map->setLayoutId(ParseUtil::jsonToQString(mapObj["layout"]));
|
||||
map->setLocation(ParseUtil::jsonToQString(mapObj["region_map_section"]));
|
||||
|
|
@ -353,9 +355,8 @@ bool Project::loadMapData(Map* map) {
|
|||
|
||||
// Check for custom fields
|
||||
/* // TODO: Re-enable
|
||||
QSet<QString> baseFields = this->getTopLevelMapFields();
|
||||
for (QString key : mapObj.keys()) {
|
||||
if (!baseFields.contains(key)) {
|
||||
if (!this->topLevelMapFields.contains(key)) {
|
||||
map->customHeaders.insert(key, mapObj[key]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1822,6 +1823,8 @@ bool Project::readMapGroups() {
|
|||
this->groupedMapNames.clear();
|
||||
this->mapNames.clear();
|
||||
|
||||
this->initTopLevelMapFields();
|
||||
|
||||
const QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::json_map_groups);
|
||||
fileWatcher.addPath(filepath);
|
||||
QJsonDocument mapGroupsDoc;
|
||||
|
|
@ -1832,14 +1835,20 @@ bool Project::readMapGroups() {
|
|||
|
||||
QJsonObject mapGroupsObj = mapGroupsDoc.object();
|
||||
QJsonArray mapGroupOrder = mapGroupsObj["group_order"].toArray();
|
||||
|
||||
const QString dynamicMapName = getDynamicMapName();
|
||||
|
||||
// Process the map group lists
|
||||
for (int groupIndex = 0; groupIndex < mapGroupOrder.size(); groupIndex++) {
|
||||
const QString groupName = ParseUtil::jsonToQString(mapGroupOrder.at(groupIndex));
|
||||
const QJsonArray mapNamesJson = mapGroupsObj.value(groupName).toArray();
|
||||
this->groupedMapNames.append(QStringList());
|
||||
this->groupNames.append(groupName);
|
||||
|
||||
// Process the names in this map group
|
||||
for (int j = 0; j < mapNamesJson.size(); j++) {
|
||||
const QString mapName = ParseUtil::jsonToQString(mapNamesJson.at(j));
|
||||
if (mapName == DYNAMIC_MAP_NAME) {
|
||||
if (mapName == dynamicMapName) {
|
||||
logWarn(QString("Ignoring map with reserved name '%1'.").arg(mapName));
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1877,7 +1886,7 @@ bool Project::readMapGroups() {
|
|||
this->mapGroups.insert(mapName, groupIndex);
|
||||
this->mapConstantsToMapNames.insert(mapConstant, mapName);
|
||||
this->mapNamesToMapConstants.insert(mapName, mapConstant);
|
||||
// TODO: Keep these updated
|
||||
// TODO: Either verify that these are known IDs, or make sure nothing breaks when they're unknown.
|
||||
this->mapNameToLayoutId.insert(mapName, ParseUtil::jsonToQString(mapObj["layout"]));
|
||||
this->mapNameToMapSectionName.insert(mapName, ParseUtil::jsonToQString(mapObj["region_map_section"]));
|
||||
}
|
||||
|
|
@ -1892,10 +1901,11 @@ bool Project::readMapGroups() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Save special "Dynamic" constant
|
||||
const QString defineName = this->getDynamicMapDefineName();
|
||||
this->mapConstantsToMapNames.insert(defineName, DYNAMIC_MAP_NAME);
|
||||
this->mapNamesToMapConstants.insert(DYNAMIC_MAP_NAME, defineName);
|
||||
this->mapNames.append(DYNAMIC_MAP_NAME);
|
||||
this->mapConstantsToMapNames.insert(defineName, dynamicMapName);
|
||||
this->mapNamesToMapConstants.insert(dynamicMapName, defineName);
|
||||
this->mapNames.append(dynamicMapName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2941,6 +2951,10 @@ QString Project::getDynamicMapDefineName() {
|
|||
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
|
||||
}
|
||||
|
||||
QString Project::getDynamicMapName() {
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::symbol_dynamic_map_name);
|
||||
}
|
||||
|
||||
// If the provided filepath is an absolute path to an existing file, return filepath.
|
||||
// If not, and the provided filepath is a relative path from the project dir to an existing file, return the relative path.
|
||||
// Otherwise return empty string.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ NewMapDialog::NewMapDialog(QWidget *parent, Project *project) :
|
|||
this->importedMap = false;
|
||||
|
||||
// Map names and IDs can only contain word characters, and cannot start with a digit.
|
||||
// TODO: Also validate this when we read ProjectIdentifier::define_map_prefix from the config
|
||||
static const QRegularExpression re("[A-Za-z_]+[\\w]*");
|
||||
auto validator = new QRegularExpressionValidator(re, this);
|
||||
ui->lineEdit_Name->setValidator(validator);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user