Read/write MAPSEC values using the region map json
This commit is contained in:
parent
7d89031273
commit
d448765d63
18 changed files with 143 additions and 241 deletions
|
@ -59,7 +59,6 @@ The filepath that Porymap expects for each file can be overridden on the ``Files
|
|||
include/constants/event_object_movement.h, yes, no, ``constants_obj_event_movement``,
|
||||
include/constants/event_objects.h, yes, no, ``constants_obj_events``,
|
||||
include/constants/event_bg.h, yes, no, ``constants_event_bg``,
|
||||
include/constants/region_map_sections.h, yes, no, ``constants_region_map_sections``,
|
||||
include/constants/metatile_labels.h, yes, yes, ``constants_metatile_labels``,
|
||||
include/constants/metatile_behaviors.h, yes, no, ``constants_metatile_behaviors``,
|
||||
include/constants/species.h, yes, no, ``constants_metatile_behaviors``, for the Wild Pokémon tab
|
||||
|
@ -122,7 +121,6 @@ In addition to these files, there are some specific symbol and macro names that
|
|||
``define_map_empty``, ``UNDEFINED``, macro name after prefix for empty maps
|
||||
``define_map_section_prefix``, ``MAPSEC_``, expected prefix for location macro names
|
||||
``define_map_section_empty``, ``NONE``, macro name after prefix for empty region map sections
|
||||
``define_map_section_count``, ``COUNT``, macro name after prefix for total number of region map sections
|
||||
``define_species_prefix``, ``SPECIES_``, expected prefix for species macro names
|
||||
``regex_behaviors``, ``\bMB_``, regex to find metatile behavior macro names
|
||||
``regex_obj_event_gfx``, ``\bOBJ_EVENT_GFX_``, regex to find Object Event graphics ID macro names
|
||||
|
|
|
@ -213,7 +213,6 @@ enum ProjectIdentifier {
|
|||
define_map_empty,
|
||||
define_map_section_prefix,
|
||||
define_map_section_empty,
|
||||
define_map_section_count,
|
||||
define_species_prefix,
|
||||
regex_behaviors,
|
||||
regex_obj_event_gfx,
|
||||
|
@ -269,7 +268,6 @@ enum ProjectFilePath {
|
|||
constants_obj_event_movement,
|
||||
constants_obj_events,
|
||||
constants_event_bg,
|
||||
constants_region_map_sections,
|
||||
constants_metatile_labels,
|
||||
constants_metatile_behaviors,
|
||||
constants_species,
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
bool loadLayout(poryjson::Json);
|
||||
bool loadEntries();
|
||||
|
||||
void setEntries(tsl::ordered_map<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
|
||||
void setEntries(tsl::ordered_map<QString, MapSectionEntry> entries) { *(this->region_map_entries) = entries; }
|
||||
void setEntries(QMap<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
|
||||
void setEntries(const QMap<QString, MapSectionEntry> &entries) { *(this->region_map_entries) = entries; }
|
||||
void clearEntries() { this->region_map_entries->clear(); }
|
||||
MapSectionEntry getEntry(QString section);
|
||||
void setEntry(QString section, MapSectionEntry entry);
|
||||
|
@ -114,8 +114,6 @@ public:
|
|||
void setLayer(QString layer) { this->current_layer = layer; }
|
||||
QString getLayer() { return this->current_layer; }
|
||||
|
||||
QString fixCase(QString);
|
||||
|
||||
int padLeft() { return this->offset_left; }
|
||||
int padTop() { return this->offset_top; }
|
||||
int padRight() { return this->tilemap_width - this->layout_width - this->offset_left; }
|
||||
|
@ -149,14 +147,12 @@ public:
|
|||
|
||||
const QString section_prefix;
|
||||
const QString default_map_section;
|
||||
const QString count_map_section;
|
||||
|
||||
signals:
|
||||
void mapNeedsDisplaying();
|
||||
|
||||
private:
|
||||
// TODO: defaults needed?
|
||||
tsl::ordered_map<QString, MapSectionEntry> *region_map_entries = nullptr;
|
||||
QMap<QString, MapSectionEntry> *region_map_entries = nullptr;
|
||||
|
||||
QString alias = "";
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ private:
|
|||
/// ClearEntries
|
||||
class ClearEntries : public QUndoCommand {
|
||||
public:
|
||||
ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
|
||||
ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
|
||||
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
@ -163,7 +163,7 @@ public:
|
|||
|
||||
private:
|
||||
RegionMap *map;
|
||||
tsl::ordered_map<QString, MapSectionEntry> entries;
|
||||
QMap<QString, MapSectionEntry> entries;
|
||||
};
|
||||
|
||||
#endif // REGIONMAPEDITCOMMANDS_H
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
struct WildPokemon {
|
||||
int minLevel = 5;
|
||||
int maxLevel = 5;
|
||||
QString species = "SPECIES_NONE";
|
||||
QString species = "SPECIES_NONE"; // TODO: Use define_species_prefix
|
||||
};
|
||||
|
||||
struct WildMonInfo {
|
||||
|
|
|
@ -49,9 +49,6 @@ public:
|
|||
QMap<QString, QString> layoutIdsToNames;
|
||||
QMap<QString, Layout*> mapLayouts;
|
||||
QMap<QString, Layout*> mapLayoutsMaster;
|
||||
QMap<QString, QString> mapSecToMapHoverName;
|
||||
QMap<QString, int> mapSectionNameToValue;
|
||||
QMap<int, QString> mapSectionValueToName;
|
||||
QMap<QString, EventGraphics*> eventGraphicsMap;
|
||||
QMap<QString, int> gfxDefines;
|
||||
QString defaultSong;
|
||||
|
@ -68,6 +65,8 @@ public:
|
|||
QStringList bgEventFacingDirections;
|
||||
QStringList trainerTypes;
|
||||
QStringList globalScriptLabels;
|
||||
QStringList mapSectionIdNames;
|
||||
QMap<QString, MapSectionEntry> regionMapEntries;
|
||||
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
|
||||
QMap<QString, uint16_t> unusedMetatileLabels;
|
||||
QMap<QString, uint32_t> metatileBehaviorMap;
|
||||
|
@ -82,9 +81,7 @@ public:
|
|||
int pokemonMaxLevel;
|
||||
int maxEncounterRate;
|
||||
bool wildEncountersLoaded;
|
||||
|
||||
// For files that are read and could contain extra text
|
||||
QMap<QString, QString> extraFileText;
|
||||
bool saveEmptyMapsec;
|
||||
|
||||
void set_root(QString);
|
||||
|
||||
|
@ -142,7 +139,7 @@ public:
|
|||
bool readSpeciesIconPaths();
|
||||
QMap<QString, QString> speciesToIconPath;
|
||||
|
||||
int appendMapsec(QString name);
|
||||
void addNewMapsec(QString name);
|
||||
|
||||
bool hasUnsavedChanges();
|
||||
bool hasUnsavedDataChanges = false;
|
||||
|
@ -172,7 +169,7 @@ public:
|
|||
void saveConfig();
|
||||
void saveMapLayouts();
|
||||
void saveMapGroups();
|
||||
void saveMapSections();
|
||||
void saveRegionMapSections();
|
||||
void saveWildMonData();
|
||||
void saveMapConstantsHeader();
|
||||
void saveHealLocations(Map*);
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
public:
|
||||
void setMap(QString mapName) { this->openMap = mapName; }
|
||||
|
||||
QStandardItem *createAreaItem(QString areaName, int areaIndex);
|
||||
QStandardItem *createAreaItem(QString areaName);
|
||||
QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex);
|
||||
|
||||
QStandardItem *insertAreaItem(QString areaName);
|
||||
|
|
|
@ -57,7 +57,6 @@ private:
|
|||
tsl::ordered_map<QString, RegionMap *> region_maps;
|
||||
|
||||
QString configFilepath;
|
||||
QString mapSectionFilepath;
|
||||
|
||||
poryjson::Json rmConfigJson;
|
||||
|
||||
|
@ -96,7 +95,7 @@ private:
|
|||
void saveConfig();
|
||||
bool loadRegionMapEntries();
|
||||
bool saveRegionMapEntries();
|
||||
tsl::ordered_map<QString, MapSectionEntry> region_map_entries;
|
||||
QMap<QString, MapSectionEntry> region_map_entries;
|
||||
|
||||
bool buildConfigDialog();
|
||||
poryjson::Json configRegionMapDialog();
|
||||
|
|
|
@ -110,7 +110,6 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{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"}},
|
||||
{ProjectIdentifier::define_species_prefix, {"define_species_prefix", "SPECIES_"}},
|
||||
// Regex
|
||||
{ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}},
|
||||
|
@ -167,7 +166,6 @@ const QMap<ProjectFilePath, QPair<QString, QString>> ProjectConfig::defaultPaths
|
|||
{ProjectFilePath::constants_obj_event_movement, { "constants_obj_event_movement", "include/constants/event_object_movement.h"}},
|
||||
{ProjectFilePath::constants_obj_events, { "constants_obj_events", "include/constants/event_objects.h"}},
|
||||
{ProjectFilePath::constants_event_bg, { "constants_event_bg", "include/constants/event_bg.h"}},
|
||||
{ProjectFilePath::constants_region_map_sections, { "constants_region_map_sections", "include/constants/region_map_sections.h"}},
|
||||
{ProjectFilePath::constants_metatile_labels, { "constants_metatile_labels", "include/constants/metatile_labels.h"}},
|
||||
{ProjectFilePath::constants_metatile_behaviors, { "constants_metatile_behaviors", "include/constants/metatile_behaviors.h"}},
|
||||
{ProjectFilePath::constants_species, { "constants_species", "include/constants/species.h"}},
|
||||
|
|
|
@ -19,8 +19,7 @@ using std::make_shared;
|
|||
|
||||
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))
|
||||
default_map_section(project->getEmptyMapsecName())
|
||||
{
|
||||
this->project = project;
|
||||
}
|
||||
|
@ -157,7 +156,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
|||
for (int x = 0; x < this->layout_width; x++) {
|
||||
int bin_index = x + y * this->layout_width;
|
||||
uint8_t square_section_id = mapBinData.at(bin_index);
|
||||
QString square_section_name = project->mapSectionValueToName.value(square_section_id);
|
||||
QString square_section_name = project->mapSectionIdNames.value(square_section_id, this->default_map_section);
|
||||
|
||||
LayoutSquare square;
|
||||
square.map_section = square_section_name;
|
||||
|
@ -401,7 +400,7 @@ void RegionMap::saveLayout() {
|
|||
for (int m = 0; m < this->layout_height; m++) {
|
||||
for (int n = 0; n < this->layout_width; n++) {
|
||||
int i = n + this->layout_width * m;
|
||||
data.append(this->project->mapSectionNameToValue.value(this->layouts["main"][i].map_section));
|
||||
data.append(this->project->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section));
|
||||
}
|
||||
}
|
||||
QFile bfile(fullPath(this->layout_path));
|
||||
|
@ -760,18 +759,15 @@ bool RegionMap::squareInLayout(int x, int y) {
|
|||
}
|
||||
|
||||
MapSectionEntry RegionMap::getEntry(QString section) {
|
||||
if (this->region_map_entries->contains(section))
|
||||
return this->region_map_entries->operator[](section);
|
||||
else
|
||||
return MapSectionEntry();
|
||||
return this->region_map_entries->value(section, MapSectionEntry());
|
||||
}
|
||||
|
||||
void RegionMap::setEntry(QString section, MapSectionEntry entry) {
|
||||
this->region_map_entries->operator[](section) = entry;
|
||||
this->region_map_entries->insert(section, entry);
|
||||
}
|
||||
|
||||
void RegionMap::removeEntry(QString section) {
|
||||
this->region_map_entries->erase(section);
|
||||
this->region_map_entries->remove(section);
|
||||
}
|
||||
|
||||
QString RegionMap::palPath() {
|
||||
|
@ -788,27 +784,6 @@ int RegionMap::getMapSquareIndex(int x, int y) {
|
|||
return ((index < tilemap.length()) && (index >= 0)) ? index : 0;
|
||||
}
|
||||
|
||||
// For turning a MAPSEC_NAME into a unique identifier sMapName-style variable.
|
||||
// CAPS_WITH_UNDERSCORE to CamelCase
|
||||
QString RegionMap::fixCase(QString caps) {
|
||||
bool big = true;
|
||||
QString camel;
|
||||
|
||||
static const QRegularExpression re_braced("({.*})");
|
||||
for (auto ch : caps.remove(re_braced).remove(this->section_prefix)) {
|
||||
if (ch == '_' || ch == ' ') {
|
||||
big = true;
|
||||
continue;
|
||||
}
|
||||
if (big) {
|
||||
camel += ch.toUpper();
|
||||
big = false;
|
||||
}
|
||||
else camel += ch.toLower();
|
||||
}
|
||||
return camel;
|
||||
}
|
||||
|
||||
QString RegionMap::fullPath(QString local) {
|
||||
return this->project->root + "/" + local;
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ void ResizeTilemap::undo() {
|
|||
|
||||
///
|
||||
|
||||
ClearEntries::ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry> entries, QUndoCommand *parent)
|
||||
ClearEntries::ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry> entries, QUndoCommand *parent)
|
||||
: QUndoCommand(parent) {
|
||||
setText("Clear Entries");
|
||||
|
||||
|
|
|
@ -1177,7 +1177,7 @@ bool MainWindow::setProjectUI() {
|
|||
ui->comboBox_Song->clear();
|
||||
ui->comboBox_Song->addItems(project->songNames);
|
||||
ui->comboBox_Location->clear();
|
||||
ui->comboBox_Location->addItems(project->mapSectionValueToName.values());
|
||||
ui->comboBox_Location->addItems(project->mapSectionIdNames);
|
||||
ui->comboBox_PrimaryTileset->clear();
|
||||
ui->comboBox_PrimaryTileset->addItems(project->primaryTilesetLabels);
|
||||
ui->comboBox_SecondaryTileset->clear();
|
||||
|
@ -1546,7 +1546,7 @@ void MainWindow::mapListAddArea() {
|
|||
|
||||
connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){
|
||||
const QString newAreaName = newNameDisplay->text();
|
||||
if (this->editor->project->mapSectionNameToValue.contains(newAreaName)){
|
||||
if (this->editor->project->mapSectionIdNames.contains(newAreaName)){
|
||||
errorMessageLabel->setText(QString("An area with the name '%1' already exists").arg(newAreaName));
|
||||
errorMessageLabel->setVisible(true);
|
||||
} else {
|
||||
|
|
169
src/project.cpp
169
src/project.cpp
|
@ -708,36 +708,45 @@ void Project::saveMapGroups() {
|
|||
mapGroupsFile.close();
|
||||
}
|
||||
|
||||
void Project::saveMapSections() {
|
||||
QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections);
|
||||
|
||||
QString text = QString("#ifndef GUARD_REGIONMAPSEC_H\n");
|
||||
text += QString("#define GUARD_REGIONMAPSEC_H\n\n");
|
||||
|
||||
int longestLength = 0;
|
||||
for (QString label : this->mapSectionNameToValue.keys()) {
|
||||
if (label.size() > longestLength)
|
||||
longestLength = label.size();
|
||||
void Project::saveRegionMapSections() {
|
||||
const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Could not open '%1' for writing").arg(filepath));
|
||||
return;
|
||||
}
|
||||
|
||||
longestLength += 1;
|
||||
const QString emptyMapsecName = getEmptyMapsecName();
|
||||
OrderedJson::array mapSectionArray;
|
||||
for (const auto &idName : this->mapSectionIdNames) {
|
||||
// The 'empty' map section (MAPSEC_NONE) isn't normally present in the region map sections data file.
|
||||
// We append this name to mapSectionIdNames ourselves if it isn't present, in which case we don't want to output data for it here.
|
||||
if (!this->saveEmptyMapsec && idName == emptyMapsecName)
|
||||
continue;
|
||||
|
||||
// TODO: Maybe print as an enum now that we can?
|
||||
for (int value : this->mapSectionValueToName.keys()) {
|
||||
QString line = QString("#define %1 0x%2\n")
|
||||
.arg(this->mapSectionValueToName[value], -1 * longestLength)
|
||||
.arg(QString("%1").arg(value, 2, 16, QLatin1Char('0')).toUpper());
|
||||
text += line;
|
||||
OrderedJson::object mapSectionObj;
|
||||
mapSectionObj["id"] = idName;
|
||||
|
||||
if (this->regionMapEntries.contains(idName)) {
|
||||
MapSectionEntry entry = this->regionMapEntries.value(idName);
|
||||
mapSectionObj["name"] = entry.name;
|
||||
mapSectionObj["x"] = entry.x;
|
||||
mapSectionObj["y"] = entry.y;
|
||||
mapSectionObj["width"] = entry.width;
|
||||
mapSectionObj["height"] = entry.height;
|
||||
}
|
||||
|
||||
mapSectionArray.append(mapSectionObj);
|
||||
}
|
||||
|
||||
// TODO: We should maybe consider another way to update MAPSEC values in this file, in case we break anything by relocating it to the bottom of the file.
|
||||
// (or alternatively keep separate strings for text before/after the MAPSEC values)
|
||||
text += "\n" + this->extraFileText[projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections)] + "\n";
|
||||
|
||||
text += QString("#endif // GUARD_REGIONMAPSEC_H\n");
|
||||
OrderedJson::object object;
|
||||
object["map_sections"] = mapSectionArray;
|
||||
|
||||
ignoreWatchedFileTemporarily(filepath);
|
||||
saveTextFile(filepath, text);
|
||||
OrderedJson json(object);
|
||||
OrderedJsonDoc jsonDoc(&json);
|
||||
jsonDoc.dump(&file);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void Project::saveWildMonData() {
|
||||
|
@ -1459,7 +1468,7 @@ void Project::updateLayout(Layout *layout) {
|
|||
void Project::saveAllDataStructures() {
|
||||
saveMapLayouts();
|
||||
saveMapGroups();
|
||||
saveMapSections();
|
||||
saveRegionMapSections();
|
||||
saveMapConstantsHeader();
|
||||
saveWildMonData();
|
||||
saveConfig();
|
||||
|
@ -2242,49 +2251,66 @@ bool Project::readFieldmapMasks() {
|
|||
}
|
||||
|
||||
bool Project::readRegionMapSections() {
|
||||
this->mapSectionNameToValue.clear();
|
||||
this->mapSectionValueToName.clear();
|
||||
this->mapSectionIdNames.clear();
|
||||
this->regionMapEntries.clear();
|
||||
this->saveEmptyMapsec = false;
|
||||
const QString defaultName = getEmptyMapsecName();
|
||||
const QString requiredPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix);
|
||||
|
||||
const QStringList regexList = {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.readCDefinesByRegex(filename, regexList);
|
||||
if (this->mapSectionNameToValue.isEmpty()) {
|
||||
logError(QString("Failed to read region map sections from %1.").arg(filename));
|
||||
QJsonDocument doc;
|
||||
const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
|
||||
if (!parser.tryParseJsonFile(&doc, filepath)) {
|
||||
logError(QString("Failed to read region map sections from '%1'").arg(filepath));
|
||||
return false;
|
||||
}
|
||||
fileWatcher.addPath(filepath);
|
||||
|
||||
for (QString defineName : this->mapSectionNameToValue.keys()) {
|
||||
this->mapSectionValueToName.insert(this->mapSectionNameToValue[defineName], defineName);
|
||||
QJsonArray mapSections = doc.object()["map_sections"].toArray();
|
||||
for (const auto &mapSection : mapSections) {
|
||||
// For each map section, "id" is the only required field. This is the field we use
|
||||
// to display the location names in various drop-downs.
|
||||
QJsonObject mapSectionObj = mapSection.toObject();
|
||||
const QString idName = ParseUtil::jsonToQString(mapSectionObj["id"]);
|
||||
if (!idName.startsWith(requiredPrefix)) {
|
||||
logWarn(QString("Ignoring data for map section '%1'. IDs must start with the prefix '%2'").arg(idName).arg(requiredPrefix));
|
||||
continue;
|
||||
}
|
||||
|
||||
this->mapSectionIdNames.append(idName);
|
||||
if (idName == defaultName) {
|
||||
// If the user has data for the 'empty' MAPSEC we need to know to output it later,
|
||||
// because we will otherwise add a dummy entry for this value.
|
||||
this->saveEmptyMapsec = true;
|
||||
}
|
||||
|
||||
// Map sections may have additional data indicating their position on the region map.
|
||||
// If they have this data, we can add them to the region map entry list.
|
||||
bool hasRegionMapData = true;
|
||||
static const QSet<QString> regionMapFieldNames = { "name", "x", "y", "width", "height" };
|
||||
for (auto fieldName : regionMapFieldNames) {
|
||||
if (!mapSectionObj.contains(fieldName)) {
|
||||
hasRegionMapData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasRegionMapData)
|
||||
continue;
|
||||
|
||||
MapSectionEntry entry;
|
||||
entry.name = ParseUtil::jsonToQString(mapSectionObj["name"]);
|
||||
entry.x = ParseUtil::jsonToInt(mapSectionObj["x"]);
|
||||
entry.y = ParseUtil::jsonToInt(mapSectionObj["y"]);
|
||||
entry.width = ParseUtil::jsonToInt(mapSectionObj["width"]);
|
||||
entry.height = ParseUtil::jsonToInt(mapSectionObj["height"]);
|
||||
entry.valid = true;
|
||||
this->regionMapEntries[idName] = entry;
|
||||
}
|
||||
|
||||
// extra text
|
||||
QString extraText;
|
||||
QString fileText = ParseUtil::readTextFile(root + "/" + filename);
|
||||
QTextStream stream(&fileText);
|
||||
QString currentLine;
|
||||
while (stream.readLineInto(¤tLine)) {
|
||||
// is this line something that porymap will output again?
|
||||
if (currentLine.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// include guards
|
||||
// TODO: Assuming guard name is the same across projects (it isn't)
|
||||
else if (currentLine.contains("GUARD_REGIONMAPSEC_H")) {
|
||||
continue;
|
||||
}
|
||||
// defines captured
|
||||
// TODO: Regex to consider comments/extra space
|
||||
else if (currentLine.contains("#define " + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))) {
|
||||
continue;
|
||||
}
|
||||
// everything else should be kept here
|
||||
else {
|
||||
extraText += currentLine + "\n";
|
||||
}
|
||||
// Make sure the default name is present in the list.
|
||||
if (!this->mapSectionIdNames.contains(defaultName)) {
|
||||
this->mapSectionIdNames.append(defaultName);
|
||||
}
|
||||
stream.seek(0);
|
||||
this->extraFileText[filename] = extraText;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2292,24 +2318,15 @@ QString Project::getEmptyMapsecName() {
|
|||
return projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty);
|
||||
}
|
||||
|
||||
// This function assumes a valid and unique name.
|
||||
// Will return the new index.
|
||||
int Project::appendMapsec(QString name) {
|
||||
const QString emptyMapsecName = getEmptyMapsecName();
|
||||
int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey();
|
||||
|
||||
// If the user has the 'empty' MAPSEC value defined last in the list we'll shift it so that it stays last in the list.
|
||||
if (this->mapSectionNameToValue.contains(emptyMapsecName) && this->mapSectionNameToValue.value(emptyMapsecName) == newMapsecValue) {
|
||||
this->mapSectionNameToValue.insert(emptyMapsecName, newMapsecValue + 1);
|
||||
this->mapSectionValueToName.insert(newMapsecValue + 1, emptyMapsecName);
|
||||
// This function assumes a valid and unique name
|
||||
void Project::addNewMapsec(QString name) {
|
||||
if (!this->mapSectionIdNames.isEmpty() && this->mapSectionIdNames.last() == getEmptyMapsecName()) {
|
||||
// If the default map section name (MAPSEC_NONE) is last in the list we'll keep it last in the list.
|
||||
this->mapSectionIdNames.insert(this->mapSectionIdNames.length() - 1, name);
|
||||
} else {
|
||||
this->mapSectionIdNames.append(name);
|
||||
}
|
||||
|
||||
// TODO: Update 'define_map_section_count'?
|
||||
|
||||
this->mapSectionNameToValue[name] = newMapsecValue;
|
||||
this->mapSectionValueToName[newMapsecValue] = name;
|
||||
this->hasUnsavedDataChanges = true;
|
||||
return newMapsecValue;
|
||||
}
|
||||
|
||||
// Read the constants to preserve any "unused" heal locations when writing the file later
|
||||
|
|
|
@ -836,7 +836,7 @@ QString MainWindow::getLocation() {
|
|||
void MainWindow::setLocation(QString location) {
|
||||
if (!this->ui || !this->editor || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->mapSectionNameToValue.contains(location)) {
|
||||
if (!this->editor->project->mapSectionIdNames.contains(location)) {
|
||||
logError(QString("Unknown location '%1'").arg(location));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -282,7 +282,7 @@ QList<QString> ScriptUtility::getSongNames() {
|
|||
QList<QString> ScriptUtility::getLocationNames() {
|
||||
if (!window || !window->editor || !window->editor->project)
|
||||
return QList<QString>();
|
||||
return window->editor->project->mapSectionNameToValue.keys();
|
||||
return window->editor->project->mapSectionIdNames;
|
||||
}
|
||||
|
||||
QList<QString> ScriptUtility::getWeatherNames() {
|
||||
|
|
|
@ -413,13 +413,12 @@ MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(par
|
|||
initialize();
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::createAreaItem(QString mapsecName, int areaIndex) {
|
||||
QStandardItem *MapAreaModel::createAreaItem(QString mapsecName) {
|
||||
QStandardItem *area = new QStandardItem;
|
||||
area->setText(mapsecName);
|
||||
area->setEditable(false);
|
||||
area->setData(mapsecName, Qt::UserRole);
|
||||
area->setData("map_section", MapListUserRoles::TypeRole);
|
||||
area->setData(areaIndex, MapListUserRoles::GroupRole);
|
||||
// group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
this->areaItems.insert(mapsecName, area);
|
||||
return area;
|
||||
|
@ -437,20 +436,14 @@ QStandardItem *MapAreaModel::createMapItem(QString mapName, int, int) {
|
|||
}
|
||||
|
||||
QStandardItem *MapAreaModel::insertAreaItem(QString areaName) {
|
||||
int newAreaIndex = this->project->appendMapsec(areaName);
|
||||
QStandardItem *item = createAreaItem(areaName, newAreaIndex);
|
||||
this->root->insertRow(newAreaIndex, item);
|
||||
|
||||
// MAPSEC_NONE may have shifted to accomodate the new item, update it in the list.
|
||||
const QString emptyMapsecName = Project::getEmptyMapsecName();
|
||||
if (this->areaItems.contains(emptyMapsecName))
|
||||
this->areaItems[emptyMapsecName]->setData(this->project->mapSectionNameToValue.value(emptyMapsecName), MapListUserRoles::GroupRole);
|
||||
|
||||
this->project->addNewMapsec(areaName);
|
||||
QStandardItem *item = createAreaItem(areaName);
|
||||
this->root->appendRow(item);
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return item;
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, int groupIndex) {
|
||||
// int areaIndex = this->project->mapSectionNameToValue[areaName];
|
||||
QStandardItem *area = this->areaItems[areaName];
|
||||
if (!area) {
|
||||
return nullptr;
|
||||
|
@ -461,21 +454,18 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in
|
|||
return map;
|
||||
}
|
||||
|
||||
// Note: Not actually supported in the interface at the moment.
|
||||
void MapAreaModel::removeFolder(int index) {
|
||||
this->removeRow(index);
|
||||
this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(index));
|
||||
this->project->mapSectionIdNames.removeAt(index);
|
||||
}
|
||||
|
||||
void MapAreaModel::initialize() {
|
||||
this->areaItems.clear();
|
||||
this->mapItems.clear();
|
||||
this->setSortRole(MapListUserRoles::GroupRole);
|
||||
|
||||
// TODO: Ignore 'define_map_section_count' and/or 'define_map_section_empty'?
|
||||
for (int i : this->project->mapSectionNameToValue) {
|
||||
QString mapsecName = project->mapSectionValueToName.value(i);
|
||||
QStandardItem *areaItem = createAreaItem(mapsecName, i);
|
||||
this->root->appendRow(areaItem);
|
||||
for (const auto &idName : this->project->mapSectionIdNames) {
|
||||
this->root->appendRow(createAreaItem(idName));
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->project->groupNames.length(); i++) {
|
||||
|
@ -560,9 +550,7 @@ QVariant MapAreaModel::data(const QModelIndex &index, int role) const {
|
|||
QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
|
||||
if (type == "map_section") {
|
||||
return QString("[0x%1] %2")
|
||||
.arg(QString("%1").arg(item->data(MapListUserRoles::GroupRole).toInt(), 2, 16, QLatin1Char('0')).toUpper())
|
||||
.arg(item->data(Qt::UserRole).toString());
|
||||
return item->data(Qt::UserRole).toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,6 +591,7 @@ QStandardItem *LayoutTreeModel::createMapItem(QString mapName) {
|
|||
QStandardItem *LayoutTreeModel::insertLayoutItem(QString layoutId) {
|
||||
QStandardItem *layoutItem = this->createLayoutItem(layoutId);
|
||||
this->root->appendRow(layoutItem);
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return layoutItem;
|
||||
}
|
||||
|
||||
|
@ -644,6 +633,7 @@ void LayoutTreeModel::initialize() {
|
|||
this->layoutItems[layoutId]->appendRow(map);
|
||||
}
|
||||
}
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const {
|
||||
|
|
|
@ -34,7 +34,7 @@ void NewMapPopup::initUi() {
|
|||
ui->comboBox_NewMap_Group->addItems(project->groupNames);
|
||||
ui->comboBox_NewMap_Song->addItems(project->songNames);
|
||||
ui->comboBox_NewMap_Type->addItems(project->mapTypes);
|
||||
ui->comboBox_NewMap_Location->addItems(project->mapSectionNameToValue.keys());
|
||||
ui->comboBox_NewMap_Location->addItems(project->mapSectionIdNames);
|
||||
|
||||
const QSignalBlocker b(ui->comboBox_Layout);
|
||||
ui->comboBox_Layout->addItems(project->mapLayoutsTable);
|
||||
|
@ -186,7 +186,7 @@ void NewMapPopup::setDefaultSettings(Project *project) {
|
|||
settings.primaryTilesetLabel = project->getDefaultPrimaryTilesetLabel();
|
||||
settings.secondaryTilesetLabel = project->getDefaultSecondaryTilesetLabel();
|
||||
settings.type = project->mapTypes.value(0, "0");
|
||||
settings.location = project->mapSectionNameToValue.keys().value(0, "0");
|
||||
settings.location = project->mapSectionIdNames.value(0, "0");
|
||||
settings.song = project->defaultSong;
|
||||
settings.canFlyTo = false;
|
||||
settings.showLocationName = true;
|
||||
|
|
|
@ -29,7 +29,6 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project) :
|
|||
this->ui->setupUi(this);
|
||||
this->project = project;
|
||||
this->configFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_porymap_cfg));
|
||||
this->mapSectionFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
|
||||
this->initShortcuts();
|
||||
this->restoreWindowState();
|
||||
}
|
||||
|
@ -110,67 +109,13 @@ void RegionMapEditor::applyUserShortcuts() {
|
|||
}
|
||||
|
||||
bool RegionMapEditor::loadRegionMapEntries() {
|
||||
this->region_map_entries.clear();
|
||||
|
||||
ParseUtil parser;
|
||||
QJsonDocument sectionsDoc;
|
||||
if (!parser.tryParseJsonFile(§ionsDoc, this->mapSectionFilepath)) {
|
||||
logError(QString("Failed to read map data from %1").arg(this->mapSectionFilepath));
|
||||
return false;
|
||||
}
|
||||
|
||||
// for some unknown reason, the OrderedJson class would not parse this properly
|
||||
// perhaps updating nlohmann/json here would fix it, but that also requires using C++17
|
||||
QJsonObject object = sectionsDoc.object();
|
||||
|
||||
for (auto entryRef : object["map_sections"].toArray()) {
|
||||
QJsonObject entryObject = entryRef.toObject();
|
||||
QString entryMapSection = ParseUtil::jsonToQString(entryObject["map_section"]);
|
||||
MapSectionEntry entry;
|
||||
entry.name = ParseUtil::jsonToQString(entryObject["name"]);
|
||||
entry.x = ParseUtil::jsonToInt(entryObject["x"]);
|
||||
entry.y = ParseUtil::jsonToInt(entryObject["y"]);
|
||||
entry.width = ParseUtil::jsonToInt(entryObject["width"]);
|
||||
entry.height = ParseUtil::jsonToInt(entryObject["height"]);
|
||||
entry.valid = true;
|
||||
this->region_map_entries[entryMapSection] = entry;
|
||||
}
|
||||
|
||||
this->region_map_entries = this->project->regionMapEntries;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionMapEditor::saveRegionMapEntries() {
|
||||
QFile sectionsFile(this->mapSectionFilepath);
|
||||
if (!sectionsFile.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Could not open %1 for writing").arg(this->mapSectionFilepath));
|
||||
return false;
|
||||
}
|
||||
|
||||
OrderedJson::object object;
|
||||
OrderedJson::array mapSectionArray;
|
||||
|
||||
for (auto pair : this->region_map_entries) {
|
||||
QString section = pair.first;
|
||||
MapSectionEntry entry = pair.second;
|
||||
|
||||
OrderedJson::object entryObject;
|
||||
entryObject["map_section"] = section;
|
||||
entryObject["name"] = entry.name;
|
||||
entryObject["x"] = entry.x;
|
||||
entryObject["y"] = entry.y;
|
||||
entryObject["width"] = entry.width;
|
||||
entryObject["height"] = entry.height;
|
||||
|
||||
mapSectionArray.append(entryObject);
|
||||
}
|
||||
|
||||
object["map_sections"] = mapSectionArray;
|
||||
|
||||
OrderedJson sectionsJson(object);
|
||||
OrderedJsonDoc jsonDoc(§ionsJson);
|
||||
jsonDoc.dump(§ionsFile);
|
||||
sectionsFile.close();
|
||||
|
||||
this->project->regionMapEntries = this->region_map_entries;
|
||||
this->project->saveRegionMapSections();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -708,7 +653,7 @@ void RegionMapEditor::displayRegionMapLayoutOptions() {
|
|||
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
|
||||
this->ui->comboBox_RM_ConnectedMap->clear();
|
||||
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionValueToName.values());
|
||||
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionIdNames);
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
|
||||
|
||||
this->ui->frame_RM_Options->setEnabled(true);
|
||||
|
@ -775,7 +720,7 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
|
|||
if (!this->region_map->layoutEnabled()) return;
|
||||
|
||||
this->ui->comboBox_RM_Entry_MapSection->clear();
|
||||
this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionValueToName.values());
|
||||
this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionIdNames);
|
||||
this->ui->spinBox_RM_Entry_x->setMaximum(128);
|
||||
this->ui->spinBox_RM_Entry_y->setMaximum(128);
|
||||
this->ui->spinBox_RM_Entry_width->setMinimum(1);
|
||||
|
@ -787,17 +732,13 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
|
|||
void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
|
||||
if (!this->region_map->layoutEnabled()) return;
|
||||
|
||||
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));
|
||||
|
||||
bool enabled = (section != this->region_map->default_map_section) && 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(!isSpecialSection);
|
||||
this->ui->pushButton_entryActivate->setEnabled(section != this->region_map->default_map_section);
|
||||
this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add");
|
||||
|
||||
this->ui->lineEdit_RM_MapName->blockSignals(true);
|
||||
|
@ -902,14 +843,8 @@ void RegionMapEditor::onRegionMapEntryDragged(int new_x, int new_y) {
|
|||
}
|
||||
|
||||
void RegionMapEditor::onRegionMapLayoutSelectedTileChanged(int index) {
|
||||
QString message = QString();
|
||||
this->currIndex = index;
|
||||
this->region_map_layout_item->highlightedTile = index;
|
||||
if (this->region_map->squareHasMap(index)) {
|
||||
message = QString("\t %1").arg(this->project->mapSecToMapHoverName.value(
|
||||
this->region_map->squareMapSection(index))).remove("{NAME_END}");
|
||||
}
|
||||
this->ui->statusbar->showMessage(message);
|
||||
|
||||
updateRegionMapLayoutOptions(index);
|
||||
this->region_map_layout_item->draw();
|
||||
|
@ -922,8 +857,7 @@ void RegionMapEditor::onRegionMapLayoutHoveredTileChanged(int index) {
|
|||
if (x >= 0 && y >= 0) {
|
||||
message = QString("(%1, %2)").arg(x).arg(y);
|
||||
if (this->region_map->squareHasMap(index)) {
|
||||
message += QString("\t %1").arg(this->project->mapSecToMapHoverName.value(
|
||||
this->region_map->squareMapSection(index))).remove("{NAME_END}");
|
||||
message += QString("\t %1").arg(this->region_map->squareMapSection(index));
|
||||
}
|
||||
}
|
||||
this->ui->statusbar->showMessage(message);
|
||||
|
@ -1203,10 +1137,10 @@ void RegionMapEditor::on_action_Swap_triggered() {
|
|||
QFormLayout form(&popup);
|
||||
|
||||
QComboBox *oldSecBox = new QComboBox();
|
||||
oldSecBox->addItems(this->project->mapSectionValueToName.values());
|
||||
oldSecBox->addItems(this->project->mapSectionIdNames);
|
||||
form.addRow(new QLabel("Map Section 1:"), oldSecBox);
|
||||
QComboBox *newSecBox = new QComboBox();
|
||||
newSecBox->addItems(this->project->mapSectionValueToName.values());
|
||||
newSecBox->addItems(this->project->mapSectionIdNames);
|
||||
form.addRow(new QLabel("Map Section 2:"), newSecBox);
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);
|
||||
|
@ -1242,10 +1176,10 @@ void RegionMapEditor::on_action_Replace_triggered() {
|
|||
QFormLayout form(&popup);
|
||||
|
||||
QComboBox *oldSecBox = new QComboBox();
|
||||
oldSecBox->addItems(this->project->mapSectionValueToName.values());
|
||||
oldSecBox->addItems(this->project->mapSectionIdNames);
|
||||
form.addRow(new QLabel("Old Map Section:"), oldSecBox);
|
||||
QComboBox *newSecBox = new QComboBox();
|
||||
newSecBox->addItems(this->project->mapSectionValueToName.values());
|
||||
newSecBox->addItems(this->project->mapSectionIdNames);
|
||||
form.addRow(new QLabel("New Map Section:"), newSecBox);
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);
|
||||
|
|
Loading…
Reference in a new issue