diff --git a/forms/regionmapeditor.ui b/forms/regionmapeditor.ui
index 88856e07..517e6e0c 100644
--- a/forms/regionmapeditor.ui
+++ b/forms/regionmapeditor.ui
@@ -6,8 +6,8 @@
0
0
- 829
- 644
+ 957
+ 535
@@ -15,98 +15,94 @@
- -
-
-
-
-
-
-
- 30
- 50
-
-
-
-
- 30
- 160
-
-
-
- Qt::StrongFocus
-
-
- 10
-
-
- 100
-
-
- 30
-
-
- Qt::Vertical
-
-
- QSlider::NoTicks
-
-
- 1
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
- 30
- 0
-
-
-
-
- 30
- 160
-
-
-
- Qt::StrongFocus
-
-
- 10
-
-
- 100
-
-
- 30
-
-
- Qt::Vertical
-
-
- QSlider::NoTicks
-
-
- 1
-
-
-
-
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Region
+
+
+
+ -
+
+
+ QComboBox::AdjustToContents
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Crop View to Map Size
+
+
+ false
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 169
+ 20
+
+
+
+
+
+
- -
+
-
-
@@ -158,12 +154,909 @@
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ false
+
+
+
+
+ 393
+ 251
+
+
+
+ 0
+
+
+
+ Background Image
+
+
+
-
+
+
+
+ 1
+ 1
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 466
+ 350
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ false
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ QGraphicsView::NoDrag
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 16
+ 166
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 166
+ 16
+
+
+
+
+
+
+
+
+
+
+
+
+ Map Layout
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 466
+ 350
+
+
+
+
+ 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 Entries
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 466
+ 350
+
+
+
+
+ 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 320
+ 200
+
+
+
+ 0
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 162
+ 162
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ true
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+ true
+
+
+
+ 8
+ 0
+ 278
+ 341
+
+
+
+
+ 0
+ 0
+
+
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::Panel
+
+
+ QFrame::Sunken
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ h-flip
+
+
+
+ -
+
+
+ v-flip
+
+
+
+ -
+
+
+ 15
+
+
+
+ -
+
+
+ palette
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 300
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 1
+
+
+
-
+
+
+
-
+
+
+ Layer
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ QLayout::SetNoConstraint
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ <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
+
+
+
+ -
+
+
+ Map Section
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Delete Square
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ -
+
+
+ Layout Height
+
+
+
+ -
+
+
+ Layout Width
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 300
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 1
+
+
+
-
+
+
+ QLayout::SetNoConstraint
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ width
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ height
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ <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
+
+
+
+ -
+
+
+ Dimensions
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ x
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ y
+
+
+
+
+
+
+ -
+
+
+ Location
+
+
+
+ -
+
+
+ Map Section
+
+
+
+ -
+
+
+ Map Name
+
+
+
+ -
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
-
-
+
30
- 0
+ 50
@@ -195,1140 +1088,21 @@
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
- -
-
-
- Qt::Vertical
-
-
- false
-
-
-
- Qt::Horizontal
-
-
- false
-
-
-
-
- 393
- 251
-
-
-
- 0
-
-
-
- Background Image
-
-
-
-
-
-
-
- 1
- 1
-
-
-
- true
-
-
-
-
- 0
- 0
- 350
- 225
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 166
- 16
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- false
-
-
- false
-
-
- QAbstractScrollArea::AdjustIgnored
-
-
- QGraphicsView::NoDrag
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 16
- 166
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 16
- 166
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 166
- 16
-
-
-
-
-
-
-
-
-
-
-
-
- Map Layout
-
-
- -
-
-
-
- 1
- 0
-
-
-
- true
-
-
-
-
- 0
- 0
- 350
- 225
-
-
-
-
- 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 Entries
-
-
- -
-
-
-
- 1
- 0
-
-
-
- true
-
-
-
-
- 0
- 0
- 350
- 225
-
-
-
-
- 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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 320
- 200
-
-
-
- 0
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 162
- 162
-
-
-
- Qt::ScrollBarAlwaysOn
-
-
- Qt::ScrollBarAsNeeded
-
-
- QAbstractScrollArea::AdjustIgnored
-
-
- true
-
-
- Qt::AlignHCenter|Qt::AlignTop
-
-
-
- true
-
-
-
- 8
- 0
- 278
- 262
-
-
-
-
- 0
- 0
-
-
-
-
- QLayout::SetDefaultConstraint
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
- Qt::ScrollBarAlwaysOff
-
-
- Qt::ScrollBarAlwaysOff
-
-
- QAbstractScrollArea::AdjustIgnored
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- false
-
-
-
- 0
- 0
-
-
-
-
- 300
- 0
-
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
- 1
-
-
-
-
-
-
- QLayout::SetNoConstraint
-
-
-
-
-
- Map Section
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- <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
-
-
- QComboBox::NoInsert
-
-
-
- -
-
-
- Map Name
-
-
-
- -
-
-
- true
-
-
-
- -
-
-
- City Map
-
-
-
- -
-
-
- <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
-
-
-
-
-
- -
-
-
- Delete Square
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
-
- 300
- 0
-
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
- 1
-
-
-
-
-
-
- QLayout::SetNoConstraint
-
-
-
-
-
- Map Section
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
- <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
-
-
- QComboBox::NoInsert
-
-
-
- -
-
-
- Location
-
-
-
- -
-
-
- Dimensions
-
-
-
- -
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
-
-
-
- x
-
-
-
- -
-
-
- -
-
-
- -
-
-
- y
-
-
-
-
-
-
- -
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
-
-
-
- width
-
-
-
- -
-
-
- -
-
-
- -
-
-
- height
-
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
-
-
-
-
-
- Qt::Horizontal
-
-
- false
-
-
-
-
- QLayout::SetDefaultConstraint
-
- -
-
-
-
-
-
- City Map:
-
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
- <html><head/><body><p>Add a new city map.</p></body></html>
-
-
-
-
-
-
- :/icons/add.ico
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
-
- 1
- 0
-
-
-
-
- 102
- 102
-
-
-
- true
-
-
-
-
- 0
- 0
- 441
- 230
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 166
- 16
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 16
- 166
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- false
-
-
- false
-
-
- QAbstractScrollArea::AdjustIgnored
-
-
- QGraphicsView::NoDrag
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 16
- 166
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 166
- 16
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 82
- 82
-
-
-
- Qt::ScrollBarAlwaysOn
-
-
- Qt::ScrollBarAsNeeded
-
-
- QAbstractScrollArea::AdjustIgnored
-
-
- true
-
-
- Qt::AlignHCenter|Qt::AlignTop
-
-
-
- true
-
-
-
- 8
- 0
- 255
- 274
-
-
-
-
- 0
- 0
-
-
-
-
- QLayout::SetDefaultConstraint
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
- Qt::ScrollBarAlwaysOff
-
-
- Qt::ScrollBarAlwaysOff
-
-
- QAbstractScrollArea::AdjustIgnored
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
@@ -1433,6 +1205,13 @@
+
+
+ NoScrollComboBox
+ QWidget
+
+
+
diff --git a/forms/regionmappropertiesdialog.ui b/forms/regionmappropertiesdialog.ui
new file mode 100644
index 00000000..7b627774
--- /dev/null
+++ b/forms/regionmappropertiesdialog.ui
@@ -0,0 +1,729 @@
+
+
+ RegionMapPropertiesDialog
+
+
+
+ 0
+ 0
+ 564
+ 1016
+
+
+
+
+ 0
+ 0
+
+
+
+ Region Map Properties
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+ -
+
+
+ alias
+
+
+
+ -
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ Tilemap Properties
+
+
+
-
+
+
+ format
+
+
+
+ -
+
+
-
+
+ plain
+
+
+ -
+
+ 4bpp
+
+
+ -
+
+ 8bpp
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ width
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+ 255
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ height
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+ 255
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ tileset path
+
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 350
+ 0
+
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ tilemap path
+
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+ -
+
+
+ palette path
+
+
+
+
+
+
+ -
+
+
+ Layout Properties
+
+
+ true
+
+
+
-
+
+
+ format
+
+
+
+ -
+
+
-
+
+ C array
+
+
+ -
+
+ binary
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+ layout path
+
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ width
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+ 0
+
+
+ 255
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ left offset
+
+
+
+ -
+
+
+ 255
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 85
+ 2
+
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ height
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+ 0
+
+
+ 255
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 87
+ 13
+
+
+
+
+ -
+
+
+ top offset
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 87
+ 13
+
+
+
+
+
+
+
+ -
+
+
+ color: #ff5c33
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+ -
+
+
+ width
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+
+ -
+
+
+ height
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ RegionMapPropertiesDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ RegionMapPropertiesDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/include/core/regionmap.h b/include/core/regionmap.h
index 03059266..f16f35f2 100644
--- a/include/core/regionmap.h
+++ b/include/core/regionmap.h
@@ -3,7 +3,6 @@
#define REGIONMAP_H
#include "map.h"
-#include "project.h"
#include "tilemaptileselector.h"
#include "history.h"
@@ -15,6 +14,11 @@
#include
#include
+#include
+using std::shared_ptr;
+
+class Project;
+
enum RegionMapEditorBox {
BackgroundImage = 1,
CityMapImage = 2,
@@ -41,71 +45,44 @@ public:
~RegionMapHistoryItem() {}
};
-class RegionMapEntry
+struct LayoutSquare
{
-public:
- RegionMapEntry()=default;
- RegionMapEntry(int x_, int y_, int width_, int height_, QString name_) {
- this-> x = x_;
- this-> y = y_;
- this-> width = width_;
- this-> height = height_;
- this-> name = name_;
- }
+ QString map_section;
int x;
int y;
- int width;
- int height;
- QString name;
-
- void setX(int);
- void setY(int);
- void setWidth(int);
- void setHeight(int);
+ bool has_map = false;
};
-class RegionMapSquare
+struct MapSectionEntry
{
-public:
- int x = -1;
- int y = -1;
- uint8_t tile_img_id = 0x00;
- uint8_t secid = 0x00;
- bool has_map = false;
- bool has_city_map = false;
- bool duplicated = false;
- QString map_name;
- QString mapsec;
- QString city_map_name;
+ QString name = "";
+ int x = 0;
+ int y = 0;
+ int width = 1;
+ int height = 1;
+ bool valid = false;
};
class RegionMap
{
public:
- RegionMap() = default;
+ RegionMap() = delete;
+ RegionMap(Project *);
Project *project = nullptr;
- QVector map_squares;
- History history;
+ History history; // TODO
- QMap sMapNamesMap;
- QMap mapSecToMapEntry;
- QVector sMapNames;
+ bool loadMapData(poryjson::Json);
+ bool loadTilemap(poryjson::Json);
+ bool loadLayout(poryjson::Json);
+ bool loadEntries();
- const int padLeft = 1;
- const int padRight = 3;
- const int padTop = 2;
- const int padBottom = 3;
-
- bool init(Project*);
-
- bool readBkgImgBin();
- bool readLayout();
+ void setEntries(tsl::ordered_map *entries) { this->region_map_entries = entries; }
+ MapSectionEntry getEntry(QString section);
void save();
- void saveTileImages();
- void saveBkgImgBin();
+ void saveTilemap();
void saveLayout();
void saveOptions(int id, QString sec, QString name, int x, int y);
@@ -115,38 +92,115 @@ public:
void clearImage();
void replaceSectionId(unsigned oldId, unsigned newId);
- int width();
- int height();
- QSize imgSize();
+ unsigned getTileId(int index);
+ shared_ptr getTile(int index);
unsigned getTileId(int x, int y);
+ shared_ptr getTile(int x, int y);
+ bool squareHasMap(int index);
+ QString squareMapSection(int index);
+ int squareX(int index);
+ int squareY(int index);
+ bool squareInLayout(int x, int y);
+ int firstLayoutIndex() { return this->offset_left + this->offset_top * this->tilemap_width; }
+
+ void setTileId(int index, unsigned id);
+ void setTile(int index, TilemapTile &tile);
+ void setTileData(int index, unsigned id, bool hFlip, bool vFlip, int palette);
int getMapSquareIndex(int x, int y);
+
+ QString palPath();
QString pngPath();
- void setTemporaryPngPath(QString);
QString cityTilesPath();
- void setTemporaryCityTilesPath(QString);
+ QString entriesPath() { return this->entries_path; }
QVector getTiles();
void setTiles(QVector tileIds);
+ QStringList getLayers() { return this->layout_layers; }
+ void setLayer(QString layer) { this->current_layer = layer; }
+ QString getLayer() { return this->current_layer; }
+
QString fixCase(QString);
-private:
- int layout_width_;
- int layout_height_;
- int img_width_;
- int img_height_;
+ int padLeft() { return this->offset_left; }
+ int padTop() { return this->offset_top; }
+ int padRight() { return this->tilemap_width - this->layout_width - this->offset_left; }
+ int padBottom() { return this->tilemap_height - this->layout_height - this->offset_top; }
- QString region_map_png_path;
- QString region_map_bin_path;
- QString region_map_entries_path;
- QString region_map_layout_bin_path;
+ int tilemapWidth() { return this->tilemap_width; }
+ int tilemapHeight() { return this->tilemap_height; }
+ int tilemapSize() { return this->tilemap_width * this->tilemap_height; }
+ int tilemapBytes();
+
+ int tilemapToLayoutIndex(int index);
+
+ TilemapFormat tilemapFormat() { return this->tilemap_format; }
+
+ int pixelWidth() { return this->tilemap_width * 8; }
+ int pixelHeight() { return this->tilemap_height * 8; }
+
+ QString fullPath(QString local);
+
+private:
+
+ tsl::ordered_map *region_map_entries = nullptr;
+
+ QString alias;
+
+ int tilemap_width;
+ int tilemap_height;
+
+ // default is 32x20 (or 30x20 / screen size??)
+ int region_width;
+ int region_height;
+
+ // default is 28x15
+ int layout_width;
+ int layout_height;
+
+ int offset_left;
+ int offset_top;
+ //int ;
+ //int img_height_;
+
+ TilemapFormat tilemap_format;
+
+ enum class LayoutFormat { None, Binary, CArray };
+ LayoutFormat layout_format;
+
+ QString tileset_path;
+ QString tilemap_path;
+ QString palette_path = "";
+
+ QString entries_path;
+ QString layout_path;
+
+ // TODO: default values?
+ QString layout_array_label;
+ bool layout_uses_layers = false;
+ //QList layout_layers;
+
+ //QList map_squares;
+ QList> tilemap;
+
+ // what about separate array for layout
+ // and a pointer to an entries / map sections object (from project? or editor?)
+ QStringList layout_layers;
+ QString current_layer;
+
+ // TODO: qstring, or {section name, x, y, section_id, has_map}
+ QMap> layouts; // key: layer, value: layout list
+
+ // TODO
QString city_map_tiles_path;
+ // todo: no???? why would i be doing this it's pointless
+ // let the user figure this shit out
bool region_map_png_needs_saving = false;
bool city_map_png_needs_saving = false;
- int img_index_(int x, int y);
- int layout_index_(int x, int y);
+ int get_tilemap_index(int x, int y);
+ int get_layout_index(int x, int y);
};
#endif // REGIONMAP_H
diff --git a/include/project.h b/include/project.h
index a081733b..97730481 100644
--- a/include/project.h
+++ b/include/project.h
@@ -9,6 +9,7 @@
#include "wildmoninfo.h"
#include "parseutil.h"
#include "orderedjson.h"
+#include "regionmap.h"
#include
#include
diff --git a/include/ui/regionmapeditor.h b/include/ui/regionmapeditor.h
index 1dee23f7..32c74adc 100644
--- a/include/ui/regionmapeditor.h
+++ b/include/ui/regionmapeditor.h
@@ -6,6 +6,8 @@
#include "regionmaplayoutpixmapitem.h"
#include "regionmapentriespixmapitem.h"
#include "regionmap.h"
+#include "orderedjson.h"
+#include "project.h"
#include
#include
@@ -24,9 +26,10 @@ public:
explicit RegionMapEditor(QWidget *parent = 0, Project *pro = nullptr);
~RegionMapEditor();
- RegionMap *region_map;
+ RegionMap *region_map = nullptr;
+ tsl::ordered_map region_maps;
- bool loadRegionMapData();
+ bool load();
bool loadCityMaps();
void setCurrentSquareOptions();
@@ -56,9 +59,11 @@ private:
Ui::RegionMapEditor *ui;
Project *project;
+ poryjson::Json rmConfigJson;
+
History history;
- int currIndex;
+ int currIndex = 0;
unsigned selectedCityTile;
unsigned selectedImageTile;
QString activeEntry;
@@ -86,6 +91,17 @@ private:
RegionMapPixmapItem *region_map_item = nullptr;
CityMapPixmapItem *city_map_item = nullptr;
+ bool loadRegionMapEntries();
+ bool saveRegionMapEntries();
+ tsl::ordered_map region_map_entries;
+
+ void buildConfigDialog();
+ poryjson::Json configRegionMapDialog();
+ void buildUpdateConfigDialog();
+ poryjson::Json buildDefaultJson();
+ poryjson::Json getJsonFromAlias(QString alias);
+ bool loadRegionMapData();
+
void initShortcuts();
void displayRegionMap();
void displayRegionMapImage();
@@ -94,11 +110,11 @@ private:
void displayRegionMapLayoutOptions();
void updateRegionMapLayoutOptions(int index);
void displayRegionMapTileSelector();
+ void updateLayerDisplayed();
void displayCityMapTileSelector();
void displayCityMap(QString name);
void displayRegionMapEntryOptions();
void updateRegionMapEntryOptions(QString);
- void importTileImage(bool city = false);
bool createCityMap(QString name);
bool tryInsertNewMapEntry(QString);
@@ -114,21 +130,22 @@ private slots:
void on_action_RegionMap_ClearImage_triggered();
void on_action_RegionMap_ClearLayout_triggered();
void on_action_Swap_triggered();
- void on_action_Import_RegionMap_ImageTiles_triggered();
- void on_action_Import_CityMap_ImageTiles_triggered();
void on_tabWidget_Region_Map_currentChanged(int);
void on_pushButton_RM_Options_delete_clicked();
void on_comboBox_RM_ConnectedMap_textActivated(const QString &);
void on_comboBox_RM_Entry_MapSection_textActivated(const QString &);
+ void on_comboBox_regionSelector_textActivated(const QString &);
+ void on_comboBox_layoutLayer_textActivated(const QString &);
void on_spinBox_RM_Entry_x_valueChanged(int);
void on_spinBox_RM_Entry_y_valueChanged(int);
void on_spinBox_RM_Entry_width_valueChanged(int);
void on_spinBox_RM_Entry_height_valueChanged(int);
+ void on_spinBox_tilePalette_valueChanged(int);
+ void on_checkBox_tileHFlip_stateChanged(int);
+ void on_checkBox_tileVFlip_stateChanged(int);
void on_pushButton_CityMap_add_clicked();
void on_verticalSlider_Zoom_Map_Image_valueChanged(int);
void on_verticalSlider_Zoom_Image_Tiles_valueChanged(int);
- void on_verticalSlider_Zoom_City_Map_valueChanged(int);
- void on_verticalSlider_Zoom_City_Tiles_valueChanged(int);
void on_comboBox_CityMap_picker_currentTextChanged(const QString &);
void on_lineEdit_RM_MapName_textEdited(const QString &);
void onHoveredRegionMapTileChanged(int x, int y);
diff --git a/include/ui/regionmappropertiesdialog.h b/include/ui/regionmappropertiesdialog.h
new file mode 100644
index 00000000..6097d842
--- /dev/null
+++ b/include/ui/regionmappropertiesdialog.h
@@ -0,0 +1,47 @@
+#ifndef REGIONMAPPROPERTIESDIALOG_H
+#define REGIONMAPPROPERTIESDIALOG_H
+
+#include "orderedjson.h"
+
+#include
+#include
+
+class Project;
+
+namespace Ui {
+class RegionMapPropertiesDialog;
+}
+
+class RegionMapPropertiesDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit RegionMapPropertiesDialog(QWidget *parent = nullptr);
+ ~RegionMapPropertiesDialog();
+
+ void setProject(Project *project) { this->project = project; }
+
+ void setProperties(poryjson::Json object);
+ poryjson::Json saveToJson();
+
+ virtual void accept() override;
+
+private:
+ Ui::RegionMapPropertiesDialog *ui;
+ Project *project = nullptr;
+
+ void hideMessages();
+
+ QString browse(QString filter, QFileDialog::FileMode mode);
+
+private slots:
+ void on_browse_tilesetImagePath_clicked();
+ void on_browse_tilemapBinPath_clicked();
+ void on_browse_tilemapPalettePath_clicked();
+ void on_browse_layoutPath_clicked();
+
+ //void on_buttonBox_accepted();
+};
+
+#endif // REGIONMAPPROPERTIESDIALOG_H
diff --git a/include/ui/tilemaptileselector.h b/include/ui/tilemaptileselector.h
index 95650e4b..ab266fbc 100644
--- a/include/ui/tilemaptileselector.h
+++ b/include/ui/tilemaptileselector.h
@@ -1,29 +1,146 @@
+#pragma once
#ifndef TILEMAPTILESELECTOR_H
#define TILEMAPTILESELECTOR_H
#include "selectablepixmapitem.h"
+#include "paletteutil.h"
+
+#include
+using std::shared_ptr;
+
+enum class TilemapFormat { Plain, BPP_4, BPP_8 };
+
+class TilemapTile {
+ unsigned raw_ = 0;
+ unsigned id_ = 0;
+ bool hFlip_ = false;
+ bool vFlip_ = false;
+ int palette_ = 0;
+
+protected:
+ TilemapTile(unsigned raw, unsigned id, bool hFlip, bool vFlip, int palette) : raw_(raw), id_(id), hFlip_(hFlip), vFlip_(vFlip), palette_(palette) {}
+ virtual ~TilemapTile() {}
+
+public:
+ TilemapTile()=default;
+
+ TilemapTile(TilemapTile &other) {
+ this->raw_ = other.raw();
+ this->id_ = other.id();
+ this->hFlip_ = other.hFlip();
+ this->vFlip_ = other.vFlip();
+ this->palette_ = other.palette();
+ }
+
+ TilemapTile &operator=(const TilemapTile &other) {
+ this->raw_ = other.raw();
+ this->id_ = other.id();
+ this->hFlip_ = other.hFlip();
+ this->vFlip_ = other.vFlip();
+ this->palette_ = other.palette();
+ return *this;
+ }
+
+ virtual void copy(TilemapTile &other) {
+ this->raw_ = other.raw();
+ this->id_ = other.id();
+ this->hFlip_ = other.hFlip();
+ this->vFlip_ = other.vFlip();
+ this->palette_ = other.palette();
+ }
+
+ virtual unsigned raw() const { return this->raw_; }
+ virtual unsigned id() const { return this->id_; }
+ virtual bool hFlip() const { return this->hFlip_; }
+ virtual bool vFlip() const { return this->vFlip_; }
+ virtual int palette() const { return this->palette_; }
+
+ virtual void setId(unsigned id) { this->id_ = id; }
+ virtual void setHFlip(bool hFlip) { this->hFlip_ = hFlip; }
+ virtual void setVFlip(bool vFlip) { this->vFlip_ = vFlip; }
+ virtual void setPalette(int palette) { this->palette_ = palette; }
+
+ virtual QString info() {
+ return QString("Tile: 0x") + QString("%1 ").arg(this->id(), 4, 16, QChar('0')).toUpper();
+ }
+};
+
+class PlainTile : public TilemapTile {
+public:
+ PlainTile(unsigned raw) : TilemapTile(raw, raw, false, false, 0) {}
+
+ ~PlainTile() {}
+};
+
+class BPP4Tile : public TilemapTile {
+public:
+ BPP4Tile(unsigned raw) : TilemapTile(
+ raw,
+ raw & 0x3ff, // tileId
+ !!(raw & 0x0400), // hFlip
+ !!(raw & 0x0800), // vFlip
+ (raw & 0xf000) >> 12 // palette
+ ) {}
+
+ ~BPP4Tile() {}
+
+ virtual QString info() override {
+ return TilemapTile::info() + QString("hFlip: %1 vFlip: %2 palette: %3").arg(this->hFlip()).arg(this->vFlip()).arg(this->palette());
+ }
+};
+
+class BPP8Tile : public TilemapTile {
+public:
+ BPP8Tile(unsigned raw) : TilemapTile(
+ raw,
+ raw & 0x3ff, // tileId
+ !!(raw & 0x0400), // hFlip
+ !!(raw & 0x0800), // vFlip
+ 0 // palette
+ ) {}
+
+ ~BPP8Tile() {}
+
+ virtual QString info() override {
+ return TilemapTile::info() + QString("hFlip: %1 vFlip: %2").arg(this->hFlip()).arg(this->vFlip());
+ }
+};
class TilemapTileSelector: public SelectablePixmapItem {
Q_OBJECT
public:
- TilemapTileSelector(QPixmap pixmap_): SelectablePixmapItem(8, 8, 1, 1) {
- this->tilemap = pixmap_;
- this->setPixmap(this->tilemap);
- this->numTilesWide = tilemap.width() / 8;
+ TilemapTileSelector(QString tilesetFilepath, TilemapFormat format, QString palFilepath): SelectablePixmapItem(8, 8, 1, 1) {
+ this->tileset = QImage(tilesetFilepath);
+ this->format = format;
+ bool err;
+ this->palette = PaletteUtil::parse(palFilepath, &err);
+ this->setPixmap(QPixmap::fromImage(this->tileset));
+ this->numTilesWide = this->tileset.width() / 8;
this->selectedTile = 0x00;
setAcceptHoverEvents(true);
}
void draw();
- void select(unsigned tileId);
- unsigned getSelectedTile();
+ void setPalette();
int pixelWidth;
int pixelHeight;
+ void select(unsigned tileId);
unsigned selectedTile = 0;
- QPixmap tilemap;
- QImage tileImg(unsigned tileId);
+ void selectVFlip(bool hFlip) { this->tile_hFlip = hFlip; }
+ bool tile_hFlip = false;
+
+ void selectHFlip(bool vFlip) { this->tile_vFlip = vFlip; }
+ bool tile_vFlip = false;
+
+ void selectPalette(int palette) { this->tile_palette = palette; }
+ int tile_palette = 0;
+
+ QImage tileset;
+ TilemapFormat format = TilemapFormat::Plain;
+ QList palette;
+ QImage tileImg(shared_ptr tile);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent*);
diff --git a/porymap.pro b/porymap.pro
index b73c4ee6..2a86653e 100644
--- a/porymap.pro
+++ b/porymap.pro
@@ -77,6 +77,7 @@ SOURCES += src/core/block.cpp \
src/ui/shortcutseditor.cpp \
src/ui/multikeyedit.cpp \
src/ui/preferenceeditor.cpp \
+ src/ui/regionmappropertiesdialog.cpp \
src/config.cpp \
src/editor.cpp \
src/main.cpp \
@@ -151,6 +152,7 @@ HEADERS += include/core/block.h \
include/ui/shortcutseditor.h \
include/ui/multikeyedit.h \
include/ui/preferenceeditor.h \
+ include/ui/regionmappropertiesdialog.h \
include/config.h \
include/editor.h \
include/mainwindow.h \
@@ -169,11 +171,13 @@ FORMS += forms/mainwindow.ui \
forms/newtilesetdialog.ui \
forms/mapimageexporter.ui \
forms/shortcutseditor.ui \
- forms/preferenceeditor.ui
+ forms/preferenceeditor.ui \
+ forms/regionmappropertiesdialog.ui
RESOURCES += \
resources/images.qrc \
- resources/themes.qrc
+ resources/themes.qrc \
+ resources/text.qrc
INCLUDEPATH += include
INCLUDEPATH += include/core
diff --git a/resources/icons/empty_cross_cursor.ico b/resources/icons/empty_cross_cursor.ico
new file mode 100644
index 00000000..01b03b54
Binary files /dev/null and b/resources/icons/empty_cross_cursor.ico differ
diff --git a/resources/icons/pencil_bw.ico b/resources/icons/pencil_bw.ico
new file mode 100644
index 00000000..7d79243b
Binary files /dev/null and b/resources/icons/pencil_bw.ico differ
diff --git a/resources/text.qrc b/resources/text.qrc
new file mode 100644
index 00000000..211598e4
--- /dev/null
+++ b/resources/text.qrc
@@ -0,0 +1,7 @@
+
+
+ text/region_map_default_emerald.json
+ text/region_map_default_firered.json
+ text/region_map_default_ruby.json
+
+
diff --git a/resources/text/region_map_default_emerald.json b/resources/text/region_map_default_emerald.json
new file mode 100644
index 00000000..a25e459c
--- /dev/null
+++ b/resources/text/region_map_default_emerald.json
@@ -0,0 +1,40 @@
+{
+ "region_maps": [
+ {
+ "alias": "hoenn",
+ "width": 32,
+ "height": 20,
+ "tilemap": {
+ "width": 64,
+ "height": 64,
+ "format": "plain",
+ "tileset_path": "graphics/pokenav/region_map.png",
+ "tilemap_path": "graphics/pokenav/region_map_map.bin"
+ },
+ "layout": {
+ "width": 28,
+ "height": 15,
+ "offset_left": 1,
+ "offset_top": 2,
+ "format": "binary",
+ "path": "graphics/pokenav/region_map_section_layout.bin"
+ }
+ },
+ {
+ "alias": "pokedex area screen",
+ "width": 32,
+ "height": 20,
+ "tilemap": {
+ "width": 32,
+ "height": 32,
+ "format": "8bpp",
+ "tileset_path": "graphics/pokedex/region_map.png",
+ "tilemap_path": "graphics/pokedex/region_map.bin"
+ },
+ "layout": null
+ }
+ ],
+ "entries": {
+ "path": "src/data/region_map/region_map_sections.json"
+ }
+}
diff --git a/resources/text/region_map_default_firered.json b/resources/text/region_map_default_firered.json
new file mode 100644
index 00000000..aa5e199e
--- /dev/null
+++ b/resources/text/region_map_default_firered.json
@@ -0,0 +1,91 @@
+{
+ "region_maps": [
+ {
+ "alias": "kanto",
+ "width": 30,
+ "height": 20,
+ "tilemap": {
+ "width": 30,
+ "height": 20,
+ "format": "4bpp",
+ "tileset_path": "graphics/region_map/region_map.png",
+ "tilemap_path": "graphics/region_map/kanto.bin",
+ "palette": "graphics/region_map/region_map.pal"
+ },
+ "layout": {
+ "width": 22,
+ "height": 15,
+ "offset_left": 4,
+ "offset_top": 4,
+ "format": "C array",
+ "path": "src/data/region_map/region_map_layout_kanto.h"
+ }
+ },
+ {
+ "alias": "sevii_123",
+ "width": 30,
+ "height": 20,
+ "tilemap": {
+ "width": 30,
+ "height": 20,
+ "format": "4bpp",
+ "tileset_path": "graphics/region_map/region_map.png",
+ "tilemap_path": "graphics/region_map/sevii_123.bin",
+ "palette": "graphics/region_map/region_map.pal"
+ },
+ "layout": {
+ "width": 22,
+ "height": 15,
+ "offset_left": 4,
+ "offset_top": 4,
+ "format": "C array",
+ "path": "src/data/region_map/region_map_layout_sevii_123.h"
+ }
+ },
+ {
+ "alias": "sevii_45",
+ "width": 30,
+ "height": 20,
+ "tilemap": {
+ "width": 30,
+ "height": 20,
+ "format": "4bpp",
+ "tileset_path": "graphics/region_map/region_map.png",
+ "tilemap_path": "graphics/region_map/sevii_45.bin",
+ "palette": "graphics/region_map/region_map.pal"
+ },
+ "layout": {
+ "width": 22,
+ "height": 15,
+ "offset_left": 4,
+ "offset_top": 4,
+ "format": "C array",
+ "path": "src/data/region_map/region_map_layout_sevii_45.h"
+ }
+ },
+ {
+ "alias": "sevii_67",
+ "width": 30,
+ "height": 20,
+ "tilemap": {
+ "width": 30,
+ "height": 20,
+ "format": "4bpp",
+ "tileset_path": "graphics/region_map/region_map.png",
+ "tilemap_path": "graphics/region_map/sevii_67.bin",
+ "palette": "graphics/region_map/region_map.pal"
+ },
+ "layout": {
+ "width": 22,
+ "height": 15,
+ "offset_left": 4,
+ "offset_top": 4,
+ "format": "C array",
+ "path": "src/data/region_map/region_map_layout_sevii_67.h"
+ }
+ }
+ ],
+ "revion_map_sections": {
+ "path": "src/data/region_map/region_map_sections.json"
+ }
+}
diff --git a/resources/text/region_map_default_ruby.json b/resources/text/region_map_default_ruby.json
new file mode 100644
index 00000000..e69de29b
diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp
index 4302147b..f81547ec 100644
--- a/src/core/parseutil.cpp
+++ b/src/core/parseutil.cpp
@@ -34,6 +34,9 @@ QString ParseUtil::readTextFile(const QString &path) {
return QString();
}
QTextStream in(&file);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ in.setCodec("UTF-8");
+#endif // Qt6 defaults to UTF-8, but setCodec is renamed to setEncoding
QString text = "";
while (!in.atEnd()) {
text += in.readLine() + '\n';
diff --git a/src/core/regionmap.cpp b/src/core/regionmap.cpp
index f8dbcac1..88116268 100644
--- a/src/core/regionmap.cpp
+++ b/src/core/regionmap.cpp
@@ -1,6 +1,7 @@
#include "regionmap.h"
#include "regionmapeditor.h"
#include "paletteutil.h"
+#include "project.h"
#include "log.h"
#include "config.h"
@@ -11,6 +12,8 @@
#include
#include
+using std::make_shared;
+
static bool ensureRegionMapFileExists(QString filepath) {
if (!QFile::exists(filepath)) {
logError(QString("Region map file does not exist: %1").arg(filepath));
@@ -19,390 +22,420 @@ static bool ensureRegionMapFileExists(QString filepath) {
return true;
}
-bool RegionMap::init(Project *pro) {
- QString path = pro->root;
- this->project = pro;
+RegionMap::RegionMap(Project *project) {
+ this->project = project;
+}
- QSize dimensions = porymapConfig.getRegionMapDimensions();
- img_width_ = dimensions.width();
- img_height_ = dimensions.height();
+bool RegionMap::loadMapData(poryjson::Json data) {
+ poryjson::Json::object mapObject = data.object_items();
- layout_width_ = img_width_ - this->padLeft - this->padRight;
- layout_height_ = img_height_ - this->padTop - this->padBottom;
+ this->alias = mapObject["alias"].string_value();
+ this->region_width = mapObject["width"].int_value();
+ this->region_height = mapObject["height"].int_value();
- region_map_bin_path = path + "/graphics/pokenav/region_map_map.bin";
- region_map_png_path = path + "/graphics/pokenav/region_map.png";
- region_map_entries_path = path + "/src/data/region_map/region_map_entries.h";
- region_map_layout_bin_path = path + "/graphics/pokenav/region_map_section_layout.bin";
- city_map_tiles_path = path + "/graphics/pokenav/zoom_tiles.png";
- bool allFilesExist = ensureRegionMapFileExists(region_map_bin_path)
- && ensureRegionMapFileExists(region_map_png_path)
- && ensureRegionMapFileExists(region_map_entries_path)
- && ensureRegionMapFileExists(region_map_layout_bin_path)
- && ensureRegionMapFileExists(city_map_tiles_path);
+ poryjson::Json tilemapJson = mapObject["tilemap"];
+ poryjson::Json layoutJson = mapObject["layout"];
- return allFilesExist
- && readBkgImgBin()
- && readLayout();
+ this->tilemap.clear();
+ this->layout_layers.clear();
+ this->layouts.clear();
+
+ loadTilemap(tilemapJson);
+ loadLayout(layoutJson);
+}
+
+int RegionMap::tilemapBytes() {
+ // bytes per tile multiplier
+ int multiplier = 1;
+
+ switch (tilemap_format) {
+ case TilemapFormat::Plain:
+ multiplier = 1;
+ break;
+ case TilemapFormat::BPP_4:
+ multiplier = 2;
+ break;
+ case TilemapFormat::BPP_8:
+ multiplier = 2;
+ break;
+ }
+
+ return tilemapSize() * multiplier;
+}
+
+bool RegionMap::loadTilemap(poryjson::Json tilemapJson) {
+ bool errored = false;
+
+ poryjson::Json::object tilemapObject = tilemapJson.object_items();
+
+ this->tilemap_width = tilemapObject["width"].int_value();
+ this->tilemap_height = tilemapObject["height"].int_value();
+
+
+ QString tilemapFormat = tilemapObject["format"].string_value();
+ QMap formatsMap = { {"plain", TilemapFormat::Plain}, {"4bpp", TilemapFormat::BPP_4}, {"8bpp", TilemapFormat::BPP_8} };
+ this->tilemap_format = formatsMap[tilemapFormat];
+
+ this->tileset_path = tilemapObject["tileset_path"].string_value();
+ this->tilemap_path = tilemapObject["tilemap_path"].string_value();
+
+ //! TODO: set a config option for this
+ if (tilemapObject.contains("palette")) {
+ this->palette_path = tilemapObject["palette"].string_value();
+ }
+
+ QFile tilemapFile(fullPath(tilemap_path));
+ if (!tilemapFile.open(QIODevice::ReadOnly)) {
+ logError(QString("Failed to open region map tilemap file %1.").arg(tilemap_path));
+ return false;
+ }
+ QDataStream dataStream(&tilemapFile);
+ dataStream.setByteOrder(QDataStream::LittleEndian);
+
+ if (tilemapFile.size() < tilemapBytes()) {
+ logError(QString("The region map tilemap at %1 is too small.").arg(tilemap_path));
+ return false;
+ }
+
+ this->tilemap.resize(tilemapSize());
+ switch (this->tilemap_format) {
+ case TilemapFormat::Plain:
+ for (int i = 0; i < tilemapBytes(); i++) {
+ uint8_t tile;
+ dataStream >> tile;
+ this->tilemap[i] = make_shared(tile);
+ }
+ break;
+ case TilemapFormat::BPP_4:
+ for (int i = 0; i < tilemapBytes(); i+=2) {
+ uint16_t tile;
+ dataStream >> tile;
+ this->tilemap[i / 2] = make_shared(tile & 0xffff);
+ }
+ break;
+ case TilemapFormat::BPP_8:
+ for (int i = 0; i < tilemapBytes(); i+=2) {
+ uint16_t tile;
+ dataStream >> tile;
+ this->tilemap[i / 2] = make_shared(tile & 0xffff);
+ }
+ break;
+ }
+
+ tilemapFile.close();
+
+ return !errored;
+}
+
+bool RegionMap::loadLayout(poryjson::Json layoutJson) {
+ if (layoutJson.is_null()) {
+ this->layout_format = LayoutFormat::None;
+ return true;
+ }
+
+ poryjson::Json::object layoutObject = layoutJson.object_items();
+
+ QString layoutFormat = layoutObject["format"].string_value();
+ QMap layoutFormatMap = { {"binary", LayoutFormat::Binary}, {"C array", LayoutFormat::CArray} };
+ this->layout_format = layoutFormatMap[layoutFormat];
+
+ this->layout_path = layoutObject["path"].string_value();
+ this->layout_width = layoutObject["width"].int_value();
+ this->layout_height = layoutObject["height"].int_value();
+
+ this->offset_left = layoutObject["offset_left"].int_value();
+ this->offset_top = layoutObject["offset_top"].int_value();
+
+ bool errored = false;
+
+ switch (this->layout_format) {
+ case LayoutFormat::Binary:
+ {
+ // TODO: only one layer supported for binary layouts (change or no?)
+ QFile binFile(fullPath(this->layout_path));
+ if (!binFile.open(QIODevice::ReadOnly)) {
+ logError(QString("Failed to read region map layout binary file %1").arg(this->layout_path));
+ return false;
+ }
+ QByteArray mapBinData = binFile.readAll();
+ binFile.close();
+
+ if (mapBinData.size() != this->layout_width * this->layout_height) {
+ logError("Region map layout file size does not match given dimensions for " + this->alias);
+ return false;
+ }
+
+ // for layouts with only a single layer, it is called main
+ this->layout_layers.append("main");
+ QList layout;
+
+ for (int y = 0; y < this->layout_height; y++) {
+ for (int x = 0; x < this->layout_width; x++) {
+ int bin_index = x + y * this->layout_width;
+ uint8_t square_section_id = mapBinData.at(bin_index);
+ QString square_section_name = project->mapSectionValueToName.value(square_section_id);
+
+ LayoutSquare square;
+ square.map_section = square_section_name;
+ square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
+ square.x = x;
+ square.y = y;
+
+ layout.append(square);
+ }
+ }
+ this->layouts["main"] = layout;
+ break;
+ }
+ case LayoutFormat::CArray:
+ {
+ // TODO: pokeruby / non-layered style C array or just an array of mapsections
+
+ ParseUtil parser;
+ QString text = parser.readTextFile(fullPath(this->layout_path));
+
+ QRegularExpression re("(?static)?\\s?(?const)?\\s?(?[A-Za-z0-9_]+)?\\s+(?