mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-22 00:26:37 -05:00
Reserve MAP_DYNAMIC, fix some MAPSEC displays not updating, new error messages/handling
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>238</width>
|
||||
<height>106</height>
|
||||
<height>107</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
@@ -56,6 +56,9 @@
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The constant that will be used to refer to this layout. It cannot be the same as any other existing layout.</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
|
||||
@@ -349,7 +349,9 @@ private:
|
||||
void clearProjectUI();
|
||||
|
||||
void openNewMapDialog();
|
||||
void openDuplicateMapDialog(const QString &mapName);
|
||||
void openNewLayoutDialog();
|
||||
void openDuplicateLayoutDialog(const QString &layoutId);
|
||||
void openSubWindow(QWidget * window);
|
||||
void scrollMapList(MapTree *list, const QString &itemName);
|
||||
void scrollMapListToCurrentMap(MapTree *list);
|
||||
@@ -360,6 +362,7 @@ private:
|
||||
bool openProject(QString dir, bool initial = false);
|
||||
bool closeProject();
|
||||
void showProjectOpenFailure();
|
||||
void showMapsExcludedAlert(const QStringList &excludedMapNames);
|
||||
|
||||
bool setInitialMap();
|
||||
void saveGlobalConfigs();
|
||||
@@ -408,7 +411,7 @@ private:
|
||||
void scrollMetatileSelectorToSelection();
|
||||
MapListToolBar* getCurrentMapListToolBar();
|
||||
MapTree* getCurrentMapList();
|
||||
void refreshLocationsComboBox();
|
||||
void setLocationComboBoxes(const QStringList &locations);
|
||||
|
||||
QObjectList shortcutableObjects() const;
|
||||
void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);
|
||||
|
||||
@@ -280,6 +280,7 @@ signals:
|
||||
void mapGroupAdded(const QString &groupName);
|
||||
void mapSectionAdded(const QString &idName);
|
||||
void mapSectionIdNamesChanged(const QStringList &idNames);
|
||||
void mapsExcluded(const QStringList &excludedMapNames);
|
||||
};
|
||||
|
||||
#endif // PROJECT_H
|
||||
|
||||
@@ -44,6 +44,8 @@ public:
|
||||
|
||||
bool reconfigure();
|
||||
|
||||
void setLocations(const QStringList &locations);
|
||||
|
||||
QObjectList shortcutableObjects() const;
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -397,10 +397,15 @@ void RegionMap::saveLayout() {
|
||||
case LayoutFormat::Binary:
|
||||
{
|
||||
QByteArray data;
|
||||
int defaultValue = this->project->mapSectionIdNames.indexOf(this->default_map_section);
|
||||
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->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section));
|
||||
int mapSectionValue = this->project->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section);
|
||||
if (mapSectionValue < 0){
|
||||
mapSectionValue = defaultValue;
|
||||
}
|
||||
data.append(mapSectionValue);
|
||||
}
|
||||
}
|
||||
QFile bfile(fullPath(this->layout_path));
|
||||
|
||||
@@ -627,7 +627,8 @@ bool MainWindow::openProject(QString dir, bool initial) {
|
||||
connect(project, &Project::tilesetCreated, this, &MainWindow::onNewTilesetCreated);
|
||||
connect(project, &Project::mapGroupAdded, this, &MainWindow::onNewMapGroupCreated);
|
||||
connect(project, &Project::mapSectionAdded, this, &MainWindow::onNewMapSectionCreated);
|
||||
connect(project, &Project::mapSectionIdNamesChanged, this->mapHeaderForm, &MapHeaderForm::setLocations);
|
||||
connect(project, &Project::mapSectionIdNamesChanged, this, &MainWindow::setLocationComboBoxes);
|
||||
connect(project, &Project::mapsExcluded, this, &MainWindow::showMapsExcludedAlert);
|
||||
this->editor->setProject(project);
|
||||
|
||||
// Make sure project looks reasonable before attempting to load it
|
||||
@@ -702,6 +703,22 @@ void MainWindow::showProjectOpenFailure() {
|
||||
error.exec();
|
||||
}
|
||||
|
||||
// Alert the user that one or more maps have been excluded while loading the project.
|
||||
void MainWindow::showMapsExcludedAlert(const QStringList &excludedMapNames) {
|
||||
QMessageBox msgBox(QMessageBox::Icon::Warning, "porymap", "", QMessageBox::Ok, this);
|
||||
|
||||
QString errorMsg;
|
||||
if (excludedMapNames.length() == 1) {
|
||||
errorMsg = QString("Failed to load map '%1'. Saving will exclude this map from your project.").arg(excludedMapNames.first());
|
||||
} else {
|
||||
errorMsg = QString("Failed to load the maps listed below. Saving will exclude these maps from your project.");
|
||||
msgBox.setDetailedText(excludedMapNames.join("\n"));
|
||||
}
|
||||
errorMsg.append(QString("\n\nPlease see %1 for full error details.").arg(getLogPath()));
|
||||
msgBox.setText(errorMsg);
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
bool MainWindow::isProjectOpen() {
|
||||
return editor && editor->project;
|
||||
}
|
||||
@@ -861,19 +878,23 @@ bool MainWindow::userSetMap(QString map_name) {
|
||||
return true; // Already set
|
||||
|
||||
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.warning(nullptr, "Cannot Open Map", errorMsg);
|
||||
QMessageBox msgBox(QMessageBox::Icon::Warning,
|
||||
"Cannot Open Map",
|
||||
QString("The map '%1' can't be opened, it's a placeholder to indicate the specified map will be set programmatically.").arg(map_name),
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
msgBox.exec();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!setMap(map_name)) {
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3")
|
||||
.arg(map_name)
|
||||
.arg(getLogPath())
|
||||
.arg(getMostRecentError());
|
||||
msgBox.critical(nullptr, "Error Opening Map", errorMsg);
|
||||
QMessageBox msgBox(QMessageBox::Icon::Critical,
|
||||
"Error Opening Map",
|
||||
QString("There was an error opening map %1.\n\nPlease see %2 for full error details.").arg(map_name).arg(getLogPath()),
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
msgBox.setDetailedText(getMostRecentError());
|
||||
msgBox.exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -929,12 +950,13 @@ void MainWindow::setLayoutOnlyMode(bool layoutOnly) {
|
||||
// Use when the user is specifically requesting a layout to open.
|
||||
bool MainWindow::userSetLayout(QString layoutId) {
|
||||
if (!setLayout(layoutId)) {
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("There was an error opening layout %1. Please see %2 for full error details.\n\n%3")
|
||||
.arg(layoutId)
|
||||
.arg(getLogPath())
|
||||
.arg(getMostRecentError());
|
||||
msgBox.critical(nullptr, "Error Opening Layout", errorMsg);
|
||||
QMessageBox msgBox(QMessageBox::Icon::Critical,
|
||||
"Error Opening Layout",
|
||||
QString("There was an error opening layout %1.\n\nPlease see %2 for full error details.").arg(layoutId).arg(getLogPath()),
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
msgBox.setDetailedText(getMostRecentError());
|
||||
msgBox.exec();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1217,8 +1239,7 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
|
||||
copyToolTipAction = menu.addAction("Copy Map ID");
|
||||
menu.addSeparator();
|
||||
connect(menu.addAction("Duplicate Map"), &QAction::triggered, [this, itemName] {
|
||||
auto dialog = new NewMapDialog(this->editor->project, this->editor->project->getMap(itemName), this);
|
||||
dialog->open();
|
||||
openDuplicateMapDialog(itemName);
|
||||
});
|
||||
//menu.addSeparator();
|
||||
//connect(menu.addAction("Delete Map"), &QAction::triggered, [this, index] { deleteMapListItem(index); }); // TODO: No support for deleting maps
|
||||
@@ -1244,12 +1265,7 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
|
||||
copyToolTipAction = menu.addAction("Copy Layout ID");
|
||||
menu.addSeparator();
|
||||
connect(menu.addAction("Duplicate Layout"), &QAction::triggered, [this, itemName] {
|
||||
auto layout = this->editor->project->loadLayout(itemName);
|
||||
if (layout) {
|
||||
auto dialog = new NewLayoutDialog(this->editor->project, layout, this);
|
||||
connect(dialog, &NewLayoutDialog::applied, this, &MainWindow::userSetLayout);
|
||||
dialog->open();
|
||||
}
|
||||
openDuplicateLayoutDialog(itemName);
|
||||
});
|
||||
addToFolderAction = menu.addAction("Add New Map with Layout");
|
||||
//menu.addSeparator();
|
||||
@@ -1436,8 +1452,12 @@ void MainWindow::onNewMapGroupCreated(const QString &groupName) {
|
||||
void MainWindow::onNewMapSectionCreated(const QString &idName) {
|
||||
// Add new map section to the Areas map list view
|
||||
this->mapAreaModel->insertMapFolderItem(idName);
|
||||
}
|
||||
|
||||
// TODO: Refresh Region Map Editor's map section dropdown, if it's open
|
||||
void MainWindow::setLocationComboBoxes(const QStringList &locations) {
|
||||
this->mapHeaderForm->setLocations(locations);
|
||||
if (this->regionMapEditor)
|
||||
this->regionMapEditor->setLocations(locations);
|
||||
}
|
||||
|
||||
void MainWindow::onNewTilesetCreated(Tileset *tileset) {
|
||||
@@ -1460,12 +1480,33 @@ void MainWindow::openNewMapDialog() {
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void MainWindow::openDuplicateMapDialog(const QString &mapName) {
|
||||
const Map *map = this->editor->project->getMap(mapName);
|
||||
if (map) {
|
||||
auto dialog = new NewMapDialog(this->editor->project, map, this);
|
||||
dialog->open();
|
||||
} else {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::openNewLayoutDialog() {
|
||||
auto dialog = new NewLayoutDialog(this->editor->project, this);
|
||||
connect(dialog, &NewLayoutDialog::applied, this, &MainWindow::userSetLayout);
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void MainWindow::openDuplicateLayoutDialog(const QString &layoutId) {
|
||||
auto layout = this->editor->project->loadLayout(layoutId);
|
||||
if (layout) {
|
||||
auto dialog = new NewLayoutDialog(this->editor->project, layout, this);
|
||||
connect(dialog, &NewLayoutDialog::applied, this, &MainWindow::userSetLayout);
|
||||
dialog->open();
|
||||
} else {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionNew_Tileset_triggered() {
|
||||
auto dialog = new NewTilesetDialog(editor->project, this);
|
||||
dialog->open();
|
||||
|
||||
110
src/project.cpp
110
src/project.cpp
@@ -406,10 +406,10 @@ Map *Project::createNewMap(const Project::NewMapSettings &settings, const Map* t
|
||||
mapNamePos = this->mapNames.length();
|
||||
}
|
||||
|
||||
if (!this->mapSectionIdNames.contains(map->header()->location())) {
|
||||
const QString location = map->header()->location();
|
||||
if (!this->mapSectionIdNames.contains(location) && isIdentifierUnique(location)) {
|
||||
// Unrecognized MAPSEC value. Add it.
|
||||
// TODO: Validate location before adding
|
||||
addNewMapsec(map->header()->location());
|
||||
addNewMapsec(location);
|
||||
}
|
||||
|
||||
this->mapNames.insert(mapNamePos, map->name());
|
||||
@@ -492,15 +492,12 @@ bool Project::loadLayout(Layout *layout) {
|
||||
}
|
||||
|
||||
Layout *Project::loadLayout(QString layoutId) {
|
||||
if (this->mapLayouts.contains(layoutId)) {
|
||||
Layout *layout = this->mapLayouts[layoutId];
|
||||
if (loadLayout(layout)) {
|
||||
return layout;
|
||||
}
|
||||
Layout *layout = this->mapLayouts.value(layoutId);
|
||||
if (!layout || !loadLayout(layout)) {
|
||||
logError(QString("Failed to load layout '%1'").arg(layoutId));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
logError(QString("Failed to load layout '%1'").arg(layoutId));
|
||||
return nullptr;
|
||||
return layout;
|
||||
}
|
||||
|
||||
bool Project::loadMapLayout(Map* map) {
|
||||
@@ -508,12 +505,12 @@ bool Project::loadMapLayout(Map* map) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->mapLayouts.contains(map->layoutId())) {
|
||||
map->setLayout(this->mapLayouts[map->layoutId()]);
|
||||
} else {
|
||||
Layout *layout = this->mapLayouts.value(map->layoutId());
|
||||
if (!layout) {
|
||||
logError(QString("Map '%1' has an unknown layout '%2'").arg(map->name()).arg(map->layoutId()));
|
||||
return false;
|
||||
}
|
||||
map->setLayout(layout);
|
||||
|
||||
if (map->hasUnsavedChanges()) {
|
||||
return true;
|
||||
@@ -558,24 +555,11 @@ bool Project::readMapLayouts() {
|
||||
.arg(layoutsLabel));
|
||||
}
|
||||
|
||||
static const QList<QString> requiredFields = QList<QString>{
|
||||
"id",
|
||||
"name",
|
||||
"width",
|
||||
"height",
|
||||
"primary_tileset",
|
||||
"secondary_tileset",
|
||||
"border_filepath",
|
||||
"blockdata_filepath",
|
||||
};
|
||||
QStringList failedLayoutNames; // TODO: Populate
|
||||
for (int i = 0; i < layouts.size(); i++) {
|
||||
QJsonObject layoutObj = layouts[i].toObject();
|
||||
if (layoutObj.isEmpty())
|
||||
continue;
|
||||
if (!parser.ensureFieldsExist(layoutObj, requiredFields)) {
|
||||
logError(QString("Layout %1 is missing field(s) in %2.").arg(i).arg(layoutsFilepath));
|
||||
return false;
|
||||
}
|
||||
Layout *layout = new Layout();
|
||||
layout->id = ParseUtil::jsonToQString(layoutObj["id"]);
|
||||
if (layout->id.isEmpty()) {
|
||||
@@ -611,15 +595,11 @@ bool Project::readMapLayouts() {
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
int bwidth = ParseUtil::jsonToInt(layoutObj["border_width"]);
|
||||
if (bwidth <= 0) { // 0 is an expected border width/height that should be handled, GF used it for the RS layouts in FRLG
|
||||
logWarn(QString("Invalid 'border_width' value '%1' for %2 in %3. Must be greater than 0. Using default (%4) instead.")
|
||||
.arg(bwidth).arg(layout->id).arg(layoutsFilepath).arg(DEFAULT_BORDER_WIDTH));
|
||||
bwidth = DEFAULT_BORDER_WIDTH;
|
||||
}
|
||||
layout->border_width = bwidth;
|
||||
int bheight = ParseUtil::jsonToInt(layoutObj["border_height"]);
|
||||
if (bheight <= 0) {
|
||||
logWarn(QString("Invalid 'border_height' value '%1' for %2 in %3. Must be greater than 0. Using default (%4) instead.")
|
||||
.arg(bheight).arg(layout->id).arg(layoutsFilepath).arg(DEFAULT_BORDER_HEIGHT));
|
||||
bheight = DEFAULT_BORDER_HEIGHT;
|
||||
}
|
||||
layout->border_height = bheight;
|
||||
@@ -1817,8 +1797,10 @@ bool Project::readMapGroups() {
|
||||
QJsonArray mapGroupOrder = mapGroupsObj["group_order"].toArray();
|
||||
|
||||
const QString dynamicMapName = getDynamicMapName();
|
||||
const QString dynamicMapConstant = getDynamicMapDefineName();
|
||||
|
||||
// Process the map group lists
|
||||
QStringList failedMapNames;
|
||||
for (int groupIndex = 0; groupIndex < mapGroupOrder.size(); groupIndex++) {
|
||||
const QString groupName = ParseUtil::jsonToQString(mapGroupOrder.at(groupIndex));
|
||||
const QJsonArray mapNamesJson = mapGroupsObj.value(groupName).toArray();
|
||||
@@ -1829,45 +1811,73 @@ bool Project::readMapGroups() {
|
||||
const QString mapName = ParseUtil::jsonToQString(mapNamesJson.at(j));
|
||||
if (mapName == dynamicMapName) {
|
||||
logWarn(QString("Ignoring map with reserved name '%1'.").arg(mapName));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
if (this->mapNames.contains(mapName)) {
|
||||
logWarn(QString("Ignoring repeated map name '%1'.").arg(mapName));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load the map's json file so we can get its ID constant (and two other constants we use for the map list).
|
||||
QJsonDocument mapDoc;
|
||||
if (!readMapJson(mapName, &mapDoc))
|
||||
if (!readMapJson(mapName, &mapDoc)) {
|
||||
failedMapNames.append(mapName);
|
||||
continue; // Error message has already been logged
|
||||
}
|
||||
|
||||
// Read and validate the map's ID from its JSON data.
|
||||
const QJsonObject mapObj = mapDoc.object();
|
||||
const QString mapConstant = ParseUtil::jsonToQString(mapObj["id"]);
|
||||
if (mapConstant.isEmpty()) {
|
||||
logWarn(QString("Map '%1' is missing an \"id\" value and will be ignored.").arg(mapName));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
if (mapConstant == dynamicMapConstant) {
|
||||
logWarn(QString("Ignoring map with reserved \"id\" value '%1'.").arg(mapName));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
const QString expectedPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
if (!mapConstant.startsWith(expectedPrefix)) {
|
||||
logWarn(QString("Map '%1' has invalid \"id\" value '%2' and will be ignored. Value must begin with '%3'.").arg(mapName).arg(mapConstant).arg(expectedPrefix));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
auto it = this->mapConstantsToMapNames.constFind(mapConstant);
|
||||
if (it != this->mapConstantsToMapNames.constEnd()) {
|
||||
logWarn(QString("Map '%1' has the same \"id\" value '%2' as map '%3' and will be ignored.").arg(mapName).arg(it.key()).arg(it.value()));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read layout ID for map list
|
||||
const QString layoutId = ParseUtil::jsonToQString(mapObj["layout"]);
|
||||
if (!this->layoutIds.contains(layoutId)) {
|
||||
// If a map has an unknown layout ID it won't be able to load it at all anyway, so skip it.
|
||||
// Skipping these will let us assume all the map layout IDs are valid, which simplies some handling elsewhere.
|
||||
logWarn(QString("Map '%1' has unknown \"layout\" value '%2' and will be ignored.").arg(mapName).arg(layoutId));
|
||||
failedMapNames.append(mapName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read MAPSEC name for map list
|
||||
const QString mapSectionName = ParseUtil::jsonToQString(mapObj["region_map_section"]);
|
||||
if (!this->mapSectionIdNames.contains(mapSectionName)) {
|
||||
// An unknown location is OK. Aside from that name not appearing in the dropdowns this shouldn't cause problems.
|
||||
// We'll log a warning, but allow this map to be displayed.
|
||||
logWarn(QString("Map '%1' has unknown \"region_map_section\" value '%2'.").arg(mapName).arg(mapSectionName));
|
||||
}
|
||||
|
||||
// Success, save the constants to the project
|
||||
this->mapNames.append(mapName);
|
||||
this->groupNameToMapNames[groupName].append(mapName);
|
||||
// TODO: These are not well-kept in sync (and that's probably a bad design indication. Maybe Maps should have a not-fully-loaded state, but have all their map.json data cached)
|
||||
this->mapConstantsToMapNames.insert(mapConstant, mapName);
|
||||
this->mapNamesToMapConstants.insert(mapName, mapConstant);
|
||||
// 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"]));
|
||||
this->mapNameToLayoutId.insert(mapName, layoutId);
|
||||
this->mapNameToMapSectionName.insert(mapName, mapSectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1880,10 +1890,15 @@ bool Project::readMapGroups() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!failedMapNames.isEmpty()) {
|
||||
// At least 1 map was excluded due to an error.
|
||||
// User should be alerted of this, rather than just silently logging the details.
|
||||
emit mapsExcluded(failedMapNames);
|
||||
}
|
||||
|
||||
// Save special "Dynamic" constant
|
||||
const QString defineName = this->getDynamicMapDefineName();
|
||||
this->mapConstantsToMapNames.insert(defineName, dynamicMapName);
|
||||
this->mapNamesToMapConstants.insert(dynamicMapName, defineName);
|
||||
this->mapConstantsToMapNames.insert(dynamicMapConstant, dynamicMapName);
|
||||
this->mapNamesToMapConstants.insert(dynamicMapName, dynamicMapConstant);
|
||||
this->mapNames.append(dynamicMapName);
|
||||
|
||||
return true;
|
||||
@@ -2274,10 +2289,18 @@ bool Project::readRegionMapSections() {
|
||||
QJsonObject mapSectionObj = mapSections.at(i).toObject();
|
||||
|
||||
// For each map section, "id" is the only required field. This is the field we use to display the location names in the map list, and in various drop-downs.
|
||||
const QString idField = "id";
|
||||
QString idField = "id";
|
||||
if (!mapSectionObj.contains(idField)) {
|
||||
logWarn(QString("Ignoring data for map section %1 in '%2'. Missing required field \"%3\"").arg(i).arg(baseFilepath).arg(idField));
|
||||
continue;
|
||||
const QString oldIdField = "map_section";
|
||||
if (mapSectionObj.contains(oldIdField)) {
|
||||
// User has the old name for this field. Parse using this name, then save with the new name.
|
||||
// This will presumably stop the user's project from compiling, but that's preferable to
|
||||
// ignoring everything here and then wiping the file's data when we save later.
|
||||
idField = oldIdField;
|
||||
} else {
|
||||
logWarn(QString("Ignoring data for map section %1 in '%2'. Missing required field \"%3\"").arg(i).arg(baseFilepath).arg(idField));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const QString idName = ParseUtil::jsonToQString(mapSectionObj[idField]);
|
||||
if (!idName.startsWith(requiredPrefix)) {
|
||||
@@ -2338,7 +2361,6 @@ void Project::addNewMapsec(const QString &name) {
|
||||
}
|
||||
this->hasUnsavedDataChanges = true;
|
||||
|
||||
// TODO: Simplify into a single signal that updates the map list only if necessary
|
||||
emit mapSectionAdded(name);
|
||||
emit mapSectionIdNamesChanged(this->mapSectionIdNames);
|
||||
}
|
||||
|
||||
@@ -832,10 +832,6 @@ QString MainWindow::getLocation() {
|
||||
void MainWindow::setLocation(QString location) {
|
||||
if (!this->editor || !this->editor->map || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->mapSectionIdNames.contains(location)) {
|
||||
logError(QString("Unknown location '%1'").arg(location));
|
||||
return;
|
||||
}
|
||||
this->editor->map->header()->setLocation(location);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,11 @@ void MapHeaderForm::init(const Project * project) {
|
||||
ui->comboBox_BattleScene->clear();
|
||||
ui->comboBox_BattleScene->addItems(project->mapBattleScenes);
|
||||
|
||||
setLocations(project->mapSectionIdNames);
|
||||
QStringList locations = project->mapSectionIdNames;
|
||||
locations.sort();
|
||||
const QSignalBlocker b_Locations(ui->comboBox_Location);
|
||||
ui->comboBox_Location->clear();
|
||||
ui->comboBox_Location->addItems(locations);
|
||||
|
||||
// Hide config-specific settings
|
||||
|
||||
@@ -72,8 +76,7 @@ void MapHeaderForm::init(const Project * project) {
|
||||
ui->label_FloorNumber->setVisible(floorNumEnabled);
|
||||
}
|
||||
|
||||
// This combo box is treated specially because (unlike the other combo boxes)
|
||||
// items that should be in this drop-down can be added or removed externally.
|
||||
// Unlike other combo boxes in the map header form, locations can be added or removed externally.
|
||||
void MapHeaderForm::setLocations(QStringList locations) {
|
||||
locations.sort();
|
||||
|
||||
|
||||
@@ -454,10 +454,11 @@ QStandardItem *LayoutTreeModel::createMapFolderItem(const QString &folderName, Q
|
||||
// Despite using layout IDs internally, the Layouts map list shows layouts using their file path name.
|
||||
// We could handle this with Qt::DisplayRole in LayoutTreeModel::data, but then it would be sorted using the ID instead of the name.
|
||||
const Layout* layout = this->project->mapLayouts.value(folderName);
|
||||
if (layout) {
|
||||
folder->setText(layout->name);
|
||||
folder->setToolTip(layout->id);
|
||||
}
|
||||
if (layout) folder->setText(layout->name);
|
||||
|
||||
// The layout ID will instead be shown as a tool tip.
|
||||
folder->setToolTip(folderName);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
||||
@@ -651,10 +651,9 @@ void RegionMapEditor::displayRegionMapLayout() {
|
||||
void RegionMapEditor::displayRegionMapLayoutOptions() {
|
||||
if (!this->region_map->layoutEnabled()) return;
|
||||
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
|
||||
const QSignalBlocker b(ui->comboBox_RM_ConnectedMap);
|
||||
this->ui->comboBox_RM_ConnectedMap->clear();
|
||||
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionIdNames);
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
|
||||
|
||||
this->ui->frame_RM_Options->setEnabled(true);
|
||||
|
||||
@@ -662,22 +661,19 @@ void RegionMapEditor::displayRegionMapLayoutOptions() {
|
||||
}
|
||||
|
||||
void RegionMapEditor::updateRegionMapLayoutOptions(int index) {
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
|
||||
const QSignalBlocker b_ConnectedMap(ui->comboBox_RM_ConnectedMap);
|
||||
this->ui->comboBox_RM_ConnectedMap->setCurrentText(this->region_map->squareMapSection(index));
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
|
||||
|
||||
this->ui->pushButton_RM_Options_delete->setEnabled(this->region_map->squareHasMap(index));
|
||||
|
||||
this->ui->spinBox_RM_LayoutWidth->blockSignals(true);
|
||||
this->ui->spinBox_RM_LayoutHeight->blockSignals(true);
|
||||
const QSignalBlocker b_LayoutWidth(ui->spinBox_RM_LayoutWidth);
|
||||
const QSignalBlocker b_LayoutHeight(ui->spinBox_RM_LayoutHeight);
|
||||
this->ui->spinBox_RM_LayoutWidth->setMinimum(1);
|
||||
this->ui->spinBox_RM_LayoutWidth->setMaximum(this->region_map->tilemapWidth() - this->region_map->padLeft());
|
||||
this->ui->spinBox_RM_LayoutHeight->setMinimum(1);
|
||||
this->ui->spinBox_RM_LayoutHeight->setMaximum(this->region_map->tilemapHeight() - this->region_map->padTop());
|
||||
this->ui->spinBox_RM_LayoutWidth->setValue(this->region_map->layoutWidth());
|
||||
this->ui->spinBox_RM_LayoutHeight->setValue(this->region_map->layoutHeight());
|
||||
this->ui->spinBox_RM_LayoutWidth->blockSignals(false);
|
||||
this->ui->spinBox_RM_LayoutHeight->blockSignals(false);
|
||||
}
|
||||
|
||||
void RegionMapEditor::displayRegionMapEntriesImage() {
|
||||
@@ -1323,3 +1319,18 @@ void RegionMapEditor::on_verticalSlider_Zoom_Image_Tiles_valueChanged(int val) {
|
||||
ui->graphicsView_RegionMap_Tiles->setTransform(transform);
|
||||
ui->graphicsView_RegionMap_Tiles->setFixedSize(width + 2, height + 2);
|
||||
}
|
||||
|
||||
// Repopulate the combo boxes that display MAPSEC names.
|
||||
void RegionMapEditor::setLocations(const QStringList &locations) {
|
||||
const QSignalBlocker b_ConnectedMap(ui->comboBox_RM_ConnectedMap);
|
||||
auto before = ui->comboBox_RM_ConnectedMap->currentText();
|
||||
ui->comboBox_RM_ConnectedMap->clear();
|
||||
ui->comboBox_RM_ConnectedMap->addItems(locations);
|
||||
ui->comboBox_RM_ConnectedMap->setCurrentText(before);
|
||||
|
||||
const QSignalBlocker b_MapSection(ui->comboBox_RM_Entry_MapSection);
|
||||
before = ui->comboBox_RM_Entry_MapSection->currentText();
|
||||
ui->comboBox_RM_Entry_MapSection->clear();
|
||||
ui->comboBox_RM_Entry_MapSection->addItems(locations);
|
||||
ui->comboBox_RM_Entry_MapSection->setCurrentText(before);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user