diff --git a/.gitignore b/.gitignore
index 3d265d53..bde28f17 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,12 +2,14 @@ porymap.pro.user
*.autosave
*.stash
*.o
-moc_*
-qrc_*
porymap.app*
porymap
+porymap.cfg
+porymap.log
Makefile
-# Generated UI header
+# Qt generated files
ui_*.h
-
+moc_*.h
+moc_*.cpp
+qrc_*.cpp
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui
index 1aa69cdd..c1e76938 100644
--- a/forms/mainwindow.ui
+++ b/forms/mainwindow.ui
@@ -237,7 +237,7 @@
- 0
+ 4
false
@@ -1066,8 +1066,8 @@
8
0
- 221
- 328
+ 222
+ 353
@@ -2693,6 +2693,785 @@
+
+
+ Region Map
+
+
+
+
+ 460
+ 420
+ 301
+ 181
+
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ true
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+ true
+
+
+
+ 8
+ 0
+ 283
+ 179
+
+
+
+
+ 0
+ 0
+
+
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+ 19
+ 9
+ 381
+ 291
+
+
+
+ 0
+
+
+
+ Background Image
+
+
+
+
+ 30
+ 20
+ 321
+ 211
+
+
+
+
+ 1
+ 0
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 319
+ 209
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ false
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ QGraphicsView::NoDrag
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+
+
+
+
+
+
+ Map Layout
+
+
+
+
+ 20
+ 20
+ 321
+ 211
+
+
+
+
+ 1
+ 0
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 319
+ 209
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ false
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ QGraphicsView::NoDrag
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+
+
+
+
+
+
+
+
+ 80
+ 380
+ 261
+ 251
+
+
+
+
+ 1
+ 0
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 259
+ 249
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ false
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ QGraphicsView::NoDrag
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+
+
+
+
+
+
+ 440
+ 20
+ 351
+ 291
+
+
+
+ 0
+
+
+
+
+
+ 30
+ 20
+ 281
+ 261
+
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ true
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+ true
+
+
+
+ 8
+ 0
+ 263
+ 259
+
+
+
+
+ 0
+ 0
+
+
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ 50
+ 40
+ 261
+ 170
+
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ -
+
+
+ Connected Map
+
+
+
+ -
+
+
+ <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 display when the player enters it.</p></body></html>
+
+
+ true
+
+
+
+ -
+
+
+ Weather
+
+
+
+ -
+
+
+ <html><head/><body><p>The default weather for this 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
+
+
+
+ -
+
+
+ Show Location Name
+
+
+
+ -
+
+
+ <html><head/><body><p>Whether or not to display the location name when the player enters the map.</p></body></html>
+
+
+
+
+
+
+ -
+
+
+ Battle scene
+
+
+
+ -
+
+
+ <html><head/><body><p>Determines the type of battle scene graphics to use.</p></body></html>
+
+
+ true
+
+
+
+
+
+
+
+
diff --git a/include/core/regionmapeditor.h b/include/core/regionmapeditor.h
new file mode 100644
index 00000000..2875ef81
--- /dev/null
+++ b/include/core/regionmapeditor.h
@@ -0,0 +1,179 @@
+#ifndef REGIONMAP_H
+#define REGIONMAP_H
+
+#include "project.h"
+#include "map.h"
+#include "tilemaptileselector.h"
+//#include "block.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+// if editing map bins, will need to remake the graphics when editing
+// are the scenes set in the editor / project / mainwindow files?
+
+/*
+ * - display the region map background image
+ * - edit the region_map_layout.h layout
+ * - edit city maps metatile layout and JUST save the mapname_num.bin
+ * - edit
+ * who edits pokenav_city_maps 1 and 2?
+ * users can: - add the incbins probably themselves
+ * - add
+ * - edit region map background image
+ *
+ *
+ *
+ *
+ * Editor:
+ * - void displayCityMapMetatileSelector
+ * - void displayRegionMapTileSelector
+ * - void selectRegionMapTile(QString mapname)
+ * - QGraphicsScene *scene_city_map_metatiles
+ * - TilemapTileSelector *city_map_metatile_selector_item
+ * - Tileset *city_map_squares (or tileset_city_map?)
+ * - Tileset *tileset_region_map
+ *
+ * MainWindow:
+ *
+ *
+ * Project:
+ *
+ */
+
+// rename this struct
+struct CityMapPosition
+{
+ //
+ //QString filename; // eg. dewford_0
+ QString tilemap;// eg. "dewford_0"
+ int x;
+ int y;
+};
+
+// class that holds data for each square in this project
+// struct?
+// TODO: change char / uint8_t to unsigned
+class RegionMapSquare
+{
+public:
+ //
+ // are positions layout positions? (yes) so out of bounds are all (-1, -1) <-- how it's used in code
+ // (GetRegionMapLocationPosition)
+ // or image positions
+ int x = -1;// x position, 0-indexed from top left
+ int y = -1;// y position, 0-indexed from top left
+ uint8_t tile_img_id;// tilemap ids for the background image
+ bool has_map = false;// whether this square is linked to a map or is empty
+ QString map_name;// name of the map associated with this square (if has_map is true): eg. "MAUVILLE_CITY"
+ // ^ use project mapsec to names table
+ bool has_city_map;// whether there is a city map on this grid
+ //QList city_maps;
+ QString city_map_name;// filename of the city_map tilemap
+ //bool is_flyable;//? needed ?
+ friend class RegionMap;// not necessary if instance? what
+};
+
+class RegionMap : public QObject
+{
+ Q_OBJECT
+//public:
+// explicit Map(QObject *parent = nullptr);
+
+public:
+ RegionMap() = default;
+
+ ~RegionMap() {
+ delete mapname_abbr;
+ delete layout_map_names;
+ //delete background_image_tiles;
+ //delete map_squares;
+ //delete background_image_selector_item;
+ };
+
+ static QMap> ruby_city_maps_;
+ static QString mapSecToMapConstant(QString);
+
+ //RegionMapSquare *map_squares = nullptr;// array of RegionMapSquares
+ QList map_squares;
+
+ QString temp_path;// delete this
+ QString city_map_squares_path;
+ QString region_map_png_path;
+ QString region_map_bin_path;// = QString::null;
+ QString city_map_header_path;//dafuq is this?
+ QString region_map_layout_path;
+
+ //QMap something;// name of map : info about city map, position in layoit, etc.
+ //QMap regionMapLayoutTng; // mapName : tilemaptileselector
+ // maybe position data to select correct square when changing map on side but only if map is a valid
+ //QList *background_image_tiles;// the visible ones anyways // using list because replace
+ //TilemapTileSelector *background_image_selector_item;// ?
+ QMap *mapname_abbr;// layout shortcuts mapname:region_map_layout defines (both ways)
+ // make this a QHash?? <-- no because something
+ QStringList *layout_map_names;
+ // uint8_t border_tile;
+
+ bool hasUnsavedChanges();
+
+ void init(Project*);//QString);
+
+ // parseutil.cpp ?
+ void readBkgImgBin();
+ void readCityMaps();// more complicated
+ void readLayout(QMap*);
+
+ QString newAbbr(QString);// makes a *unique* 5 character abbreviation from mapname to add to mapname_abbr
+
+ // editing functions
+ // if they are booleans, returns true if successful?
+ bool placeTile(char, int, int);// place tile at x, y
+ bool removeTile(char, int, int);// replaces with 0x00 byte at x,y
+ bool placeMap(QString, int, int);
+ bool removeMap(QString, int, int);
+ bool removeMap(QString);// remove all instances of map
+
+ void save();
+ void saveBkgImgBin();
+ void saveLayout();
+ void saveCityMaps();
+
+ void update();// update the view in case something is broken?
+ void resize(int, int);
+ void setWidth(int);
+ void setHeight(int);
+ int width();
+ int height();
+ QSize imgSize();
+ unsigned getTileId(int, int);
+
+ // implement these here?
+ void undo();
+ void redo();
+
+ void test(QMap*);// remove when done testing obvi
+
+// TODO: move read / write functions to private (and others)
+private:
+ //
+ int layout_width_;
+ int layout_height_;
+ int img_width_;
+ int img_height_;
+ int img_index_(int, int);// returns index int at x,y args (x + y * width_ * 2) // 2 because
+ int layout_index_(int, int);
+
+//protected:
+ //
+
+//signals:
+ //
+};
+
+//TilemapTileSelector *city_map_metatile_selector_item = nullptr;
+
+#endif // REGIONMAP_H
diff --git a/include/editor.h b/include/editor.h
index 4b7f71a0..b28f0ebf 100644
--- a/include/editor.h
+++ b/include/editor.h
@@ -19,6 +19,8 @@
#include "currentselectedmetatilespixmapitem.h"
#include "collisionpixmapitem.h"
#include "mappixmapitem.h"
+#include "regionmappixmapitem.h"
+#include "regionmapeditor.h"
#include "settings.h"
#include "movablerect.h"
#include "cursortilerect.h"
@@ -77,6 +79,33 @@ public:
void updateCustomMapHeaderValues(QTableWidget *);
Tileset *getCurrentMapPrimaryTileset();
+//
+ RegionMap *region_map;
+ void loadRegionMapData();
+
+ QGraphicsScene *scene_region_map_image = nullptr;
+ QGraphicsScene *scene_region_map_layout = nullptr;//?
+ QGraphicsScene *scene_region_map_tiles = nullptr;
+ TilemapTileSelector *mapsquare_selector_item = nullptr;
+ RegionMapPixmapItem *region_map_item = nullptr;
+
+ void displayRegionMap();
+ void displayRegionMapTileSelector();
+
+ // selectedTileChanged, hoveredTileChanged, hoveredTileCleared
+ void onRegionMapTileSelectorSelectedTileChanged();
+ void onRegionMapTileSelectorHoveredTileChanged(unsigned);
+ void onRegionMapTileSelectorHoveredTileCleared();
+
+private slots:
+ void onHoveredRegionMapTileChanged(int, int);
+ void onHoveredRegionMapTileCleared();
+ void mouseEvent_region_map(QGraphicsSceneMouseEvent *, RegionMapPixmapItem *);
+
+public:
+ QString regionMapTabStatusbarMessage;// TODO: make this name not terrible
+//
+
DraggablePixmapItem *addMapEvent(Event *event);
void selectMapEvent(DraggablePixmapItem *object);
void selectMapEvent(DraggablePixmapItem *object, bool toggle);
@@ -105,6 +134,7 @@ public:
QGraphicsScene *scene_selected_border_metatiles = nullptr;
QGraphicsScene *scene_collision_metatiles = nullptr;
QGraphicsScene *scene_elevation_metatiles = nullptr;
+
MetatileSelector *metatile_selector_item = nullptr;
BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
diff --git a/include/mainwindow.h b/include/mainwindow.h
index bb7d98c1..3cbe1fc0 100644
--- a/include/mainwindow.h
+++ b/include/mainwindow.h
@@ -65,6 +65,8 @@ private slots:
void on_checkBox_AllowBiking_clicked(bool checked);
void on_checkBox_AllowEscapeRope_clicked(bool checked);
+ void on_tabWidget_Region_Map_currentChanged(int);
+
void on_tabWidget_currentChanged(int index);
void on_actionUndo_triggered();
diff --git a/include/ui/regionmappixmapitem.h b/include/ui/regionmappixmapitem.h
new file mode 100644
index 00000000..12de3385
--- /dev/null
+++ b/include/ui/regionmappixmapitem.h
@@ -0,0 +1,36 @@
+#ifndef REGIONMAPPIXMAPITEM_H
+#define REGIONMAPPIXMAPITEM_H
+
+#include "regionmapeditor.h"
+#include "tilemaptileselector.h"
+#include
+
+class RegionMapPixmapItem : public QObject, public QGraphicsPixmapItem {
+ Q_OBJECT
+public:
+ RegionMapPixmapItem(RegionMap *rmap, TilemapTileSelector *tile_selector) {
+ this->region_map = rmap;
+ this->tile_selector = tile_selector;
+ setAcceptHoverEvents(true);
+ }
+ RegionMap *region_map;
+ TilemapTileSelector *tile_selector;
+
+ virtual void paint(QGraphicsSceneMouseEvent*);
+ virtual void select(QGraphicsSceneMouseEvent*);
+ virtual void draw();
+
+signals:
+ void mouseEvent(QGraphicsSceneMouseEvent *, RegionMapPixmapItem *);
+ void hoveredRegionMapTileChanged(int x, int y);
+ void hoveredRegionMapTileCleared();
+
+protected:
+ void hoverMoveEvent(QGraphicsSceneHoverEvent*);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
+ void mousePressEvent(QGraphicsSceneMouseEvent*);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent*);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
+};
+
+#endif // REGIONMAPPIXMAPITEM_H
diff --git a/include/ui/tilemaptileselector.h b/include/ui/tilemaptileselector.h
new file mode 100644
index 00000000..8bb52050
--- /dev/null
+++ b/include/ui/tilemaptileselector.h
@@ -0,0 +1,51 @@
+#ifndef TILEMAPTILESELECTOR_H
+#define TILEMAPTILESELECTOR_H
+
+#include "selectablepixmapitem.h"
+
+class TilemapTileSelector: public SelectablePixmapItem {
+ Q_OBJECT
+public:
+ TilemapTileSelector(QPixmap pixmap): SelectablePixmapItem(8, 8, 1, 1) {
+ this->pixmap = pixmap;
+ this->numTilesWide = 16;
+ this->selectedTile = 0x00;
+ setAcceptHoverEvents(true);
+ }
+ void draw();
+ void select(unsigned tileId);
+ unsigned getSelectedTile();
+
+ int pixelWidth;
+ int pixelHeight;
+
+ unsigned selectedTile;
+
+ // TODO: which of these need to be made public?
+ // call this tilemap? or is tilemap the binary file?
+ QPixmap pixmap;// pointer?
+ QImage currTile;// image of just the currently selected tile to draw onto graphicsview
+ QImage tileImg(unsigned tileId);
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent*);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent*);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
+ void hoverMoveEvent(QGraphicsSceneHoverEvent*);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
+
+private:
+ int numTilesWide;
+ int numTiles;
+ void updateSelectedTile();
+ unsigned getTileId(int x, int y);
+ QPoint getTileIdCoords(unsigned);
+ unsigned getValidTileId(unsigned);// TODO: implement this to prevent segfaults
+
+signals:
+ void hoveredTileChanged(unsigned);
+ void hoveredTileCleared();
+ void selectedTileChanged(unsigned);
+};
+
+#endif // TILEMAPTILESELECTOR_H
diff --git a/porymap.pro b/porymap.pro
index cfd02755..3868a8a2 100644
--- a/porymap.pro
+++ b/porymap.pro
@@ -28,6 +28,7 @@ SOURCES += src/core/block.cpp \
src/core/parseutil.cpp \
src/core/tile.cpp \
src/core/tileset.cpp \
+ src/core/regionmapeditor.cpp \
src/ui/aboutporymap.cpp \
src/ui/bordermetatilespixmapitem.cpp \
src/ui/collisionpixmapitem.cpp \
@@ -40,6 +41,7 @@ SOURCES += src/core/block.cpp \
src/ui/graphicsview.cpp \
src/ui/imageproviders.cpp \
src/ui/mappixmapitem.cpp \
+ src/ui/regionmappixmapitem.cpp \
src/ui/mapsceneeventfilter.cpp \
src/ui/metatilelayersitem.cpp \
src/ui/metatileselector.cpp \
@@ -53,6 +55,7 @@ SOURCES += src/core/block.cpp \
src/ui/tileseteditor.cpp \
src/ui/tileseteditormetatileselector.cpp \
src/ui/tileseteditortileselector.cpp \
+ src/ui/tilemaptileselector.cpp \
src/ui/newmappopup.cpp \
src/config.cpp \
src/editor.cpp \
@@ -78,6 +81,7 @@ HEADERS += include/core/block.h \
include/core/parseutil.h \
include/core/tile.h \
include/core/tileset.h \
+ include/core/regionmapeditor.h \
include/ui/aboutporymap.h \
include/ui/bordermetatilespixmapitem.h \
include/ui/collisionpixmapitem.h \
@@ -90,6 +94,7 @@ HEADERS += include/core/block.h \
include/ui/graphicsview.h \
include/ui/imageproviders.h \
include/ui/mappixmapitem.h \
+ include/ui/regionmappixmapitem.h \
include/ui/mapsceneeventfilter.h \
include/ui/metatilelayersitem.h \
include/ui/metatileselector.h \
@@ -103,6 +108,7 @@ HEADERS += include/core/block.h \
include/ui/tileseteditor.h \
include/ui/tileseteditormetatileselector.h \
include/ui/tileseteditortileselector.h \
+ include/ui/tilemaptileselector.h \
include/ui/newmappopup.h \
include/config.h \
include/editor.h \
diff --git a/src/core/regionmapeditor.cpp b/src/core/regionmapeditor.cpp
new file mode 100644
index 00000000..73b27c0f
--- /dev/null
+++ b/src/core/regionmapeditor.cpp
@@ -0,0 +1,402 @@
+#include "regionmapeditor.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+
+
+// TODO: add logging / config stuff
+
+// IN: ROUTE_101 ... OUT: MAP_ROUTE101
+// eg. SOUTHERN_ISLAND -> MAP_SOUTHERN_ISLAND -> SouthernIsland(n) -> SouthernIsland_Exterior
+// MT_CHIMNEY -> MAP_MT_CHIMNEY -> MtChimney(y)
+// ROUTE_101 -> MAP_ROUTE101 -> Route101(y)
+// TODO: move this maybe? would I be able to call it from this file if it was in map.cpp?
+QString RegionMap::mapSecToMapConstant(QString mapSectionName) {
+ //
+ QString mapConstantName = "MAP_";
+ QString sectionNameTemp = mapSectionName.replace("ROUTE_","ROUTE");
+ mapConstantName += sectionNameTemp;
+ return mapConstantName;
+}
+
+// TODO: verify these are in the correct order
+// also TODO: read this from the project somehow
+QMap> RegionMap::ruby_city_maps_ = QMap>({
+ {"LavaridgeTown", {
+ {"lavaridge_0.bin", 5, 3},
+ }},
+ {"FallarborTown", {
+ {"fallarbor_0.bin", 3, 0},
+ }},
+ {"FortreeCity", {
+ {"fortree_0.bin", 12, 0},
+ }},
+ {"SlateportCity", {
+ {"slateport_0.bin", 8, 10},
+ {"slateport_1.bin", 8, 11},
+ }},
+ {"RustboroCity", {
+ {"rustboro_0.bin", 0, 5},
+ {"rustboro_1.bin", 0, 6},
+ }},
+ {"PacifidlogTown", {
+ {"pacifidlog_0.bin", 17, 10},
+ }},
+ {"MauvilleCity", {
+ {"mauville_0.bin", 8, 6},
+ {"mauville_1.bin", 9, 6},
+ }},
+ {"OldaleTown", {
+ {"oldale_0.bin", 4, 9},
+ }},
+ {"LilycoveCity", {
+ {"lilycove_0.bin", 18, 3},
+ {"lilycove_1.bin", 19, 3},
+ }},
+ {"LittlerootTown", {
+ {"littleroot_0.bin", 4, 11},
+ }},
+ {"DewfordTown", {
+ {"dewford_0.bin", 2, 14},
+ }},
+ {"SootopolisCity", {
+ {"sootopolis_0.bin", 21, 7},
+ }},
+ {"EverGrandeCity", {
+ {"ever_grande_0.bin", 27, 8},
+ {"ever_grande_1.bin", 27, 9},
+ }},
+ {"VerdanturfTown", {
+ {"verdanturf_0.bin", 4, 6},
+ }},
+ {"MossdeepCity", {
+ {"mossdeep_0.bin", 24, 5},
+ {"mossdeep_1.bin", 25, 5},
+ }},
+ {"PetalburgCity", {
+ {"petalburg_0.bin", 1, 9},
+ }},
+});
+
+void RegionMap::init(Project *pro) {
+ QString path = pro->root;
+ //
+ // TODO: in the future, allow these to be adjustable (and save values)
+ // possibly use a config file?
+ layout_width_ = 28;
+ layout_height_ = 15;
+
+ img_width_ = layout_width_ + 4;
+ img_height_ = layout_height_ + 5;
+
+ //city_map_squares_path = QString();
+ temp_path = path;// delete this
+ region_map_bin_path = path + "/graphics/pokenav/region_map_map.bin";
+ region_map_png_path = path + "/graphics/pokenav/region_map.png";
+ region_map_layout_path = path + "/src/data/region_map_layout.h";
+
+ readBkgImgBin();
+ readLayout(pro->mapConstantsToMapNames);
+ readCityMaps();
+
+ //tryGetMap();
+
+ //saveBkgImgBin();
+ //saveLayout();
+ test(pro->mapConstantsToMapNames);
+}
+
+// as of now, this needs to be called first because it initializes all the
+// RegionMapSquare s in the list
+// TODO: if the tileId is not valid for the provided image, make sure it does not crash
+void RegionMap::readBkgImgBin() {
+ QFile binFile(region_map_bin_path);
+ if (!binFile.open(QIODevice::ReadOnly)) return;
+
+ QByteArray mapBinData = binFile.readAll();
+ binFile.close();
+
+ // the two is because lines are skipped for some reason
+ // (maybe that is because there could be multiple layers?)
+ // background image is also 32x20
+ for (int m = 0; m < img_height_; m++) {
+ for (int n = 0; n < img_width_; n++) {
+ RegionMapSquare square;// =
+ square.tile_img_id = mapBinData.at(n + m * img_width_ * 2);
+ map_squares.append(square);
+ }
+ }
+}
+
+void RegionMap::saveBkgImgBin() {
+ QByteArray data(4096,0);// use a constant here? maybe read the original size?
+
+ for (int m = 0; m < img_height_; m++) {
+ for (int n = 0; n < img_width_; n++) {
+ data[n + m * img_width_ * 2] = map_squares[n + m * img_width_].tile_img_id;
+ }
+ }
+
+ QFile file(region_map_bin_path);
+ if (!file.open(QIODevice::WriteOnly)) return;
+ file.write(data);
+ file.close();
+}
+
+// done
+void RegionMap::readLayout(QMap *qmap) {
+ QFile file(region_map_layout_path);
+ if (!file.open(QIODevice::ReadOnly)) return;
+
+ QMap * abbr = new QMap;
+
+ QString line, text;
+ QStringList *captured = new QStringList;
+
+ QTextStream in(&file);
+ while (!in.atEnd()) {
+ line = in.readLine();
+ if (line.startsWith("#define")) {
+ QStringList split = line.split(QRegularExpression("\\s+"));
+ abbr->insert(split[2].replace("MAPSEC_",""), split[1]);
+ } else {
+ text += line.remove(" ");
+ }
+ }
+ QRegularExpression re("{(.*?)}");
+ *captured = re.match(text).captured(1).split(",");
+ captured->removeAll({});
+
+ // replace abbreviations with names
+ for (int i = 0; i < captured->length(); i++) {
+ QString value = (*captured)[i];
+ if (value.startsWith("R(")) {// routes are different
+ captured->replace(i, QString("ROUTE_%1").arg(value.mid(2,3)));
+ } else {
+ captured->replace(i, abbr->key(value));
+ }
+ }
+
+ // TODO: improve this?
+ for (int m = 0, i = 0; m < layout_height_; m++) {
+ for (int n = 0; n < layout_width_; n++) {
+ i = img_index_(n,m);
+ QString secname = (*captured)[layout_index_(n,m)];
+ if (secname != "NOTHING") map_squares[i].has_map = true;
+ map_squares[i].map_name = qmap->value(mapSecToMapConstant(secname));
+ map_squares[i].x = n;
+ map_squares[i].y = m;
+ }
+ }
+ mapname_abbr = abbr;
+ layout_map_names = captured;
+ file.close();
+}
+
+// does it matter that it doesn't save in order?
+// do i need to use a QList ??
+void RegionMap::saveLayout() {
+ //
+ QString layout_text = "";
+ QString mapsec = "MAPSEC_";
+ QString define = "#define ";
+ QString array_start = "static const u8 sRegionMapLayout[] =\n{";
+ QString array_close = "\n};\n";
+ QString tab = " ";
+
+ for (QString key : mapname_abbr->keys()) {
+ layout_text += define + mapname_abbr->value(key) + tab + mapsec + key + "\n";
+ }
+
+ layout_text += "\n" + array_start;// + + array_close;//oops
+
+ //qDebug() << *layout_map_names;
+ int cnt = 0;
+ for (QString s : *layout_map_names) {
+ //
+ if (!(cnt % layout_width_)) {
+ layout_text += "\n" + tab;
+ }
+ if (s.startsWith("ROUTE_")) {
+ layout_text += QString("R(%1)").arg(s.replace("ROUTE_","")) + ", ";
+ } else {
+ layout_text += mapname_abbr->value(s) + ", ";
+ }
+ cnt++;
+ }
+
+ //layout_text.
+ layout_text += array_close;
+
+ QFile file(region_map_layout_path);
+ if (!file.open(QIODevice::WriteOnly)) return;
+ file.write(layout_text.toUtf8());
+ file.close();
+}
+
+void RegionMap::readCityMaps() {
+ //
+ //for (int m = 0; m < layout_height_; m++) {
+ // QString tester;
+ // for (int n = 0; n < layout_width_; n++) {
+ // tester += (QString::number(img_index_(n,m)).rightJustified(3, '.') + " ");
+ // }
+ // qDebug() << tester;
+ //}
+ //for (auto map : map_squares) {
+ for (int map = 0; map < map_squares.size(); map++) {
+ //
+ if (map_squares[map].has_map) {
+ //
+ if (ruby_city_maps_.contains(map_squares[map].map_name)) {
+ map_squares[map].has_city_map = true;
+ //map_squares[map].city_map_name = ruby_city_maps_.value(map_squares[map].map_name)[0].tilemap;
+ QList city_maps = ruby_city_maps_.value(map_squares[map].map_name);
+ for (auto city_map : city_maps) {
+ //
+ if (city_map.x == map_squares[map].x
+ && city_map.y == map_squares[map].y)
+ //
+ map_squares[map].city_map_name = city_map.tilemap;
+ }
+ }
+ }
+ }
+}
+
+//done
+QString RegionMap::newAbbr(QString mapname) {
+ QString abbr;
+ QStringList words = mapname.split("_");
+
+ if (words.length() == 1) {
+ abbr = (words[0] + "_____X").left(6);
+ } else {
+ abbr = (words.front() + "___X").left(4) + "_" + words.back().at(0);
+ }
+
+ // to guarantee unique abbreviations (up to 14)
+ QString extra_chars = "23456789BCDEF";
+ int count = 0;
+ while ((*mapname_abbr).values().contains(abbr)) {
+ abbr.replace(5,1,extra_chars[count]);
+ count++;
+ }
+ return abbr;
+}
+
+// layout coords to image index
+int RegionMap::img_index_(int x, int y) {
+ return ((x + 1) + (y + 2) * img_width_);
+}
+
+// layout coords to layout index
+int RegionMap::layout_index_(int x, int y) {
+ return (x + y * layout_width_);
+}
+
+// img coords to layout index?
+// img coords to img index?
+
+void RegionMap::test(QMap* qmap) {
+ //
+ bool debug_rmap = false;
+
+ if (debug_rmap) {
+ for (auto square : map_squares) {
+ qDebug() << "(" << square.x << "," << square.y << ")"
+ << square.tile_img_id
+ << square.has_map
+ << square.map_name
+ << square.has_city_map
+ << square.city_map_name
+ ;
+ //if (qmap->contains(mapSecToMapConstant(square.map_name)))
+ // extras += qmap->value(mapSecToMapConstant(square.map_name)) + " ";
+ //else
+ // extras += "nothing ";
+ }
+
+ QPixmap png(region_map_png_path);
+ //png.load(region_map_png_path);
+ qDebug() << "png num 8x8 tiles" << QString("0x%1").arg((png.width()/8) * (png.height() / 8), 2, 16, QChar('0'));
+ }
+
+}
+
+int RegionMap::width() {
+ return this->img_width_;
+}
+
+int RegionMap::height() {
+ return this->img_height_;
+}
+
+// TODO: remove +2 and put elsewhere
+QSize RegionMap::imgSize() {
+ return QSize(img_width_ * 8 + 2, img_height_ * 8 + 2);
+}
+
+// TODO: rename to getTileIdAt()?
+unsigned RegionMap::getTileId(int x, int y) {
+ //
+ return map_squares[x + y * img_width_].tile_img_id;
+ //qDebug() << x << y;
+ //return 0;
+}
+
+// sidenote: opening the map from MAPSEC_x will not always be right
+// there needs to be a mapsections to mapname QMap
+// otherwie, look for the first map with right substring
+// mapConstantsToMapNames [MAP_ROUTE106] = "Route106"
+// eg. SOUTHERN_ISLAND -> MAP_SOUTHERN_ISLAND -> SouthernIsland(n) -> SouthernIsland_Exterior
+// MT_CHIMNEY -> MAP_MT_CHIMNEY -> MtChimney(y)
+// ROUTE_101 -> MAP_ROUTE101 -> Route101(y)
+// (or synchronize these for consistency in the repos :: underscore / no underscore)
+
+// TODO: change debugs to logs
+void RegionMap::save() {
+ //
+ qDebug() << "saving region map image tilemap at" << region_map_bin_path << "\n"
+ ;//<< "saving region map layout at" << region_map_layout_path << "\n";
+
+ saveBkgImgBin();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/editor.cpp b/src/editor.cpp
index 5674721b..9cfce50e 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -19,12 +19,16 @@ Editor::Editor(Ui::MainWindow* ui)
this->settings = new Settings();
this->playerViewRect = new MovableRect(&this->settings->playerViewRectEnabled, 30 * 8, 20 * 8, qRgb(255, 255, 255));
this->cursorMapTileRect = new CursorTileRect(&this->settings->cursorTileRectEnabled, qRgb(255, 255, 255));
+ this->region_map = new RegionMap;// TODO: why is this here?
}
void Editor::saveProject() {
if (project) {
project->saveAllMaps();
project->saveAllDataStructures();
+ if (region_map) {
+ region_map->save();
+ }
}
}
@@ -33,6 +37,9 @@ void Editor::save() {
project->saveMap(map);
project->saveAllDataStructures();
}
+ if (project && region_map) {
+ region_map->save();
+ }
}
void Editor::undo() {
@@ -600,6 +607,9 @@ void Editor::displayMap() {
scene->addItem(this->playerViewRect);
scene->addItem(this->cursorMapTileRect);
+ displayRegionMapTileSelector();//?
+ displayRegionMap();
+
if (map_item) {
map_item->setVisible(false);
}
@@ -1261,6 +1271,93 @@ void Editor::deleteEvent(Event *event) {
//updateSelectedObjects();
}
+void Editor::loadRegionMapData() {
+ //
+ region_map->init(project);
+}
+
+// TODO: get this to display on a decent scale
+void Editor::displayRegionMapTileSelector() {
+ //
+ this->mapsquare_selector_item = new TilemapTileSelector(QPixmap(this->region_map->region_map_png_path));
+ this->mapsquare_selector_item->draw();
+
+ this->scene_region_map_tiles = new QGraphicsScene;
+ this->scene_region_map_tiles->addItem(this->mapsquare_selector_item);
+
+ connect(this->mapsquare_selector_item, &TilemapTileSelector::selectedTileChanged,
+ this, &Editor::onRegionMapTileSelectorSelectedTileChanged);// TODO: remove this?
+ connect(this->mapsquare_selector_item, &TilemapTileSelector::hoveredTileChanged,
+ this, &Editor::onRegionMapTileSelectorHoveredTileChanged);
+ connect(this->mapsquare_selector_item, &TilemapTileSelector::hoveredTileCleared,
+ this, &Editor::onRegionMapTileSelectorHoveredTileCleared);
+
+ this->ui->graphicsView_RegionMap_Tiles->setScene(this->scene_region_map_tiles);
+ this->ui->graphicsView_RegionMap_Tiles->setFixedSize(this->mapsquare_selector_item->pixelWidth + 2,
+ this->mapsquare_selector_item->pixelHeight + 2);
+}
+
+// TODO: change the signal slot to new syntax
+void Editor::displayRegionMap() {
+ //
+ this->region_map_item = new RegionMapPixmapItem(this->region_map, this->mapsquare_selector_item);
+ connect(region_map_item, SIGNAL(mouseEvent(QGraphicsSceneMouseEvent*, RegionMapPixmapItem*)),
+ this, SLOT(mouseEvent_region_map(QGraphicsSceneMouseEvent*, RegionMapPixmapItem*)));
+ connect(region_map_item, SIGNAL(hoveredRegionMapTileChanged(int, int)),
+ this, SLOT(onHoveredRegionMapTileChanged(int, int)));
+ connect(region_map_item, SIGNAL(hoveredRegionMapTileCleared()),
+ this, SLOT(onHoveredRegionMapTileCleared()));
+ this->region_map_item->draw();
+
+ this->scene_region_map_image = new QGraphicsScene;
+ this->scene_region_map_image->addItem(this->region_map_item);
+ this->scene_region_map_image->setSceneRect(this->scene_region_map_image->sceneRect());
+
+ //this->scene_region_map_image->scale(2, 2);
+ this->ui->graphicsView_Region_Map_BkgImg->setScene(this->scene_region_map_image);
+ this->ui->graphicsView_Region_Map_BkgImg->setFixedSize(this->region_map->imgSize());
+ //this->ui->graphicsView_Region_Map_BkgImg->scale(2.0, 2.0);
+}
+
+void Editor::onRegionMapTileSelectorSelectedTileChanged() {
+ //
+}
+
+void Editor::onRegionMapTileSelectorHoveredTileChanged(unsigned tileId) {
+ QString message = QString("Tile: 0x") + QString("%1").arg(tileId, 4, 16, QChar('0')).toUpper();
+ this->ui->statusBar->showMessage(message);
+}
+
+void Editor::onRegionMapTileSelectorHoveredTileCleared() {
+ //
+ QString message = QString("Selected Tile: 0x") + QString("%1").arg(this->mapsquare_selector_item->selectedTile, 4, 16, QChar('0')).toUpper();
+ this->ui->statusBar->showMessage(message);
+}
+
+void Editor::onHoveredRegionMapTileChanged(int x, int y) {
+ //
+ regionMapTabStatusbarMessage = QString("x: %1, y: %2 Tile: 0x").arg(x).arg(y) + QString("%1").arg(this->region_map->getTileId(x, y), 4, 16, QChar('0')).toUpper();
+ this->ui->statusBar->showMessage(regionMapTabStatusbarMessage);
+}
+
+void Editor::onHoveredRegionMapTileCleared() {
+ //
+ this->ui->statusBar->clearMessage();
+}
+
+void Editor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, RegionMapPixmapItem *item) {
+ //
+ if (event->buttons() & Qt::RightButton) {
+ //
+ item->select(event);
+ } else if (event->buttons() & Qt::MiddleButton) {
+ // TODO: add functionality here? replace or?
+ } else {
+ //
+ item->paint(event);
+ }
+}
+
// It doesn't seem to be possible to prevent the mousePress event
// from triggering both event's DraggablePixmapItem and the background mousePress.
// Since the DraggablePixmapItem's event fires first, we can set a temp
@@ -1274,6 +1371,5 @@ void Editor::objectsView_onMousePress(QMouseEvent *event) {
selected_events->append(first);
updateSelectedEvents();
}
-
selectingEvent = false;
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 982f3be8..0bf6e874 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -263,11 +263,13 @@ bool MainWindow::openProject(QString dir) {
setWindowTitle(editor->project->getProjectTitle());
loadDataStructures();
populateMapList();
+ editor->loadRegionMapData();
success = setMap(getDefaultMap(), true);
} else {
setWindowTitle(editor->project->getProjectTitle());
loadDataStructures();
populateMapList();
+ editor->loadRegionMapData();
}
if (success) {
@@ -596,6 +598,11 @@ void MainWindow::on_checkBox_AllowEscapeRope_clicked(bool checked)
}
}
+void MainWindow::on_tabWidget_Region_Map_currentChanged(int index) {
+ //
+ ui->stackedWidget_RM_Options->setCurrentIndex(index);
+}
+
void MainWindow::loadDataStructures() {
Project *project = editor->project;
project->readMapLayouts();
diff --git a/src/ui/regionmappixmapitem.cpp b/src/ui/regionmappixmapitem.cpp
new file mode 100644
index 00000000..4c751898
--- /dev/null
+++ b/src/ui/regionmappixmapitem.cpp
@@ -0,0 +1,73 @@
+#include "regionmappixmapitem.h"
+#include "imageproviders.h"
+
+
+
+// the function that draws the map on the scene
+// (qnqlogous to Map::render)
+// TODO: figure out why this is being called twice!!
+void RegionMapPixmapItem::draw() {
+ if (!region_map) return;
+
+ QImage image(region_map->width() * 8, region_map->height() * 8, QImage::Format_RGBA8888);
+
+ QPainter painter(&image);
+ for (int i = 0; i < region_map->map_squares.size(); i++) {
+ QImage img = this->tile_selector->tileImg(region_map->map_squares[i].tile_img_id);
+ int x = i % region_map->width();
+ int y = i / region_map->width();
+ QPoint pos = QPoint(x * 8, y * 8);
+ painter.drawImage(pos, img);
+ }
+ painter.end();
+
+ this->setPixmap(QPixmap::fromImage(image));
+}
+
+void RegionMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
+ if (region_map) {
+ if (event->type() == QEvent::GraphicsSceneMousePress) {
+ } else {
+ QPointF pos = event->pos();
+ int x = static_cast(pos.x()) / 8;
+ int y = static_cast(pos.y()) / 8;
+ this->region_map->map_squares[x + y * region_map->width()].tile_img_id = this->tile_selector->selectedTile;
+ }
+ draw();
+ }
+}
+
+void RegionMapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
+ QPointF pos = event->pos();
+ int x = static_cast(pos.x()) / 8;
+ int y = static_cast(pos.y()) / 8;
+ this->tile_selector->select(this->region_map->getTileId(x, y));
+}
+
+void RegionMapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
+ int x = static_cast(event->pos().x()) / 8;
+ int y = static_cast(event->pos().y()) / 8;
+ emit this->hoveredRegionMapTileChanged(x, y);
+}
+
+void RegionMapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
+ emit this->hoveredRegionMapTileCleared();
+}
+
+void RegionMapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+ QPointF pos = event->pos();
+ int x = static_cast(pos.x()) / 8;
+ int y = static_cast(pos.y()) / 8;
+ emit mouseEvent(event, this);
+}
+
+void RegionMapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+ int x = static_cast(event->pos().x()) / 8;
+ int y = static_cast(event->pos().y()) / 8;
+ emit this->hoveredRegionMapTileChanged(x, y);
+ emit mouseEvent(event, this);
+}
+
+void RegionMapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+ emit mouseEvent(event, this);
+}
diff --git a/src/ui/tilemaptileselector.cpp b/src/ui/tilemaptileselector.cpp
new file mode 100644
index 00000000..b109ceb2
--- /dev/null
+++ b/src/ui/tilemaptileselector.cpp
@@ -0,0 +1,112 @@
+#include "tilemaptileselector.h"
+
+#include
+
+void TilemapTileSelector::draw() {
+ size_t width_ = this->pixmap.width();
+ this->pixelWidth = width_;
+ size_t height_ = this->pixmap.height();
+ this->pixelHeight = height_;
+ size_t ntiles_ = (width_/8) * (height_/8);// length_
+
+ this->numTilesWide = width_ / 8;
+ this->numTiles = ntiles_;
+
+ this->setPixmap(this->pixmap);
+ this->drawSelection();
+}
+
+//*
+void TilemapTileSelector::select(unsigned tileId) {
+ QPoint coords = this->getTileIdCoords(tileId);
+ SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
+ this->selectedTile = tileId;
+ emit selectedTileChanged(tileId);
+}
+//*/
+
+//*
+void TilemapTileSelector::updateSelectedTile() {
+ QPoint origin = this->getSelectionStart();
+ this->selectedTile = this->getTileId(origin.x(), origin.y());
+}
+//*/
+
+unsigned TilemapTileSelector::getSelectedTile() {
+ return this->selectedTile;
+}
+
+//*
+unsigned TilemapTileSelector::getTileId(int x, int y) {
+ int index = y * this->numTilesWide + x;
+ return index < this->numTiles ? index : this->numTiles % index;
+}
+//*/
+
+//*
+void TilemapTileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+ SelectablePixmapItem::mousePressEvent(event);
+ this->updateSelectedTile();
+ emit selectedTileChanged(this->selectedTile);
+}
+//*/
+
+//*
+void TilemapTileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+ SelectablePixmapItem::mouseMoveEvent(event);
+ this->updateSelectedTile();
+ emit hoveredTileChanged(this->selectedTile);
+ emit selectedTileChanged(this->selectedTile);
+}
+//*/
+
+//*
+void TilemapTileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+ SelectablePixmapItem::mouseReleaseEvent(event);
+ this->updateSelectedTile();
+ emit selectedTileChanged(this->selectedTile);
+}
+//*/
+
+//*
+void TilemapTileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
+ QPoint pos = this->getCellPos(event->pos());
+ unsigned tileId = this->getTileId(pos.x(), pos.y());
+ emit this->hoveredTileChanged(tileId);
+}
+//*/
+
+//*
+void TilemapTileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) {
+ emit this->hoveredTileCleared();
+}
+//*/
+
+//*
+QPoint TilemapTileSelector::getTileIdCoords(unsigned tileId) {
+ int index = tileId < this->numTiles ? tileId : this->numTiles % tileId;// TODO: change this?
+ return QPoint(index % this->numTilesWide, index / this->numTilesWide);// ? is this right?
+}
+//*/
+
+QImage TilemapTileSelector::tileImg(unsigned tileId) {
+ //
+ QPoint pos = getTileIdCoords(tileId);
+ return pixmap.copy(pos.x() * 8, pos.y() * 8, 8, 8).toImage();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+