diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 762c2cd4..cc52867b 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -16,7 +16,7 @@ - + Qt::Horizontal @@ -197,7 +197,7 @@ 6 - + Qt::Horizontal @@ -482,8 +482,8 @@ 0 0 - 469 - 608 + 545 + 587 @@ -797,8 +797,8 @@ 0 0 - 324 - 77 + 256 + 74 @@ -907,10 +907,10 @@ - 0 + 8 0 - 307 - 387 + 222 + 353 @@ -1224,7 +1224,7 @@ 0 - + 0 @@ -1249,8 +1249,8 @@ 0 0 - 381 - 657 + 371 + 643 @@ -1523,7 +1523,7 @@ 0 0 430 - 568 + 534 @@ -2308,8 +2308,8 @@ 0 0 - 826 - 557 + 818 + 539 @@ -2481,7 +2481,7 @@ 0 0 1117 - 21 + 22 @@ -2522,6 +2522,7 @@ + @@ -2562,6 +2563,14 @@ Ctrl+S + + + New Map + + + Ctrl+N + + Undo diff --git a/forms/newmappopup.ui b/forms/newmappopup.ui new file mode 100644 index 00000000..118dcf5a --- /dev/null +++ b/forms/newmappopup.ui @@ -0,0 +1,267 @@ + + + NewMapPopup + + + + 0 + 0 + 410 + 508 + + + + New Map Options + + + + + + + false + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + QLayout::SetFixedSize + + + 12 + + + + + Name + + + + + + + <html><head/><body><p>The name of the new map. If the name is invalid (red), it will be replaced with the default name of a new map.</p></body></html> + + + + + + + Group + + + + + + + <html><head/><body><p>New map group.</p></body></html> + + + true + + + + + + + Width + + + + + + + <html><head/><body><p>Width (in blocks) of the new map.</p></body></html> + + + 200 + + + + + + + Height + + + + + + + <html><head/><body><p>Height (in blocks) of the new map.</p></body></html> + + + 200 + + + + + + + Primary Tileset + + + + + + + <html><head/><body><p>The primary tileset for the new map.</p></body></html> + + + true + + + + + + + Secondary Tileset + + + + + + + <html><head/><body><p>The secondary tileset for the new map.</p></body></html> + + + true + + + + + + + Type + + + + + + + <html><head/><body><p>The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.</p></body></html> + + + true + + + + + + + Location + + + + + + + <html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.</p></body></html> + + + true + + + + + + + Can Fly To + + + + + + + <html><head/><body><p>Whether to add a heal location to the new map.</p></body></html> + + + + + + + + + + Allow Running + + + + + + + Allow Biking + + + + + + + Allow Escape Rope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Accept + + + + + + + + + 0 + 0 + 410 + 22 + + + + + + + + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+
+ + +
diff --git a/include/config.h b/include/config.h index 31c91d9f..efc76e5a 100644 --- a/include/config.h +++ b/include/config.h @@ -3,6 +3,7 @@ #include #include +#include enum MapSortOrder { Group = 0, @@ -37,11 +38,13 @@ public: void setRecentMap(QString map); void setMapSortOrder(MapSortOrder order); void setPrettyCursors(bool enabled); + void setGeometry(QByteArray, QByteArray, QByteArray, QByteArray, QByteArray); void setCollisionOpacity(int opacity); QString getRecentProject(); QString getRecentMap(); MapSortOrder getMapSortOrder(); bool getPrettyCursors(); + QMap getGeometry(); int getCollisionOpacity(); protected: QString getConfigFilepath(); @@ -51,8 +54,15 @@ protected: private: QString recentProject; QString recentMap; + QString stringFromByteArray(QByteArray); + QByteArray bytesFromString(QString); MapSortOrder mapSortOrder; bool prettyCursors; + QByteArray windowGeometry; + QByteArray windowState; + QByteArray mapSplitterState; + QByteArray eventsSlpitterState; + QByteArray mainSplitterState; int collisionOpacity; }; diff --git a/include/core/map.h b/include/core/map.h index 94dda0cf..07c4631e 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -32,7 +32,7 @@ public: QString layout_id; QString location; QString requiresFlash; - QString isFlyable; // TODO: implement this + QString isFlyable; QString weather; QString type; QString unknown; @@ -43,6 +43,7 @@ public: QString battle_scene; MapLayout *layout; bool isPersistedToFile = true; + bool needsLayoutDir = true; QImage collision_image; QPixmap collision_pixmap; QImage image; diff --git a/include/mainwindow.h b/include/mainwindow.h index a71e57e1..e7e753a3 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -16,6 +16,7 @@ #include "editor.h" #include "tileseteditor.h" #include "filterchildrenproxymodel.h" +#include "newmappopup.h" namespace Ui { class MainWindow; @@ -47,7 +48,10 @@ private slots: void onMapChanged(Map *map); void onMapNeedsRedrawing(); void onTilesetsSaved(QString, QString); + void openNewMapPopupWindow(int, QVariant); + void onNewMapCreated(); + void on_action_NewMap_triggered(); void on_action_Save_triggered(); void on_tabWidget_2_currentChanged(int index); void on_action_Exit_triggered(); @@ -98,6 +102,8 @@ private slots: void onOpenMapListContextMenu(const QPoint &point); void onAddNewMapToGroupClick(QAction* triggeredAction); + void onAddNewMapToAreaClick(QAction* triggeredAction); + void onAddNewMapToLayoutClick(QAction* triggeredAction); void onTilesetChanged(QString); void currentMetatilesSelectionChanged(); @@ -149,6 +155,7 @@ private: Ui::MainWindow *ui; TilesetEditor *tilesetEditor = nullptr; FilterChildrenProxyModel *mapListProxyModel; + NewMapPopup *newmapprompt = nullptr; QStandardItemModel *mapListModel; QList *mapGroupItemsList; QMap mapListIndexes; @@ -200,6 +207,7 @@ private: void initMapSortOrder(); void setProjectSpecificUIVisibility(); void loadUserSettings(); + void restoreWindowState(); bool openRecentProject(); void updateTilesetEditor(); QString getEventGroupFromTabWidget(QWidget *tab); diff --git a/include/project.h b/include/project.h index af4f8476..440e6bbd 100644 --- a/include/project.h +++ b/include/project.h @@ -61,6 +61,7 @@ public: void readMapGroups(); Map* addNewMapToGroup(QString mapName, int groupNum); + Map* addNewMapToGroup(QString, int, Map*, bool); QString getNewMapName(); QString getProjectTitle(); diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h new file mode 100644 index 00000000..22fa7609 --- /dev/null +++ b/include/ui/newmappopup.h @@ -0,0 +1,40 @@ +#ifndef NEWMAPPOPUP_H +#define NEWMAPPOPUP_H + +#include +#include +#include "editor.h" +#include "project.h" +#include "map.h" + +namespace Ui { +class NewMapPopup; +} + +class NewMapPopup : public QMainWindow +{ + Q_OBJECT +public: + explicit NewMapPopup(QWidget *parent = nullptr, Project *project = nullptr); + ~NewMapPopup(); + Map *map; + int group; + bool changeLayout; + QString layoutName; + void init(int, int, QString, QString); + void useLayout(QString); + +signals: + void applied(); + +private: + Ui::NewMapPopup *ui; + Project *project; + void setDefaultValues(int, QString); + +private slots: + void on_pushButton_NewMap_Accept_clicked(); + void on_lineEdit_NewMap_Name_textChanged(const QString &); +}; + +#endif // NEWMAPPOPUP_H diff --git a/porymap.pro b/porymap.pro index 9a9f9c40..c8d42948 100644 --- a/porymap.pro +++ b/porymap.pro @@ -47,6 +47,7 @@ SOURCES += src/core/block.cpp \ src/ui/tileseteditor.cpp \ src/ui/tileseteditormetatileselector.cpp \ src/ui/tileseteditortileselector.cpp \ + src/ui/newmappopup.cpp \ src/config.cpp \ src/editor.cpp \ src/main.cpp \ @@ -90,6 +91,7 @@ HEADERS += include/core/block.h \ include/ui/tileseteditor.h \ include/ui/tileseteditormetatileselector.h \ include/ui/tileseteditortileselector.h \ + include/ui/newmappopup.h \ include/config.h \ include/editor.h \ include/mainwindow.h \ @@ -100,7 +102,8 @@ HEADERS += include/core/block.h \ FORMS += forms/mainwindow.ui \ forms/eventpropertiesframe.ui \ forms/tileseteditor.ui \ - forms/paletteeditor.ui + forms/paletteeditor.ui \ + forms/newmappopup.ui RESOURCES += \ resources/images.qrc diff --git a/src/config.cpp b/src/config.cpp index 1a7a529f..78dfcb48 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -119,6 +119,16 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->mapSortOrder = MapSortOrder::Group; logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value)); } + } else if (key == "window_geometry") { + this->windowGeometry = bytesFromString(value); + } else if (key == "window_state") { + this->windowState = bytesFromString(value); + } else if (key == "map_splitter_state") { + this->mapSplitterState = bytesFromString(value); + } else if (key == "events_splitter_state") { + this->eventsSlpitterState = bytesFromString(value); + } else if (key == "main_splitter_state") { + this->mainSplitterState = bytesFromString(value); } else if (key == "collision_opacity") { bool ok; this->collisionOpacity = qMax(0, qMin(100, value.toInt(&ok))); @@ -137,10 +147,32 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("recent_map", this->recentMap); map.insert("pretty_cursors", this->prettyCursors ? "1" : "0"); map.insert("map_sort_order", mapSortOrderMap.value(this->mapSortOrder)); + map.insert("window_geometry", stringFromByteArray(this->windowGeometry)); + map.insert("window_state", stringFromByteArray(this->windowState)); + map.insert("map_splitter_state", stringFromByteArray(this->mapSplitterState)); + map.insert("events_splitter_state", stringFromByteArray(this->eventsSlpitterState)); + map.insert("main_splitter_state", stringFromByteArray(this->mainSplitterState)); map.insert("collision_opacity", QString("%1").arg(this->collisionOpacity)); return map; } +QString PorymapConfig::stringFromByteArray(QByteArray bytearray) { + QString ret; + for (auto ch : bytearray) { + ret += QString::number(static_cast(ch)) + ":"; + } + return ret; +} + +QByteArray PorymapConfig::bytesFromString(QString in) { + QByteArray ba; + QStringList split = in.split(":"); + for (auto ch : split) { + ba.append(static_cast(ch.toInt())); + } + return ba; +} + void PorymapConfig::setRecentProject(QString project) { this->recentProject = project; this->save(); @@ -161,6 +193,16 @@ void PorymapConfig::setPrettyCursors(bool enabled) { this->save(); } +void PorymapConfig::setGeometry(QByteArray windowGeometry_, QByteArray windowState_, QByteArray mapSplitterState_, + QByteArray eventsSlpitterState_, QByteArray mainSplitterState_) { + this->windowGeometry = windowGeometry_; + this->windowState = windowState_; + this->mapSplitterState = mapSplitterState_; + this->eventsSlpitterState = eventsSlpitterState_; + this->mainSplitterState = mainSplitterState_; + this->save(); +} + void PorymapConfig::setCollisionOpacity(int opacity) { this->collisionOpacity = opacity; // don't auto-save here because this can be called very frequently. @@ -182,6 +224,18 @@ bool PorymapConfig::getPrettyCursors() { return this->prettyCursors; } +QMap PorymapConfig::getGeometry() { + QMap geometry; + + geometry.insert("window_geometry", this->windowGeometry); + geometry.insert("window_state", this->windowState); + geometry.insert("map_splitter_state", this->mapSplitterState); + geometry.insert("events_splitter_state", this->eventsSlpitterState); + geometry.insert("main_splitter_state", this->mainSplitterState); + + return geometry; +} + int PorymapConfig::getCollisionOpacity() { return this->collisionOpacity; } diff --git a/src/editor.cpp b/src/editor.cpp index c3de616a..1f8dbc82 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1129,6 +1129,9 @@ DraggablePixmapItem* Editor::addNewEvent(QString event_type) { if (project && map) { Event *event = Event::createNewEvent(event_type, map->name); event->put("map_name", map->name); + if (event_type == "event_heal_location") { + event->put("index", project->flyableMaps.length()); + } map->addEvent(event); project->loadEventPixmaps(map->getAllEvents()); DraggablePixmapItem *object = addMapEvent(event); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 150ef37e..fb775f42 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -63,6 +63,7 @@ void MainWindow::initWindow() { this->initEditor(); this->initMiscHeapObjects(); this->initMapSortOrder(); + this->restoreWindowState(); } void MainWindow::initExtraShortcuts() { @@ -210,6 +211,16 @@ void MainWindow::loadUserSettings() { ui->horizontalSlider_CollisionTransparency->blockSignals(false); } +void MainWindow::restoreWindowState() { + logInfo("Restoring window geometry from previous session."); + QMap geometry = porymapConfig.getGeometry(); + this->restoreGeometry(geometry.value("window_geometry")); + this->restoreState(geometry.value("window_state")); + this->ui->splitter_map->restoreState(geometry.value("map_splitter_state")); + this->ui->splitter_events->restoreState(geometry.value("events_splitter_state")); + this->ui->splitter_main->restoreState(geometry.value("main_splitter_state")); +} + bool MainWindow::openRecentProject() { QString default_dir = porymapConfig.getRecentProject(); if (!default_dir.isNull() && default_dir.length() > 0) { @@ -722,25 +733,102 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum); connect(actions, SIGNAL(triggered(QAction*)), this, SLOT(onAddNewMapToGroupClick(QAction*))); menu->exec(QCursor::pos()); + } else if (itemType == "map_sec") { + QString secName = selectedItem->data(Qt::UserRole).toString(); + QMenu* menu = new QMenu(this); + QActionGroup* actions = new QActionGroup(menu); + actions->addAction(menu->addAction("Add New Map to Area"))->setData(secName); + connect(actions, SIGNAL(triggered(QAction*)), this, SLOT(onAddNewMapToAreaClick(QAction*))); + menu->exec(QCursor::pos()); + } else if (itemType == "map_layout") { + QString layoutName = selectedItem->data(Qt::UserRole).toString(); + QMenu* menu = new QMenu(this); + QActionGroup* actions = new QActionGroup(menu); + actions->addAction(menu->addAction("Add New Map with Layout"))->setData(layoutName); + connect(actions, SIGNAL(triggered(QAction*)), this, SLOT(onAddNewMapToLayoutClick(QAction*))); + menu->exec(QCursor::pos()); } } void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { int groupNum = triggeredAction->data().toInt(); - QStandardItem* groupItem = mapGroupItemsList->at(groupNum); + openNewMapPopupWindow(MapSortOrder::Group, groupNum); +} + +void MainWindow::onAddNewMapToAreaClick(QAction* triggeredAction) +{ + QString secName = triggeredAction->data().toString(); + openNewMapPopupWindow(MapSortOrder::Area, secName); +} + +void MainWindow::onAddNewMapToLayoutClick(QAction* triggeredAction) +{ + QString layoutName = triggeredAction->data().toString(); + openNewMapPopupWindow(MapSortOrder::Layout, layoutName); +} + +void MainWindow::onNewMapCreated() { + QString newMapName = this->newmapprompt->map->name; + int newMapGroup = this->newmapprompt->group; + Map *newMap_ = this->newmapprompt->map; + bool updateLayout = this->newmapprompt->changeLayout; + + Map *newMap = editor->project->addNewMapToGroup(newMapName, newMapGroup, newMap_, updateLayout); + + logInfo(QString("Created a new map named %1.").arg(newMapName)); - QString newMapName = editor->project->getNewMapName(); - Map* newMap = editor->project->addNewMapToGroup(newMapName, groupNum); editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); + QStandardItem* groupItem = mapGroupItemsList->at(newMapGroup); int numMapsInGroup = groupItem->rowCount(); - QStandardItem *newMapItem = createMapItem(newMapName, groupNum, numMapsInGroup); + + QStandardItem *newMapItem = createMapItem(newMapName, newMapGroup, numMapsInGroup); groupItem->appendRow(newMapItem); mapListIndexes.insert(newMapName, newMapItem->index()); - setMap(newMapName); + sortMapList(); + setMap(newMapName, true); + + if (newMap->isFlyable == "TRUE") { + addNewEvent("event_heal_location"); + editor->project->saveHealLocationStruct(newMap); + editor->save();// required + } + + disconnect(this->newmapprompt, SIGNAL(applied()), this, SLOT(onNewMapCreated())); +} + +void MainWindow::openNewMapPopupWindow(int type, QVariant data) { + if (!this->newmapprompt) { + this->newmapprompt = new NewMapPopup(this, this->editor->project); + } + if (!this->newmapprompt->isVisible()) { + this->newmapprompt->show(); + } else { + this->newmapprompt->raise(); + this->newmapprompt->activateWindow(); + } + switch (type) + { + case MapSortOrder::Group: + this->newmapprompt->init(type, data.toInt(), QString(), QString()); + break; + case MapSortOrder::Area: + this->newmapprompt->init(type, 0, data.toString(), QString()); + break; + case MapSortOrder::Layout: + this->newmapprompt->init(type, 0, QString(), data.toString()); + break; + } + connect(this->newmapprompt, SIGNAL(applied()), this, SLOT(onNewMapCreated())); + connect(this->newmapprompt, &QObject::destroyed, [=](QObject *) { this->newmapprompt = nullptr; }); + this->newmapprompt->setAttribute(Qt::WA_DeleteOnClose); +} + +void MainWindow::on_action_NewMap_triggered() { + openNewMapPopupWindow(MapSortOrder::Group, 0); } void MainWindow::onTilesetChanged(QString mapName) @@ -1758,6 +1846,13 @@ void MainWindow::on_actionTileset_Editor_triggered() } void MainWindow::closeEvent(QCloseEvent *event) { + porymapConfig.setGeometry( + this->saveGeometry(), + this->saveState(), + this->ui->splitter_map->saveState(), + this->ui->splitter_events->saveState(), + this->ui->splitter_main->saveState() + ); porymapConfig.save(); QMainWindow::closeEvent(event); diff --git a/src/project.cpp b/src/project.cpp index 34be984e..1bfe30d4 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -850,9 +850,14 @@ void Project::saveMap(Map *map) { logError(QString("Error: failed to create directory for new map: '%1'").arg(newMapDataDir)); } - QString newLayoutDir = QString(root + "/data/layouts/%1").arg(map->name); - if (!QDir::root().mkdir(newLayoutDir)) { - logError(QString("Error: failed to create directory for new layout: '%1'").arg(newLayoutDir)); + if (map->needsLayoutDir) { + QString newLayoutDir = QString(root + "/data/layouts/%1").arg(map->name); + if (!QDir::root().mkdir(newLayoutDir)) { + logError(QString("Error: failed to create directory for new layout: '%1'").arg(newLayoutDir)); + } + // Simply append to data/layouts.inc. + QString layout_text = QString("\t.include \"data/layouts/%1/layout.inc\"\n").arg(map->layout->name); + appendTextFile(root + "/data/layouts.inc", layout_text); } // TODO: In the future, these files needs more structure to allow for proper parsing/saving. @@ -875,10 +880,6 @@ void Project::saveMap(Map *map) { // Simply append to data/maps/headers.inc. text = QString("\t.include \"data/maps/%1/header.inc\"\n").arg(map->name); appendTextFile(root + "/data/maps/headers.inc", text); - - // Simply append to data/layouts.inc. - text = QString("\t.include \"data/layouts/%1/layout.inc\"\n").arg(map->layout->name); - appendTextFile(root + "/data/layouts.inc", text); } saveMapBorder(map); @@ -1247,6 +1248,50 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum) { return map; } +Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool updateLayout) { + mapNames->append(mapName); + map_groups->insert(mapName, groupNum); + groupedMapNames[groupNum].append(mapName); + + Map *map = new Map; + map = newMap; + + map->isPersistedToFile = false; + map->setName(mapName); + + mapConstantsToMapNames->insert(map->constantName, map->name); + mapNamesToMapConstants->insert(map->name, map->constantName); + + map->events_label = QString("%1_MapEvents").arg(map->name);; + map->scripts_label = QString("%1_MapScripts").arg(map->name);; + map->connections_label = "0x0"; + map->song = "MUS_DAN02"; + map->requiresFlash = "FALSE"; + map->weather = "WEATHER_SUNNY"; + map->unknown = "0"; + map->show_location = "TRUE"; + map->battle_scene = "MAP_BATTLE_SCENE_NORMAL"; + + if (!updateLayout) { + map->layout_id = QString("%1").arg(mapLayoutsTable.size() + 1); + mapLayouts.insert(map->layout->label, map->layout); + mapLayoutsTable.append(map->layout->label); + setNewMapBlockdata(map); + setNewMapBorder(map); + } else { + map->layout_id = QString("%1").arg(mapLayoutsTable.indexOf(map->layout->label) + 1); + } + + loadMapTilesets(map); + setNewMapEvents(map); + setNewMapConnections(map); + + map->commit(); + map->metatileHistory.save(); + + return map; +} + QString Project::getNewMapName() { // Ensure default name doesn't already exist. int i = 0; diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index d6e50d20..c0a25bb9 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -1,5 +1,6 @@ #include "connectionpixmapitem.h" -#include + +#include void ConnectionPixmapItem::render(qreal opacity) { QPixmap newPixmap = this->basePixmap.copy(0, 0, this->basePixmap.width(), this->basePixmap.height()); diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp new file mode 100644 index 00000000..cdbef212 --- /dev/null +++ b/src/ui/newmappopup.cpp @@ -0,0 +1,168 @@ +#include "newmappopup.h" +#include "event.h" +#include "maplayout.h" +#include "mainwindow.h" +#include "ui_newmappopup.h" +#include "config.h" + +#include +#include +#include +#include + +NewMapPopup::NewMapPopup(QWidget *parent, Project *project) : + QMainWindow(parent), + ui(new Ui::NewMapPopup) +{ + ui->setupUi(this); + this->project = project; + this->changeLayout = false; +} + +NewMapPopup::~NewMapPopup() +{ + delete ui; +} + +void NewMapPopup::init(int type, int group, QString sec, QString layout) { + switch (type) + { + case MapSortOrder::Group: + setDefaultValues(group, QString()); + break; + case MapSortOrder::Area: + setDefaultValues(group, sec); + break; + case MapSortOrder::Layout: + useLayout(layout); + setDefaultValues(group, QString()); + break; + } +} + +void NewMapPopup::useLayout(QString mapName) { + this->changeLayout = true; + this->layoutName = mapName; +} + +void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) { + ui->lineEdit_NewMap_Name->setText(project->getNewMapName()); + + QMap tilesets = project->getTilesets(); + ui->comboBox_NewMap_Primary_Tileset->addItems(tilesets.value("primary")); + ui->comboBox_NewMap_Secondary_Tileset->addItems(tilesets.value("secondary")); + + ui->comboBox_NewMap_Group->addItems(*project->groupNames); + ui->comboBox_NewMap_Group->setCurrentText("gMapGroup" + QString::number(groupNum)); + + if (changeLayout) { + ui->spinBox_NewMap_Width->setValue(project->mapLayouts.value(layoutName)->width.toInt(nullptr, 0)); + ui->spinBox_NewMap_Height->setValue(project->mapLayouts.value(layoutName)->height.toInt(nullptr, 0)); + ui->comboBox_NewMap_Primary_Tileset->setCurrentText(project->mapLayouts.value(layoutName)->tileset_primary_label); + ui->comboBox_NewMap_Secondary_Tileset->setCurrentText(project->mapLayouts.value(layoutName)->tileset_secondary_label); + ui->spinBox_NewMap_Width->setDisabled(true); + ui->spinBox_NewMap_Height->setDisabled(true); + ui->comboBox_NewMap_Primary_Tileset->setDisabled(true); + ui->comboBox_NewMap_Secondary_Tileset->setDisabled(true); + } else { + ui->spinBox_NewMap_Width->setValue(20); + ui->spinBox_NewMap_Height->setValue(20); + } + + ui->comboBox_NewMap_Type->addItems(*project->mapTypes); + ui->comboBox_NewMap_Location->addItems(*project->regionMapSections); + if (!mapSec.isEmpty()) ui->comboBox_NewMap_Location->setCurrentText(mapSec); + + ui->frame_NewMap_Options->setEnabled(true); + + switch (projectConfig.getBaseGameVersion()) + { + case BaseGameVersion::pokeruby: + ui->checkBox_NewMap_Allow_Running->setVisible(false); + ui->checkBox_NewMap_Allow_Biking->setVisible(false); + ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(false); + ui->label_NewMap_Allow_Running->setVisible(false); + ui->label_NewMap_Allow_Biking->setVisible(false); + ui->label_NewMap_Allow_Escape_Rope->setVisible(false); + break; + case BaseGameVersion::pokeemerald: + ui->checkBox_NewMap_Allow_Running->setVisible(true); + ui->checkBox_NewMap_Allow_Biking->setVisible(true); + ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(true); + ui->label_NewMap_Allow_Running->setVisible(true); + ui->label_NewMap_Allow_Biking->setVisible(true); + ui->label_NewMap_Allow_Escape_Rope->setVisible(true); + break; + } +} + +void NewMapPopup::on_lineEdit_NewMap_Name_textChanged(const QString &text) { + if (project->mapNames->contains(text)) { + QPalette palette = this->ui->lineEdit_NewMap_Name->palette(); + QColor color = Qt::red; + color.setAlpha(25); + palette.setColor(QPalette::Base, color); + this->ui->lineEdit_NewMap_Name->setPalette(palette); + } else { + this->ui->lineEdit_NewMap_Name->setPalette(QPalette()); + } +} + +void NewMapPopup::on_pushButton_NewMap_Accept_clicked() { + Map *newMap = new Map; + MapLayout *layout = new MapLayout; + + // If map name is not unique, use default value. Also use only valid characters. + QString newMapName = this->ui->lineEdit_NewMap_Name->text().remove(QRegularExpression("[^a-zA-Z0-9_]+")); + if (project->mapNames->contains(newMapName) || newMapName.isEmpty()) { + newMapName = project->getNewMapName(); + } + newMap->name = newMapName; + + newMap->type = this->ui->comboBox_NewMap_Type->currentText(); + newMap->location = this->ui->comboBox_NewMap_Location->currentText(); + + layout->width = QString::number(this->ui->spinBox_NewMap_Width->value()); + layout->height = QString::number(this->ui->spinBox_NewMap_Height->value()); + layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText(); + layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText(); + layout->border_label = QString("%1_MapBorder").arg(newMap->name); + layout->blockdata_label = QString("%1_MapBlockdata").arg(newMap->name); + + if (changeLayout) { + layout->label = layoutName; + layout->name = MapLayout::getNameFromLabel(layout->label); + QString block_path = QString("%1/data/layout/%2/map.bin").arg(project->root).arg(MapLayout::getNameFromLabel(layoutName)); + QString border_path = QString("%1/data/layout/%2/border.bin").arg(project->root).arg(MapLayout::getNameFromLabel(layoutName)); + layout->blockdata = project->readBlockdata(block_path); + layout->border = project->readBlockdata(border_path); + newMap->needsLayoutDir = false; + } else { + layout->border_path = QString("data/layouts/%1/border.bin").arg(newMap->name); + layout->blockdata_path = QString("data/layouts/%1/map.bin").arg(newMap->name); + layout->label = QString("%1_Layout").arg(newMap->name); + layout->name = MapLayout::getNameFromLabel(layout->label); + } + + if (this->ui->checkBox_NewMap_Flyable->isChecked()) { + newMap->isFlyable = "TRUE"; + } + + if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeemerald) { + newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked() ? "1" : "0"; + newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked() ? "1" : "0"; + newMap->allowEscapeRope = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked() ? "1" : "0"; + } + + group = this->ui->comboBox_NewMap_Group->currentText().remove("gMapGroup").toInt(); + + newMap->layout = layout; + newMap->layout_label = layout->label; + newMap->group_num = QString::number(group); + + map = newMap; + + emit applied(); + + this->close(); +}