Browse Source

Merge pull request #20 from huderlem/maps

Support adding new maps
yenatch 6 years ago
parent
commit
ce49e788ec
No account linked to committer's email address
9 changed files with 655 additions and 48 deletions
  1. 1
    1
      asm.cpp
  2. 2
    0
      editor.cpp
  3. 1
    0
      main.cpp
  4. 87
    23
      mainwindow.cpp
  5. 14
    0
      mainwindow.h
  6. 1
    1
      map.cpp
  7. 3
    0
      map.h
  8. 513
    19
      project.cpp
  9. 33
    4
      project.h

+ 1
- 1
asm.cpp View File

26
         //QString macro;
26
         //QString macro;
27
         //QStringList *params;
27
         //QStringList *params;
28
         strip_comment(&line);
28
         strip_comment(&line);
29
-        if (line.isEmpty()) {
29
+        if (line.trimmed().isEmpty()) {
30
         } else if (line.contains(':')) {
30
         } else if (line.contains(':')) {
31
             label = line.left(line.indexOf(':'));
31
             label = line.left(line.indexOf(':'));
32
             QStringList *list = new QStringList;
32
             QStringList *list = new QStringList;

+ 2
- 0
editor.cpp View File

10
 void Editor::saveProject() {
10
 void Editor::saveProject() {
11
     if (project) {
11
     if (project) {
12
         project->saveAllMaps();
12
         project->saveAllMaps();
13
+        project->saveAllDataStructures();
13
     }
14
     }
14
 }
15
 }
15
 
16
 
16
 void Editor::save() {
17
 void Editor::save() {
17
     if (project && map) {
18
     if (project && map) {
18
         project->saveMap(map);
19
         project->saveMap(map);
20
+        project->saveAllDataStructures();
19
     }
21
     }
20
 }
22
 }
21
 
23
 

+ 1
- 0
main.cpp View File

4
 int main(int argc, char *argv[])
4
 int main(int argc, char *argv[])
5
 {
5
 {
6
     QApplication a(argc, argv);
6
     QApplication a(argc, argv);
7
+    a.setStyle("fusion");
7
     MainWindow w;
8
     MainWindow w;
8
     w.show();
9
     w.show();
9
 
10
 

+ 87
- 23
mainwindow.cpp View File

61
         editor->project = new Project;
61
         editor->project = new Project;
62
         editor->project->root = dir;
62
         editor->project->root = dir;
63
         setWindowTitle(editor->project->getProjectTitle() + " - pretmap");
63
         setWindowTitle(editor->project->getProjectTitle() + " - pretmap");
64
+        loadDataStructures();
64
         populateMapList();
65
         populateMapList();
65
         setMap(getDefaultMap());
66
         setMap(getDefaultMap());
66
     } else {
67
     } else {
67
         setWindowTitle(editor->project->getProjectTitle() + " - pretmap");
68
         setWindowTitle(editor->project->getProjectTitle() + " - pretmap");
69
+        loadDataStructures();
68
         populateMapList();
70
         populateMapList();
69
     }
71
     }
70
 }
72
 }
71
 
73
 
72
 QString MainWindow::getDefaultMap() {
74
 QString MainWindow::getDefaultMap() {
73
     if (editor && editor->project) {
75
     if (editor && editor->project) {
74
-        QList<QStringList*> *names = editor->project->groupedMapNames;
75
-        if (names) {
76
+        QList<QStringList> names = editor->project->groupedMapNames;
77
+        if (!names.isEmpty()) {
76
             QSettings settings;
78
             QSettings settings;
77
             QString key = "project:" + editor->project->root;
79
             QString key = "project:" + editor->project->root;
78
             if (settings.contains(key)) {
80
             if (settings.contains(key)) {
79
                 QMap<QString, QVariant> qmap = settings.value(key).toMap();
81
                 QMap<QString, QVariant> qmap = settings.value(key).toMap();
80
                 if (qmap.contains("recent_map")) {
82
                 if (qmap.contains("recent_map")) {
81
                     QString map_name = qmap.value("recent_map").toString();
83
                     QString map_name = qmap.value("recent_map").toString();
82
-                    for (int i = 0; i < names->length(); i++) {
83
-                        if (names->value(i)->contains(map_name)) {
84
+                    for (int i = 0; i < names.length(); i++) {
85
+                        if (names.value(i).contains(map_name)) {
84
                             return map_name;
86
                             return map_name;
85
                         }
87
                         }
86
                     }
88
                     }
87
                 }
89
                 }
88
             }
90
             }
89
             // Failing that, just get the first map in the list.
91
             // Failing that, just get the first map in the list.
90
-            for (int i = 0; i < names->length(); i++) {
91
-                QStringList *list = names->value(i);
92
-                if (list->length()) {
93
-                    return list->value(0);
92
+            for (int i = 0; i < names.length(); i++) {
93
+                QStringList list = names.value(i);
94
+                if (list.length()) {
95
+                    return list.value(0);
94
                 }
96
                 }
95
             }
97
             }
96
         }
98
         }
278
     }
280
     }
279
 }
281
 }
280
 
282
 
283
+void MainWindow::loadDataStructures() {
284
+    Project *project = editor->project;
285
+    project->readMapAttributesTable();
286
+    project->readAllMapAttributes();
287
+}
281
 
288
 
282
 void MainWindow::populateMapList() {
289
 void MainWindow::populateMapList() {
283
     Project *project = editor->project;
290
     Project *project = editor->project;
289
     QIcon folderIcon;
296
     QIcon folderIcon;
290
     folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
297
     folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
291
 
298
 
292
-    QIcon mapIcon;
293
-    mapIcon.addFile(QStringLiteral(":/icons/map.ico"), QSize(), QIcon::Normal, QIcon::Off);
294
-    mapIcon.addFile(QStringLiteral(":/icons/image.ico"), QSize(), QIcon::Normal, QIcon::On);
299
+    mapIcon = new QIcon;
300
+    mapIcon->addFile(QStringLiteral(":/icons/map.ico"), QSize(), QIcon::Normal, QIcon::Off);
301
+    mapIcon->addFile(QStringLiteral(":/icons/image.ico"), QSize(), QIcon::Normal, QIcon::On);
295
 
302
 
296
-    QStandardItemModel *model = new QStandardItemModel;
303
+    mapListModel = new QStandardItemModel;
304
+    mapGroupsModel = new QList<QStandardItem*>;
297
 
305
 
298
     QStandardItem *entry = new QStandardItem;
306
     QStandardItem *entry = new QStandardItem;
299
     entry->setText(project->getProjectTitle());
307
     entry->setText(project->getProjectTitle());
300
     entry->setIcon(folderIcon);
308
     entry->setIcon(folderIcon);
301
     entry->setEditable(false);
309
     entry->setEditable(false);
302
-    model->appendRow(entry);
310
+    mapListModel->appendRow(entry);
303
 
311
 
304
     QStandardItem *maps = new QStandardItem;
312
     QStandardItem *maps = new QStandardItem;
305
     maps->setText("maps");
313
     maps->setText("maps");
314
         group->setText(group_name);
322
         group->setText(group_name);
315
         group->setIcon(mapFolderIcon);
323
         group->setIcon(mapFolderIcon);
316
         group->setEditable(false);
324
         group->setEditable(false);
325
+        group->setData(group_name, Qt::UserRole);
326
+        group->setData("map_group", MapListUserRoles::TypeRole);
327
+        group->setData(i, MapListUserRoles::GroupRole);
317
         maps->appendRow(group);
328
         maps->appendRow(group);
318
-        QStringList *names = project->groupedMapNames->value(i);
319
-        for (int j = 0; j < names->length(); j++) {
320
-            QString map_name = names->value(j);
321
-            QStandardItem *map = new QStandardItem;
322
-            map->setText(QString("[%1.%2] ").arg(i).arg(j, 2, 10, QLatin1Char('0')) + map_name);
323
-            map->setIcon(mapIcon);
324
-            map->setEditable(false);
325
-            map->setData(map_name, Qt::UserRole);
329
+        mapGroupsModel->append(group);
330
+        QStringList names = project->groupedMapNames.value(i);
331
+        for (int j = 0; j < names.length(); j++) {
332
+            QString map_name = names.value(j);
333
+            QStandardItem *map = createMapItem(map_name, i, j);
326
             group->appendRow(map);
334
             group->appendRow(map);
327
-            //ui->mapList->setExpanded(model->indexFromItem(map), false); // redundant
328
         }
335
         }
329
     }
336
     }
330
 
337
 
331
-    ui->mapList->setModel(model);
338
+    // Right-clicking on items in the map list tree view brings up a context menu.
339
+    ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu);
340
+    connect(ui->mapList, SIGNAL(customContextMenuRequested(const QPoint &)),
341
+            this, SLOT(onOpenMapListContextMenu(const QPoint &)));
342
+
343
+    ui->mapList->setModel(mapListModel);
332
     ui->mapList->setUpdatesEnabled(true);
344
     ui->mapList->setUpdatesEnabled(true);
333
     ui->mapList->expandToDepth(2);
345
     ui->mapList->expandToDepth(2);
334
     ui->mapList->repaint();
346
     ui->mapList->repaint();
335
 }
347
 }
336
 
348
 
349
+QStandardItem* MainWindow::createMapItem(QString mapName, int groupNum, int inGroupNum) {
350
+    QStandardItem *map = new QStandardItem;
351
+    map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName);
352
+    map->setIcon(*mapIcon);
353
+    map->setEditable(false);
354
+    map->setData(mapName, Qt::UserRole);
355
+    map->setData("map_name", MapListUserRoles::TypeRole);
356
+    return map;
357
+}
358
+
359
+void MainWindow::onOpenMapListContextMenu(const QPoint &point)
360
+{
361
+    QModelIndex index = ui->mapList->indexAt(point);
362
+    if (!index.isValid()) {
363
+        return;
364
+    }
365
+
366
+    QStandardItem *selectedItem = mapListModel->itemFromIndex(index);
367
+    QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole);
368
+    if (!itemType.isValid()) {
369
+        return;
370
+    }
371
+
372
+    // Build custom context menu depending on which type of item was selected (map group, map name, etc.)
373
+    if (itemType == "map_group") {
374
+        QString groupName = selectedItem->data(Qt::UserRole).toString();
375
+        int groupNum = selectedItem->data(MapListUserRoles::GroupRole).toInt();
376
+        QMenu* menu = new QMenu();
377
+        QActionGroup* actions = new QActionGroup(menu);
378
+        actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum);
379
+        connect(actions, SIGNAL(triggered(QAction*)), this, SLOT(onAddNewMapToGroupClick(QAction*)));
380
+        menu->exec(QCursor::pos());
381
+    }
382
+}
383
+
384
+void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction)
385
+{
386
+    int groupNum = triggeredAction->data().toInt();
387
+    QStandardItem* groupItem = mapGroupsModel->at(groupNum);
388
+
389
+    QString newMapName = editor->project->getNewMapName();
390
+    Map* newMap = editor->project->addNewMapToGroup(newMapName, groupNum);
391
+    editor->project->saveMap(newMap);
392
+    editor->project->saveAllDataStructures();
393
+
394
+    int numMapsInGroup = groupItem->rowCount();
395
+    QStandardItem *newMapItem = createMapItem(newMapName, groupNum, numMapsInGroup);
396
+    groupItem->appendRow(newMapItem);
397
+
398
+    setMap(newMapName);
399
+}
400
+
337
 void MainWindow::on_mapList_activated(const QModelIndex &index)
401
 void MainWindow::on_mapList_activated(const QModelIndex &index)
338
 {
402
 {
339
     QVariant data = index.data(Qt::UserRole);
403
     QVariant data = index.data(Qt::UserRole);

+ 14
- 0
mainwindow.h View File

4
 #include <QString>
4
 #include <QString>
5
 #include <QModelIndex>
5
 #include <QModelIndex>
6
 #include <QMainWindow>
6
 #include <QMainWindow>
7
+#include <QStandardItemModel>
7
 #include <QGraphicsPixmapItem>
8
 #include <QGraphicsPixmapItem>
8
 #include <QGraphicsItemGroup>
9
 #include <QGraphicsItemGroup>
9
 #include <QGraphicsSceneMouseEvent>
10
 #include <QGraphicsSceneMouseEvent>
65
 
66
 
66
     void on_toolButton_Dropper_clicked();
67
     void on_toolButton_Dropper_clicked();
67
 
68
 
69
+    void onOpenMapListContextMenu(const QPoint &point);
70
+    void onAddNewMapToGroupClick(QAction* triggeredAction);
71
+
68
 private:
72
 private:
69
     Ui::MainWindow *ui;
73
     Ui::MainWindow *ui;
74
+    QStandardItemModel *mapListModel;
75
+    QList<QStandardItem*> *mapGroupsModel;
70
     Editor *editor = NULL;
76
     Editor *editor = NULL;
77
+    QIcon* mapIcon;
71
     void setMap(QString);
78
     void setMap(QString);
79
+    void loadDataStructures();
72
     void populateMapList();
80
     void populateMapList();
73
     QString getExistingDirectory(QString);
81
     QString getExistingDirectory(QString);
74
     void openProject(QString dir);
82
     void openProject(QString dir);
75
     QString getDefaultMap();
83
     QString getDefaultMap();
76
     void setRecentMap(QString map_name);
84
     void setRecentMap(QString map_name);
85
+    QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
77
 
86
 
78
     void markAllEdited(QAbstractItemModel *model);
87
     void markAllEdited(QAbstractItemModel *model);
79
     void markEdited(QModelIndex index);
88
     void markEdited(QModelIndex index);
83
     void checkToolButtons();
92
     void checkToolButtons();
84
 };
93
 };
85
 
94
 
95
+enum MapListUserRoles {
96
+    GroupRole = Qt::UserRole + 1, // Used to hold the map group number.
97
+    TypeRole = Qt::UserRole + 2,  // Used to differentiate between the different layers of the map list tree view.
98
+};
99
+
86
 #endif // MAINWINDOW_H
100
 #endif // MAINWINDOW_H

+ 1
- 1
map.cpp View File

732
 }
732
 }
733
 
733
 
734
 bool Map::hasUnsavedChanges() {
734
 bool Map::hasUnsavedChanges() {
735
-    return !history.isSaved();
735
+    return !history.isSaved() || !isPersistedToFile;
736
 }
736
 }

+ 3
- 0
map.h View File

76
 public:
76
 public:
77
     QString name;
77
     QString name;
78
     QString constantName;
78
     QString constantName;
79
+    QString group_num;
79
     QString attributes_label;
80
     QString attributes_label;
80
     QString events_label;
81
     QString events_label;
81
     QString scripts_label;
82
     QString scripts_label;
102
 
103
 
103
     Blockdata* blockdata = NULL;
104
     Blockdata* blockdata = NULL;
104
 
105
 
106
+    bool isPersistedToFile = true;
107
+
105
 public:
108
 public:
106
     void setName(QString mapName);
109
     void setName(QString mapName);
107
     static QString mapConstantFromName(QString mapName);
110
     static QString mapConstantFromName(QString mapName);

+ 513
- 19
project.cpp View File

6
 #include "event.h"
6
 #include "event.h"
7
 
7
 
8
 #include <QDebug>
8
 #include <QDebug>
9
+#include <QDir>
9
 #include <QFile>
10
 #include <QFile>
10
 #include <QTextStream>
11
 #include <QTextStream>
12
+#include <QStandardItem>
11
 #include <QMessageBox>
13
 #include <QMessageBox>
12
 #include <QRegularExpression>
14
 #include <QRegularExpression>
13
 
15
 
14
 Project::Project()
16
 Project::Project()
15
 {
17
 {
16
     groupNames = new QStringList;
18
     groupNames = new QStringList;
17
-    groupedMapNames = new QList<QStringList*>;
19
+    map_groups = new QMap<QString, int>;
18
     mapNames = new QStringList;
20
     mapNames = new QStringList;
19
     map_cache = new QMap<QString, Map*>;
21
     map_cache = new QMap<QString, Map*>;
22
+    mapConstantsToMapNames = new QMap<QString, QString>;
23
+    mapNamesToMapConstants = new QMap<QString, QString>;
20
     tileset_cache = new QMap<QString, Tileset*>;
24
     tileset_cache = new QMap<QString, Tileset*>;
21
 }
25
 }
22
 
26
 
29
 }
33
 }
30
 
34
 
31
 Map* Project::loadMap(QString map_name) {
35
 Map* Project::loadMap(QString map_name) {
32
-    Map *map = new Map;
36
+    Map *map;
37
+    if (map_cache->contains(map_name)) {
38
+        map = map_cache->value(map_name);
39
+        if (map->hasUnsavedChanges()) {
40
+            return map;
41
+        }
42
+    } else {
43
+        map = new Map;
44
+        map->setName(map_name);
45
+    }
33
 
46
 
34
-    map->setName(map_name);
35
     readMapHeader(map);
47
     readMapHeader(map);
36
     readMapAttributes(map);
48
     readMapAttributes(map);
37
     getTilesets(map);
49
     getTilesets(map);
47
 }
59
 }
48
 
60
 
49
 void Project::loadMapConnections(Map *map) {
61
 void Project::loadMapConnections(Map *map) {
62
+    if (!map->isPersistedToFile) {
63
+        return;
64
+    }
65
+
50
     map->connections.clear();
66
     map->connections.clear();
51
     if (!map->connections_label.isNull()) {
67
     if (!map->connections_label.isNull()) {
52
         QString path = root + QString("/data/maps/%1/connections.inc").arg(map->name);
68
         QString path = root + QString("/data/maps/%1/connections.inc").arg(map->name);
67
                     connection->direction = command.value(1);
83
                     connection->direction = command.value(1);
68
                     connection->offset = command.value(2);
84
                     connection->offset = command.value(2);
69
                     QString mapConstant = command.value(3);
85
                     QString mapConstant = command.value(3);
70
-                    if (mapConstantsToMapNames.contains(mapConstant)) {
71
-                        connection->map_name = mapConstantsToMapNames[mapConstant];
86
+                    if (mapConstantsToMapNames->contains(mapConstant)) {
87
+                        connection->map_name = mapConstantsToMapNames->value(mapConstant);
72
                         map->connections.append(connection);
88
                         map->connections.append(connection);
73
                     } else {
89
                     } else {
74
                         qDebug() << QString("Failed to find connected map for map constant '%1'").arg(mapConstant);
90
                         qDebug() << QString("Failed to find connected map for map constant '%1'").arg(mapConstant);
79
     }
95
     }
80
 }
96
 }
81
 
97
 
98
+void Project::setNewMapConnections(Map *map) {
99
+    map->connections.clear();
100
+}
101
+
82
 QList<QStringList>* Project::getLabelMacros(QList<QStringList> *list, QString label) {
102
 QList<QStringList>* Project::getLabelMacros(QList<QStringList> *list, QString label) {
83
     bool in_label = false;
103
     bool in_label = false;
84
     QList<QStringList> *new_list = new QList<QStringList>;
104
     QList<QStringList> *new_list = new QList<QStringList>;
122
 }
142
 }
123
 
143
 
124
 void Project::readMapHeader(Map* map) {
144
 void Project::readMapHeader(Map* map) {
145
+    if (!map->isPersistedToFile) {
146
+        return;
147
+    }
148
+
125
     QString label = map->name;
149
     QString label = map->name;
126
     Asm *parser = new Asm;
150
     Asm *parser = new Asm;
127
 
151
 
145
     map->battle_scene = header->value(12);
169
     map->battle_scene = header->value(12);
146
 }
170
 }
147
 
171
 
172
+void Project::setNewMapHeader(Map* map, int mapIndex) {
173
+    map->attributes_label = QString("%1_MapAttributes").arg(map->name);
174
+    map->events_label = QString("%1_MapEvents").arg(map->name);;
175
+    map->scripts_label = QString("%1_MapScripts").arg(map->name);;
176
+    map->connections_label = "0x0";
177
+    map->song = "BGM_DAN02";
178
+    map->index = QString("%1").arg(mapIndex);
179
+    map->location = "0";
180
+    map->visibility = "0";
181
+    map->weather = "2";
182
+    map->type = "1";
183
+    map->unknown = "0";
184
+    map->show_location = "1";
185
+    map->battle_scene = "0";
186
+}
187
+
148
 void Project::saveMapHeader(Map *map) {
188
 void Project::saveMapHeader(Map *map) {
149
     QString label = map->name;
189
     QString label = map->name;
150
     QString header_path = root + "/data/maps/" + label + "/header.inc";
190
     QString header_path = root + "/data/maps/" + label + "/header.inc";
166
     saveTextFile(header_path, text);
206
     saveTextFile(header_path, text);
167
 }
207
 }
168
 
208
 
209
+void Project::readMapAttributesTable() {
210
+    int curMapIndex = 1;
211
+    QString attributesText = readTextFile(getMapAttributesTableFilepath());
212
+    QList<QStringList>* values = parse(attributesText);
213
+    bool inAttributePointers = false;
214
+    for (int i = 0; i < values->length(); i++) {
215
+        QStringList params = values->value(i);
216
+        QString macro = params.value(0);
217
+        if (macro == ".label") {
218
+            if (inAttributePointers) {
219
+                break;
220
+            }
221
+            if (params.value(1) == "gMapAttributes") {
222
+                inAttributePointers = true;
223
+            }
224
+        } else if (macro == ".4byte" && inAttributePointers) {
225
+            QString mapName = params.value(1);
226
+            if (!mapName.contains("UnknownMapAttributes")) {
227
+                // Strip off "_MapAttributes" from the label if it's a real map label.
228
+                mapName = mapName.remove(mapName.length() - 14, 14);
229
+            }
230
+            mapAttributesTable.insert(curMapIndex, mapName);
231
+            curMapIndex++;
232
+        }
233
+    }
234
+
235
+    // Deep copy
236
+    mapAttributesTableMaster = mapAttributesTable;
237
+    mapAttributesTableMaster.detach();
238
+}
239
+
240
+void Project::saveMapAttributesTable() {
241
+    QString text = "";
242
+    text += QString("\t.align 2\n");
243
+    text += QString("gMapAttributes::\n");
244
+    for (int i = 0; i < mapAttributesTableMaster.count(); i++) {
245
+        int mapIndex = i + 1;
246
+        QString mapName = mapAttributesTableMaster.value(mapIndex);
247
+        if (!mapName.contains("UnknownMapAttributes")) {
248
+            text += QString("\t.4byte %1_MapAttributes\n").arg(mapName);
249
+        } else {
250
+            text += QString("\t.4byte %1\n").arg(mapName);
251
+        }
252
+    }
253
+    saveTextFile(getMapAttributesTableFilepath(), text);
254
+}
255
+
256
+QString Project::getMapAttributesTableFilepath() {
257
+    return QString("%1/data/maps/attributes_table.inc").arg(root);
258
+}
259
+
169
 void Project::readMapAttributes(Map* map) {
260
 void Project::readMapAttributes(Map* map) {
261
+    if (!map->isPersistedToFile) {
262
+        return;
263
+    }
264
+
170
     Asm *parser = new Asm;
265
     Asm *parser = new Asm;
171
 
266
 
172
-    QString assets_text = readTextFile(root + "/data/maps/_assets.inc");
267
+    QString assets_text = readTextFile(getMapAssetsFilepath());
173
     if (assets_text.isNull()) {
268
     if (assets_text.isNull()) {
174
         return;
269
         return;
175
     }
270
     }
182
     map->tileset_secondary_label = attributes->value(5);
277
     map->tileset_secondary_label = attributes->value(5);
183
 }
278
 }
184
 
279
 
280
+void Project::readAllMapAttributes() {
281
+    mapAttributes.clear();
282
+
283
+    Asm *parser = new Asm;
284
+    QString assets_text = readTextFile(getMapAssetsFilepath());
285
+    if (assets_text.isNull()) {
286
+        return;
287
+    }
288
+
289
+    QList<QStringList> *commands = parser->parse(assets_text);
290
+
291
+    // Assume the _assets.inc file is grouped consistently in the order of:
292
+    // 1. <map_name>_MapBorder
293
+    // 2. <map_name>_MapBlockdata
294
+    // 3. <map_name>_MapAttributes
295
+    int i = 0;
296
+    while (i < commands->length()) {
297
+        // Read MapBorder assets.
298
+        QStringList borderParams = commands->value(i++);
299
+        bool isUnknownMapBorder = borderParams.value(1).startsWith("UnknownMapBorder_");
300
+        if (borderParams.value(0) != ".label" || (!borderParams.value(1).endsWith("_MapBorder") && !isUnknownMapBorder)) {
301
+            qDebug() << QString("Expected MapBorder label, but found %1").arg(borderParams.value(1));
302
+            continue;
303
+        }
304
+        QString borderLabel = borderParams.value(1);
305
+        QString mapName;
306
+        if (!isUnknownMapBorder) {
307
+            mapName = borderLabel.remove(borderLabel.length() - 10, 10);
308
+        } else {
309
+            // Unknown map name has to match the MapAttributes label.
310
+            mapName = borderLabel.replace("Border", "Attributes");
311
+        }
312
+
313
+        mapAttributes[mapName].insert("border_label", borderParams.value(1));
314
+        borderParams = commands->value(i++);
315
+        mapAttributes[mapName].insert("border_filepath", borderParams.value(1).replace("\"", ""));
316
+
317
+        // Read MapBlockData assets.
318
+        QStringList blockDataParams = commands->value(i++);
319
+        bool isUnknownMapBlockdata = blockDataParams.value(1).startsWith("UnknownMapBlockdata_");
320
+        if (blockDataParams.value(0) != ".label" || (!blockDataParams.value(1).endsWith("_MapBlockdata") && !isUnknownMapBlockdata)) {
321
+            qDebug() << QString("Expected MapBlockdata label, but found %1").arg(blockDataParams.value(1));
322
+            continue;
323
+        }
324
+        QString blockDataLabel = blockDataParams.value(1);
325
+        mapAttributes[mapName].insert("blockdata_label", blockDataLabel);
326
+        blockDataParams = commands->value(i++);
327
+        mapAttributes[mapName].insert("blockdata_filepath", blockDataParams.value(1).replace("\"", ""));
328
+
329
+        // Read MapAttributes assets.
330
+        i++; // skip .align
331
+        // Maps can share MapAttributes, so  gather a list of them.
332
+        QStringList attributeMapLabels;
333
+        QStringList attributesParams;
334
+        QStringList* sharedAttrMaps = new QStringList;
335
+        while (i < commands->length()) {
336
+            attributesParams = commands->value(i);
337
+            if (attributesParams.value(0) != ".label") {
338
+                break;
339
+            }
340
+            QString attrLabel = attributesParams.value(1);
341
+            attributeMapLabels.append(attrLabel);
342
+            sharedAttrMaps->append(attrLabel);
343
+            i++;
344
+        }
345
+
346
+        // Apply the map attributes to each of the shared maps.
347
+        QString attrWidth = commands->value(i++).value(1);
348
+        QString attrHeight = commands->value(i++).value(1);
349
+        QString attrBorderLabel = commands->value(i++).value(1);
350
+        QString attrBlockdataLabel = commands->value(i++).value(1);
351
+        QString attrTilesetPrimary = commands->value(i++).value(1);
352
+        QString attrTilesetSecondary = commands->value(i++).value(1);
353
+        for (QString attributeMapLabel: attributeMapLabels) {
354
+            QString altMapName = attributeMapLabel;
355
+            if (!altMapName.startsWith("UnknownMapAttributes_")) {
356
+                altMapName.remove(altMapName.length() - 14, 14);
357
+            }
358
+            if (!mapAttributes.contains(altMapName)) {
359
+                mapAttributes.insert(altMapName, QMap<QString, QString>());
360
+            }
361
+            mapAttributes[altMapName].insert("attributes_label", attributeMapLabel);
362
+            mapAttributes[altMapName].insert("width", attrWidth);
363
+            mapAttributes[altMapName].insert("height", attrHeight);
364
+            mapAttributes[altMapName].insert("border_label", attrBorderLabel);
365
+            mapAttributes[altMapName].insert("blockdata_label", attrBlockdataLabel);
366
+            mapAttributes[altMapName].insert("tileset_primary", attrTilesetPrimary);
367
+            mapAttributes[altMapName].insert("tileset_secondary", attrTilesetSecondary);
368
+
369
+            if (sharedAttrMaps->length() > 1) {
370
+                mapAttributes[altMapName].insert("shared_attr_maps", sharedAttrMaps->join(":"));
371
+            }
372
+        }
373
+    }
374
+
375
+    // Deep copy
376
+    mapAttributesMaster = mapAttributes;
377
+    mapAttributesMaster.detach();
378
+}
379
+
380
+void Project::saveAllMapAttributes() {
381
+    QString text = "";
382
+    for (int i = 0; i < mapAttributesTableMaster.count(); i++) {
383
+        int mapIndex = i + 1;
384
+        QString mapName = mapAttributesTableMaster.value(mapIndex);
385
+        QMap<QString, QString> attrs = mapAttributesMaster.value(mapName);
386
+
387
+        // Find the map attributes object that contains the border data.
388
+        QMap<QString, QString> attrsWithBorder;
389
+        if (attrs.contains("border_filepath")) {
390
+            attrsWithBorder = attrs;
391
+        } else {
392
+            QStringList labels = attrs.value("shared_attr_maps").split(":");
393
+            for (QString label : labels) {
394
+                label.remove(label.length() - 14, 14);
395
+                if (mapAttributesMaster.contains(label) && mapAttributesMaster.value(label).contains("border_filepath")) {
396
+                    attrsWithBorder = mapAttributesMaster.value(label);
397
+                    break;
398
+                }
399
+            }
400
+        }
401
+        if (!attrsWithBorder.isEmpty()) {
402
+            text += QString("%1::\n").arg(attrsWithBorder.value("border_label"));
403
+            text += QString("\t.incbin \"%1\"\n").arg(attrsWithBorder.value("border_filepath"));
404
+            text += QString("\n");
405
+        }
406
+
407
+        // Find the map attributes object that contains the blockdata.
408
+        QMap<QString, QString> attrsWithBlockdata;
409
+        if (attrs.contains("blockdata_filepath")) {
410
+            attrsWithBlockdata = attrs;
411
+        } else {
412
+            QStringList labels = attrs["shared_attr_maps"].split(":");
413
+            for (QString label : labels) {
414
+                label.remove(label.length() - 14, 14);
415
+                if (mapAttributesMaster.contains(label) && mapAttributesMaster.value(label).contains("blockdata_filepath")) {
416
+                    attrsWithBlockdata = mapAttributesMaster.value(label);
417
+                    break;
418
+                }
419
+            }
420
+        }
421
+        if (!attrsWithBlockdata.isEmpty()) {
422
+            text += QString("%1::\n").arg(attrsWithBlockdata.value("blockdata_label"));
423
+            text += QString("\t.incbin \"%1\"\n").arg(attrsWithBorder.value("blockdata_filepath"));
424
+            text += QString("\n");
425
+        }
426
+
427
+        text += QString("\t.align 2\n");
428
+        if (attrs.contains("shared_attr_maps")) {
429
+            QStringList labels = attrs.value("shared_attr_maps").split(":");
430
+            for (QString label : labels) {
431
+                text += QString("%1::\n").arg(label);
432
+            }
433
+        } else {
434
+            text += QString("%1::\n").arg(attrs.value("attributes_label"));
435
+        }
436
+        text += QString("\t.4byte %1\n").arg(attrs.value("width"));
437
+        text += QString("\t.4byte %1\n").arg(attrs.value("height"));
438
+        text += QString("\t.4byte %1\n").arg(attrs.value("border_label"));
439
+        text += QString("\t.4byte %1\n").arg(attrs.value("blockdata_label"));
440
+        text += QString("\t.4byte %1\n").arg(attrs.value("tileset_primary"));
441
+        text += QString("\t.4byte %1\n").arg(attrs.value("tileset_secondary"));
442
+        text += QString("\n");
443
+    }
444
+
445
+    saveTextFile(getMapAssetsFilepath(), text);
446
+}
447
+
448
+QString Project::getMapAssetsFilepath() {
449
+    return root + "/data/maps/_assets.inc";
450
+}
451
+
452
+void Project::setNewMapAttributes(Map* map) {
453
+    map->width = "20";
454
+    map->height = "20";
455
+    map->border_label = QString("%1_MapBorder").arg(map->name);
456
+    map->blockdata_label = QString("%1_MapBlockdata").arg(map->name);
457
+    map->tileset_primary_label = "gTileset_General";
458
+    map->tileset_secondary_label = "gTileset_Petalburg";
459
+
460
+    // Insert new entry into the global map attributes.
461
+    QMap<QString, QString> attrs;
462
+    attrs.insert("border_label", QString("%1_MapBorder").arg(map->name));
463
+    attrs.insert("border_filepath", QString("data/maps/%1/border.bin").arg(map->name));
464
+    attrs.insert("blockdata_label", QString("%1_MapBlockdata").arg(map->name));
465
+    attrs.insert("blockdata_filepath", QString("data/maps/%1/map.bin").arg(map->name));
466
+    attrs.insert("attributes_label", QString("%1_MapAttributes").arg(map->name));
467
+    attrs.insert("width", map->width);
468
+    attrs.insert("height", map->height);
469
+    attrs.insert("tileset_primary", map->tileset_primary_label);
470
+    attrs.insert("tileset_secondary", map->tileset_secondary_label);
471
+    mapAttributes.insert(map->name, attrs);
472
+}
473
+
474
+void Project::saveMapGroupsTable() {
475
+    QString text = "";
476
+    int groupNum = 0;
477
+    for (QStringList mapNames : groupedMapNames) {
478
+        text += QString("\t.align 2\n");
479
+        text += QString("gMapGroup%1::\n").arg(groupNum);
480
+        for (QString mapName : mapNames) {
481
+            text += QString("\t.4byte %1\n").arg(mapName);
482
+        }
483
+        text += QString("\n");
484
+        groupNum++;
485
+    }
486
+
487
+    text += QString("\t.align 2\n");
488
+    text += QString("gMapGroups::\n");
489
+    for (int i = 0; i < groupNum; i++) {
490
+        text += QString("\t.4byte gMapGroup%1\n").arg(i);
491
+    }
492
+
493
+    saveTextFile(root + "/data/maps/_groups.inc", text);
494
+}
495
+
496
+void Project::saveMapConstantsHeader() {
497
+    QString text = QString("#ifndef GUARD_CONSTANTS_MAPS_H\n");
498
+    text += QString("#define GUARD_CONSTANTS_MAPS_H\n");
499
+    text += QString("\n");
500
+
501
+    int groupNum = 0;
502
+    for (QStringList mapNames : groupedMapNames) {
503
+        text += QString("// Map Group %1\n").arg(groupNum);
504
+        int maxLength = 0;
505
+        for (QString mapName : mapNames) {
506
+            QString mapConstantName = mapNamesToMapConstants->value(mapName);
507
+            if (mapConstantName.length() > maxLength)
508
+                maxLength = mapConstantName.length();
509
+        }
510
+        int groupIndex = 0;
511
+        for (QString mapName : mapNames) {
512
+            QString mapConstantName = mapNamesToMapConstants->value(mapName);
513
+            text += QString("#define %1%2(%3 | (%4 << 8))\n")
514
+                    .arg(mapConstantName)
515
+                    .arg(QString(" ").repeated(maxLength - mapConstantName.length() + 1))
516
+                    .arg(groupIndex)
517
+                    .arg(groupNum);
518
+            groupIndex++;
519
+        }
520
+        text += QString("\n");
521
+        groupNum++;
522
+    }
523
+
524
+    text += QString("\n");
525
+    text += QString("#define MAP_NONE (0x7F | (0x7F << 8))\n");
526
+    text += QString("#define MAP_UNDEFINED (0xFF | (0xFF << 8))\n\n\n");
527
+    text += QString("#define MAP_GROUP(map) (MAP_##map >> 8)\n");
528
+    text += QString("#define MAP_NUM(map) (MAP_##map & 0xFF)\n\n");
529
+    text += QString("#endif  // GUARD_CONSTANTS_MAPS_H\n");
530
+    saveTextFile(root + "/include/constants/maps.h", text);
531
+}
532
+
185
 void Project::getTilesets(Map* map) {
533
 void Project::getTilesets(Map* map) {
186
     map->tileset_primary = getTileset(map->tileset_primary_label);
534
     map->tileset_primary = getTileset(map->tileset_primary_label);
187
     map->tileset_secondary = getTileset(map->tileset_secondary_label);
535
     map->tileset_secondary = getTileset(map->tileset_secondary_label);
210
 }
558
 }
211
 
559
 
212
 QString Project::getBlockdataPath(Map* map) {
560
 QString Project::getBlockdataPath(Map* map) {
213
-    QString text = readTextFile(root + "/data/maps/_assets.inc");
561
+    QString text = readTextFile(getMapAssetsFilepath());
214
     QStringList *values = getLabelValues(parse(text), map->blockdata_label);
562
     QStringList *values = getLabelValues(parse(text), map->blockdata_label);
215
     QString path;
563
     QString path;
216
     if (!values->isEmpty()) {
564
     if (!values->isEmpty()) {
222
 }
570
 }
223
 
571
 
224
 QString Project::getMapBorderPath(Map *map) {
572
 QString Project::getMapBorderPath(Map *map) {
225
-    QString text = readTextFile(root + "/data/maps/_assets.inc");
573
+    QString text = readTextFile(getMapAssetsFilepath());
226
     QStringList *values = getLabelValues(parse(text), map->border_label);
574
     QStringList *values = getLabelValues(parse(text), map->border_label);
227
     QString path;
575
     QString path;
228
     if (!values->isEmpty()) {
576
     if (!values->isEmpty()) {
234
 }
582
 }
235
 
583
 
236
 void Project::loadBlockdata(Map* map) {
584
 void Project::loadBlockdata(Map* map) {
585
+    if (!map->isPersistedToFile) {
586
+        return;
587
+    }
588
+
237
     QString path = getBlockdataPath(map);
589
     QString path = getBlockdataPath(map);
238
     map->blockdata = readBlockdata(path);
590
     map->blockdata = readBlockdata(path);
239
 }
591
 }
240
 
592
 
593
+void Project::setNewMapBlockdata(Map* map) {
594
+    Blockdata *blockdata = new Blockdata;
595
+    for (int i = 0; i < map->getWidth() * map->getHeight(); i++) {
596
+        blockdata->addBlock(qint16(0x3001));
597
+    }
598
+    map->blockdata = blockdata;
599
+}
600
+
241
 void Project::loadMapBorder(Map *map) {
601
 void Project::loadMapBorder(Map *map) {
602
+    if (!map->isPersistedToFile) {
603
+        return;
604
+    }
605
+
242
     QString path = getMapBorderPath(map);
606
     QString path = getMapBorderPath(map);
243
     map->border = readBlockdata(path);
607
     map->border = readBlockdata(path);
244
 }
608
 }
245
 
609
 
610
+void Project::setNewMapBorder(Map *map) {
611
+    Blockdata *blockdata = new Blockdata;
612
+    blockdata->addBlock(qint16(0x01D4));
613
+    blockdata->addBlock(qint16(0x01D5));
614
+    blockdata->addBlock(qint16(0x01DC));
615
+    blockdata->addBlock(qint16(0x01DD));
616
+    map->border = blockdata;
617
+}
618
+
619
+void Project::saveMapBorder(Map *map) {
620
+    QString path = getMapBorderPath(map);
621
+    writeBlockdata(path, map->border);
622
+}
623
+
246
 void Project::saveBlockdata(Map* map) {
624
 void Project::saveBlockdata(Map* map) {
247
     QString path = getBlockdataPath(map);
625
     QString path = getBlockdataPath(map);
248
     writeBlockdata(path, map->blockdata);
626
     writeBlockdata(path, map->blockdata);
267
 }
645
 }
268
 
646
 
269
 void Project::saveMap(Map *map) {
647
 void Project::saveMap(Map *map) {
270
-    saveBlockdata(map);
648
+    // Create/Modify a few collateral files for brand new maps.
649
+    if (!map->isPersistedToFile) {
650
+        QString newMapDataDir = QString(root + "/data/maps/%1").arg(map->name);
651
+        if (!QDir::root().mkdir(newMapDataDir)) {
652
+            qDebug() << "Error: failed to create directory for new map. " << newMapDataDir;
653
+        }
654
+
655
+        // TODO: In the future, these files needs more structure to allow for proper parsing/saving.
656
+        // Create file data/scripts/maps/<map_name>.inc
657
+        QString text = QString("%1_MapScripts::\n\t.byte 0\n").arg(map->name);
658
+        saveTextFile(root + "/data/scripts/maps/" + map->name + ".inc", text);
659
+
660
+        // Create file data/text/maps/<map_name>.inc
661
+        saveTextFile(root + "/data/text/maps/" + map->name + ".inc", "\n");
662
+
663
+        // Simply append to data/event_scripts.s.
664
+        text = QString("\n\t.include \"data/scripts/maps/%1.inc\"\n").arg(map->name);
665
+        text += QString("\t.include \"data/text/maps/%1.inc\"\n").arg(map->name);
666
+        appendTextFile(root + "/data/event_scripts.s", text);
667
+
668
+        // Simply append to data/map_events.s.
669
+        text = QString("\n\t.include \"data/maps/events/%1.inc\"\n").arg(map->name);
670
+        appendTextFile(root + "/data/map_events.s", text);
671
+
672
+        // Simply append to data/maps/headers.inc.
673
+        text = QString("\t.include \"data/maps/%1/header.inc\"\n").arg(map->name);
674
+        appendTextFile(root + "/data/maps/headers.inc", text);
675
+    }
676
+
677
+    saveMapBorder(map);
271
     saveMapHeader(map);
678
     saveMapHeader(map);
679
+    saveBlockdata(map);
272
     saveMapEvents(map);
680
     saveMapEvents(map);
681
+
682
+    // Update global data structures with current map data.
683
+    updateMapAttributes(map);
684
+
685
+    map->isPersistedToFile = true;
686
+}
687
+
688
+void Project::updateMapAttributes(Map* map) {
689
+    mapAttributesTableMaster.insert(map->index.toInt(nullptr, 0), map->name);
690
+
691
+    // Deep copy
692
+    QMap<QString, QString> attrs = mapAttributes.value(map->name);
693
+    attrs.detach();
694
+    mapAttributesMaster.insert(map->name, attrs);
695
+}
696
+
697
+void Project::saveAllDataStructures() {
698
+    saveMapAttributesTable();
699
+    saveAllMapAttributes();
700
+    saveMapGroupsTable();
701
+    saveMapConstantsHeader();
273
 }
702
 }
274
 
703
 
275
 void Project::loadTilesetAssets(Tileset* tileset) {
704
 void Project::loadTilesetAssets(Tileset* tileset) {
472
     }
901
     }
473
 }
902
 }
474
 
903
 
904
+void Project::appendTextFile(QString path, QString text) {
905
+    QFile file(path);
906
+    if (file.open(QIODevice::Append)) {
907
+        file.write(text.toUtf8());
908
+    } else {
909
+        qDebug() << QString("Could not open '%1' for appending: ").arg(path) + file.errorString();
910
+    }
911
+}
912
+
475
 void Project::readMapGroups() {
913
 void Project::readMapGroups() {
476
     QString text = readTextFile(root + "/data/maps/_groups.inc");
914
     QString text = readTextFile(root + "/data/maps/_groups.inc");
477
     if (text.isNull()) {
915
     if (text.isNull()) {
501
         }
939
         }
502
     }
940
     }
503
 
941
 
504
-    QList<QStringList*> *groupedMaps = new QList<QStringList*>;
942
+    QList<QStringList> groupedMaps;
505
     for (int i = 0; i < groups->length(); i++) {
943
     for (int i = 0; i < groups->length(); i++) {
506
-        QStringList *list = new QStringList;
507
-        groupedMaps->append(list);
944
+        groupedMaps.append(QStringList());
508
     }
945
     }
509
 
946
 
510
     QStringList *maps = new QStringList;
947
     QStringList *maps = new QStringList;
518
             if (group != -1) {
955
             if (group != -1) {
519
                 for (int j = 1; j < params.length(); j++) {
956
                 for (int j = 1; j < params.length(); j++) {
520
                     QString mapName = params.value(j);
957
                     QString mapName = params.value(j);
521
-                    QStringList *list = groupedMaps->value(group);
522
-                    list->append(mapName);
958
+                    groupedMaps[group].append(mapName);
523
                     maps->append(mapName);
959
                     maps->append(mapName);
960
+                    map_groups->insert(mapName, group);
524
 
961
 
525
                     // Build the mapping and reverse mapping between map constants and map names.
962
                     // Build the mapping and reverse mapping between map constants and map names.
526
                     QString mapConstant = Map::mapConstantFromName(mapName);
963
                     QString mapConstant = Map::mapConstantFromName(mapName);
527
-                    mapConstantsToMapNames.insert(mapConstant, mapName);
528
-                    mapNamesToMapConstants.insert(mapName, mapConstant);
964
+                    mapConstantsToMapNames->insert(mapConstant, mapName);
965
+                    mapNamesToMapConstants->insert(mapName, mapConstant);
529
                 }
966
                 }
530
             }
967
             }
531
         }
968
         }
536
     mapNames = maps;
973
     mapNames = maps;
537
 }
974
 }
538
 
975
 
976
+Map* Project::addNewMapToGroup(QString mapName, int groupNum) {
977
+    int mapIndex = mapAttributesTable.count() + 1;
978
+    mapAttributesTable.insert(mapIndex, mapName);
979
+
980
+    // Setup new map in memory, but don't write to file until map is actually saved later.
981
+    mapNames->append(mapName);
982
+    map_groups->insert(mapName, groupNum);
983
+    groupedMapNames[groupNum].append(mapName);
984
+
985
+    Map *map = new Map;
986
+    map->isPersistedToFile = false;
987
+    map->setName(mapName);
988
+    mapConstantsToMapNames->insert(map->constantName, map->name);
989
+    mapNamesToMapConstants->insert(map->name, map->constantName);
990
+    setNewMapHeader(map, mapIndex);
991
+    setNewMapAttributes(map);
992
+    getTilesets(map);
993
+    setNewMapBlockdata(map);
994
+    setNewMapBorder(map);
995
+    setNewMapEvents(map);
996
+    setNewMapConnections(map);
997
+    map->commit();
998
+    map->history.save();
999
+    map_cache->insert(mapName, map);
1000
+
1001
+    return map;
1002
+}
1003
+
1004
+QString Project::getNewMapName() {
1005
+    // Ensure default name doesn't already exist.
1006
+    int i = 0;
1007
+    QString newMapName;
1008
+    do {
1009
+        newMapName = QString("NewMap%1").arg(++i);
1010
+    } while (mapNames->contains(newMapName));
1011
+
1012
+    return newMapName;
1013
+}
1014
+
539
 QList<QStringList>* Project::parse(QString text) {
1015
 QList<QStringList>* Project::parse(QString text) {
540
     Asm *parser = new Asm;
1016
     Asm *parser = new Asm;
541
     return parser->parse(text);
1017
     return parser->parse(text);
739
             text += QString(", %1").arg(warp->get("y"));
1215
             text += QString(", %1").arg(warp->get("y"));
740
             text += QString(", %1").arg(warp->get("elevation"));
1216
             text += QString(", %1").arg(warp->get("elevation"));
741
             text += QString(", %1").arg(warp->get("destination_warp"));
1217
             text += QString(", %1").arg(warp->get("destination_warp"));
742
-            text += QString(", %1").arg(mapNamesToMapConstants[warp->get("destination_map_name")]);
1218
+            text += QString(", %1").arg(mapNamesToMapConstants->value(warp->get("destination_map_name")));
743
             text += "\n";
1219
             text += "\n";
744
         }
1220
         }
745
         text += "\n";
1221
         text += "\n";
811
 }
1287
 }
812
 
1288
 
813
 void Project::readMapEvents(Map *map) {
1289
 void Project::readMapEvents(Map *map) {
1290
+    if (!map->isPersistedToFile) {
1291
+        return;
1292
+    }
1293
+
814
     // lazy
1294
     // lazy
815
     QString path = root + QString("/data/maps/events/%1.inc").arg(map->name);
1295
     QString path = root + QString("/data/maps/events/%1.inc").arg(map->name);
816
     QString text = readTextFile(path);
1296
     QString text = readTextFile(path);
882
 
1362
 
883
             // Ensure the warp destination map constant is valid before adding it to the warps.
1363
             // Ensure the warp destination map constant is valid before adding it to the warps.
884
             QString mapConstant = command.value(i++);
1364
             QString mapConstant = command.value(i++);
885
-            if (mapConstantsToMapNames.contains(mapConstant)) {
886
-                warp->put("destination_map_name", mapConstantsToMapNames[mapConstant]);
1365
+            if (mapConstantsToMapNames->contains(mapConstant)) {
1366
+                warp->put("destination_map_name", mapConstantsToMapNames->value(mapConstant));
887
                 warp->put("event_type", "warp");
1367
                 warp->put("event_type", "warp");
888
                 map->events["warp"].append(warp);
1368
                 map->events["warp"].append(warp);
889
             } else {
1369
             } else {
973
     }
1453
     }
974
 }
1454
 }
975
 
1455
 
1456
+void Project::setNewMapEvents(Map *map) {
1457
+    map->object_events_label = "0x0";
1458
+    map->warps_label = "0x0";
1459
+    map->coord_events_label = "0x0";
1460
+    map->bg_events_label = "0x0";
1461
+    map->events["object"].clear();
1462
+    map->events["warp"].clear();
1463
+    map->events["trap"].clear();
1464
+    map->events["trap_weather"].clear();
1465
+    map->events["sign"].clear();
1466
+    map->events["event_hidden_item"].clear();
1467
+    map->events["event_secret_base"].clear();
1468
+}
1469
+
976
 QStringList Project::readCArray(QString text, QString label) {
1470
 QStringList Project::readCArray(QString text, QString label) {
977
     QStringList list;
1471
     QStringList list;
978
 
1472
 

+ 33
- 4
project.h View File

6
 
6
 
7
 #include <QStringList>
7
 #include <QStringList>
8
 #include <QList>
8
 #include <QList>
9
+#include <QStandardItem>
9
 
10
 
10
 class Project
11
 class Project
11
 {
12
 {
13
     Project();
14
     Project();
14
     QString root;
15
     QString root;
15
     QStringList *groupNames = NULL;
16
     QStringList *groupNames = NULL;
16
-    QList<QStringList*> *groupedMapNames = NULL;
17
+    QMap<QString, int> *map_groups;
18
+    QList<QStringList> groupedMapNames;
17
     QStringList *mapNames = NULL;
19
     QStringList *mapNames = NULL;
18
-    QMap<QString, QString> mapConstantsToMapNames;
19
-    QMap<QString, QString> mapNamesToMapConstants;
20
+    QMap<QString, QString>* mapConstantsToMapNames;
21
+    QMap<QString, QString>* mapNamesToMapConstants;
22
+    QMap<int, QString> mapAttributesTable;
23
+    QMap<int, QString> mapAttributesTableMaster;
24
+    QMap<QString, QMap<QString, QString>> mapAttributes;
25
+    QMap<QString, QMap<QString, QString>> mapAttributesMaster;
26
+
20
 
27
 
21
     QMap<QString, Map*> *map_cache;
28
     QMap<QString, Map*> *map_cache;
22
     Map* loadMap(QString);
29
     Map* loadMap(QString);
31
 
38
 
32
     QString readTextFile(QString path);
39
     QString readTextFile(QString path);
33
     void saveTextFile(QString path, QString text);
40
     void saveTextFile(QString path, QString text);
41
+    void appendTextFile(QString path, QString text);
34
 
42
 
35
     void readMapGroups();
43
     void readMapGroups();
44
+    Map* addNewMapToGroup(QString mapName, int groupNum);
45
+    QString getNewMapName();
36
     QString getProjectTitle();
46
     QString getProjectTitle();
37
 
47
 
38
     QList<QStringList>* getLabelMacros(QList<QStringList>*, QString);
48
     QList<QStringList>* getLabelMacros(QList<QStringList>*, QString);
39
     QStringList* getLabelValues(QList<QStringList>*, QString);
49
     QStringList* getLabelValues(QList<QStringList>*, QString);
40
     void readMapHeader(Map*);
50
     void readMapHeader(Map*);
51
+    void readMapAttributesTable();
52
+    void readAllMapAttributes();
41
     void readMapAttributes(Map*);
53
     void readMapAttributes(Map*);
42
     void getTilesets(Map*);
54
     void getTilesets(Map*);
43
     void loadTilesetAssets(Tileset*);
55
     void loadTilesetAssets(Tileset*);
44
 
56
 
45
     QString getBlockdataPath(Map*);
57
     QString getBlockdataPath(Map*);
46
     void saveBlockdata(Map*);
58
     void saveBlockdata(Map*);
59
+    void saveMapBorder(Map*);
47
     void writeBlockdata(QString, Blockdata*);
60
     void writeBlockdata(QString, Blockdata*);
48
     void saveAllMaps();
61
     void saveAllMaps();
49
     void saveMap(Map*);
62
     void saveMap(Map*);
50
-    void saveMapHeader(Map*);
63
+    void saveAllDataStructures();
64
+    void saveAllMapAttributes();
65
+    void saveMapGroupsTable();
66
+    void saveMapConstantsHeader();
51
 
67
 
52
     QList<QStringList>* parse(QString text);
68
     QList<QStringList>* parse(QString text);
53
     QStringList getSongNames();
69
     QStringList getSongNames();
73
     QStringList readCArray(QString text, QString label);
89
     QStringList readCArray(QString text, QString label);
74
     QString readCIncbin(QString text, QString label);
90
     QString readCIncbin(QString text, QString label);
75
     QMap<QString, int> readCDefines(QString text, QStringList prefixes);
91
     QMap<QString, int> readCDefines(QString text, QStringList prefixes);
92
+private:
93
+    QString getMapAttributesTableFilepath();
94
+    QString getMapAssetsFilepath();
95
+    void saveMapHeader(Map*);
96
+    void saveMapAttributesTable();
97
+    void updateMapAttributes(Map* map);
98
+
99
+    void setNewMapHeader(Map* map, int mapIndex);
100
+    void setNewMapAttributes(Map* map);
101
+    void setNewMapBlockdata(Map* map);
102
+    void setNewMapBorder(Map *map);
103
+    void setNewMapEvents(Map *map);
104
+    void setNewMapConnections(Map *map);
76
 };
105
 };
77
 
106
 
78
 #endif // PROJECT_H
107
 #endif // PROJECT_H