From 562edc5e3e2114bf3a91b396e92503205fb63c72 Mon Sep 17 00:00:00 2001
From: Marcus Huderle <huderlem@gmail.com>
Date: Sat, 10 Mar 2018 00:17:50 -0800
Subject: [PATCH 1/2] Fix collision and elevation selections

---
 editor.cpp | 18 ++++++++++++++++++
 editor.h   | 22 ++++++++++++++++++----
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/editor.cpp b/editor.cpp
index ddca2fdd..ebf906a8 100755
--- a/editor.cpp
+++ b/editor.cpp
@@ -332,6 +332,24 @@ void MetatilesPixmapItem::updateSelection(QPointF pos, Qt::MouseButton button) {
     }
 }
 
+void MovementPermissionsPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent* event) {
+    QPointF pos = event->pos();
+    int x = ((int)pos.x()) / 16;
+    int y = ((int)pos.y()) / 16;
+    int width = pixmap().width() / 16;
+    int height = pixmap().height() / 16;
+    if ((x >= 0 && x < width) && (y >=0 && y < height)) {
+        pick(y * width + x);
+    }
+}
+void MovementPermissionsPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
+    updateCurHoveredMetatile(event->pos());
+    mousePressEvent(event);
+}
+void MovementPermissionsPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
+    mousePressEvent(event);
+}
+
 void CollisionMetatilesPixmapItem::updateCurHoveredMetatile(QPointF pos) {
     int x = ((int)pos.x()) / 16;
     int y = ((int)pos.y()) / 16;
diff --git a/editor.h b/editor.h
index 954da138..68b051f2 100755
--- a/editor.h
+++ b/editor.h
@@ -266,10 +266,24 @@ protected:
     void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
 };
 
-class CollisionMetatilesPixmapItem : public MetatilesPixmapItem {
+class MovementPermissionsPixmapItem : public MetatilesPixmapItem {
     Q_OBJECT
 public:
-    CollisionMetatilesPixmapItem(Map *map_): MetatilesPixmapItem(map_) {
+    MovementPermissionsPixmapItem(Map *map_): MetatilesPixmapItem(map_) {}
+    virtual void pick(uint collision) {
+        map->paint_collision = collision;
+        draw();
+    }
+protected:
+    void mousePressEvent(QGraphicsSceneMouseEvent*);
+    void mouseMoveEvent(QGraphicsSceneMouseEvent*);
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
+};
+
+class CollisionMetatilesPixmapItem : public MovementPermissionsPixmapItem {
+    Q_OBJECT
+public:
+    CollisionMetatilesPixmapItem(Map *map_): MovementPermissionsPixmapItem(map_) {
         connect(map, SIGNAL(paintCollisionChanged(Map*)), this, SLOT(paintCollisionChanged(Map *)));
     }
     virtual void pick(uint collision) {
@@ -287,10 +301,10 @@ private slots:
     }
 };
 
-class ElevationMetatilesPixmapItem : public MetatilesPixmapItem {
+class ElevationMetatilesPixmapItem : public MovementPermissionsPixmapItem {
     Q_OBJECT
 public:
-    ElevationMetatilesPixmapItem(Map *map_): MetatilesPixmapItem(map_) {
+    ElevationMetatilesPixmapItem(Map *map_): MovementPermissionsPixmapItem(map_) {
         connect(map, SIGNAL(paintCollisionChanged(Map*)), this, SLOT(paintCollisionChanged(Map *)));
     }
     virtual void pick(uint elevation) {

From 69c84a68e34c0ce84ead266cbed775baffc6be50 Mon Sep 17 00:00:00 2001
From: Marcus Huderle <huderlem@gmail.com>
Date: Tue, 13 Mar 2018 20:07:16 -0700
Subject: [PATCH 2/2] Properly support painting tiles from secondary tileset

---
 editor.cpp | 38 ++++++++++++++++++++------------------
 editor.h   |  2 --
 map.cpp    | 35 ++++++++++++++++++++++++++---------
 map.h      |  6 ++++--
 4 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/editor.cpp b/editor.cpp
index ebf906a8..2d23b437 100755
--- a/editor.cpp
+++ b/editor.cpp
@@ -322,7 +322,7 @@ void MetatilesPixmapItem::updateSelection(QPointF pos, Qt::MouseButton button) {
     if ((x >= 0 && x < width) && (y >=0 && y < height)) {
         int baseTileX = x < map->paint_metatile_initial_x ? x : map->paint_metatile_initial_x;
         int baseTileY = y < map->paint_metatile_initial_y ? y : map->paint_metatile_initial_y;
-        map->paint_tile = baseTileY * 8 + baseTileX;
+        map->paint_tile_index = baseTileY * 8 + baseTileX;
         map->paint_tile_width = abs(map->paint_metatile_initial_x - x) + 1;
         map->paint_tile_height = abs(map->paint_metatile_initial_y - y) + 1;
         map->smart_paths_enabled = button == Qt::RightButton
@@ -411,7 +411,7 @@ void MapPixmapItem::paintNormal(int x, int y) {
         int actualY = j + y;
         Block *block = map->getBlock(actualX, actualY);
         if (block) {
-            block->tile = map->paint_tile + i + (j * 8);
+            block->tile = map->getSelectedBlockIndex(map->paint_tile_index + i + (j * 8));
             map->_setBlock(actualX, actualY, *block);
         }
     }
@@ -439,32 +439,38 @@ QList<int> MapPixmapItem::smartPathTable = QList<int>({
     8 + 1, // 1111
 });
 
-#define IS_SMART_PATH_TILE(block) ((block->tile >= map->paint_tile && block->tile < map->paint_tile + 3) \
-                                || (block->tile >= map->paint_tile + 8 && block->tile < map->paint_tile + 11) \
-                                || (block->tile >= map->paint_tile + 16 && block->tile < map->paint_tile + 19))
+#define IS_SMART_PATH_TILE(block) ((map->getDisplayedBlockIndex(block->tile) >= map->paint_tile_index && map->getDisplayedBlockIndex(block->tile) < map->paint_tile_index + 3) \
+                                || (map->getDisplayedBlockIndex(block->tile) >= map->paint_tile_index + 8 && map->getDisplayedBlockIndex(block->tile) < map->paint_tile_index + 11) \
+                                || (map->getDisplayedBlockIndex(block->tile) >= map->paint_tile_index + 16 && map->getDisplayedBlockIndex(block->tile) < map->paint_tile_index + 19))
 
 void MapPixmapItem::paintSmartPath(int x, int y) {
     // Smart path should never be enabled without a 3x3 block selection.
     if (map->paint_tile_width != 3 || map->paint_tile_height != 3) return;
 
     // Shift to the middle tile of the smart path selection.
-    int openTile = map->paint_tile + 8 + 1;
+    int openTile = map->paint_tile_index + 8 + 1;
 
     // Fill the region with the open tile.
-    for (int i = -1; i <= 1 && i + x < map->getWidth() && i + x >= 0; i++)
-    for (int j = -1; j <= 1 && j + y < map->getHeight() && j + y >= 0; j++) {
+    for (int i = -1; i <= 1; i++)
+    for (int j = -1; j <= 1; j++) {
+        // Check if in map bounds.
+        if (!(i + x < map->getWidth() && i + x >= 0 && j + y < map->getHeight() && j + y >= 0))
+            continue;
         int actualX = i + x;
         int actualY = j + y;
         Block *block = map->getBlock(actualX, actualY);
         if (block) {
-            block->tile = openTile;
+            block->tile = map->getSelectedBlockIndex(openTile);
             map->_setBlock(actualX, actualY, *block);
         }
     }
 
     // Go back and resolve the edge tiles
-    for (int i = -2; i <= 2 && i + x < map->getWidth() && i + x >= 0; i++)
-    for (int j = -2; j <= 2 && j + y < map->getHeight() && j + y >= 0; j++) {
+    for (int i = -2; i <= 2; i++)
+    for (int j = -2; j <= 2; j++) {
+        // Check if in map bounds.
+        if (!(i + x < map->getWidth() && i + x >= 0 && j + y < map->getHeight() && j + y >= 0))
+            continue;
         // Ignore the corners, which can't possible be affected by the smart path.
         if ((i == -2 && j == -2) || (i == 2 && j == -2) ||
             (i == -2 && j ==  2) || (i == 2 && j ==  2))
@@ -494,11 +500,7 @@ void MapPixmapItem::paintSmartPath(int x, int y) {
         if (left && IS_SMART_PATH_TILE(left))
             id += 8;
 
-        if (block) {
-            qDebug() << "tile: " << block->tile << "base: " << map->paint_tile << "id: " << id;
-        }
-
-        block->tile = map->paint_tile + smartPathTable[id];;
+        block->tile = map->getSelectedBlockIndex(map->paint_tile_index + smartPathTable[id]);
         map->_setBlock(actualX, actualY, *block);
     }
 }
@@ -508,7 +510,7 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
         QPointF pos = event->pos();
         int x = (int)(pos.x()) / 16;
         int y = (int)(pos.y()) / 16;
-        map->floodFill(x, y, map->paint_tile);
+        map->floodFill(x, y, map->getSelectedBlockIndex(map->paint_tile_index));
         draw();
     }
 }
@@ -519,7 +521,7 @@ void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
     int y = (int)(pos.y()) / 16;
     Block *block = map->getBlock(x, y);
     if (block) {
-        map->paint_tile = block->tile;
+        map->paint_tile_index = map->getDisplayedBlockIndex(block->tile);
         map->paint_tile_width = 1;
         map->paint_tile_height = 1;
         emit map->paintTileChanged(map);
diff --git a/editor.h b/editor.h
index 68b051f2..e8ccfc0c 100755
--- a/editor.h
+++ b/editor.h
@@ -243,8 +243,6 @@ protected:
 class MetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
     Q_OBJECT
 public:
-    MetatilesPixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
-    }
     MetatilesPixmapItem(Map *map_) {
         map = map_;
         setAcceptHoverEvents(true);
diff --git a/map.cpp b/map.cpp
index ced7d77a..3dfa7b71 100755
--- a/map.cpp
+++ b/map.cpp
@@ -12,7 +12,7 @@ Map::Map(QObject *parent) : QObject(parent)
     cached_blockdata = new Blockdata;
     cached_collision = new Blockdata;
     cached_border = new Blockdata;
-    paint_tile = 1;
+    paint_tile_index = 1;
     paint_collision = 0;
     paint_elevation = 3;
 }
@@ -72,6 +72,22 @@ int Map::getBlockIndex(int index) {
     }
 }
 
+int Map::getSelectedBlockIndex(int index) {
+    if (index < tileset_primary->metatiles->length()) {
+        return index;
+    } else {
+        return 0x200 + (index - tileset_primary->metatiles->length());
+    }
+}
+
+int Map::getDisplayedBlockIndex(int index) {
+    if (index < tileset_primary->metatiles->length()) {
+        return index;
+    } else {
+        return index - 0x200 + tileset_primary->metatiles->length();
+    }
+}
+
 QImage Map::getMetatileTile(int tile) {
     Tileset *tileset = getBlockTileset(tile);
     int local_index = getBlockIndex(tile);
@@ -426,7 +442,7 @@ QPixmap Map::renderCollisionMetatiles() {
         QImage metatile_image = getCollisionMetatileImage(i);
         painter.drawImage(origin, metatile_image);
     }
-    drawSelection(paint_collision, width_, &painter);
+    drawSelection(paint_collision, width_, 1, 1, &painter);
     painter.end();
     return QPixmap::fromImage(image);
 }
@@ -444,20 +460,20 @@ QPixmap Map::renderElevationMetatiles() {
         QImage metatile_image = getElevationMetatileImage(i);
         painter.drawImage(origin, metatile_image);
     }
-    drawSelection(paint_elevation, width_, &painter);
+    drawSelection(paint_elevation, width_, 1, 1, &painter);
     painter.end();
     return QPixmap::fromImage(image);
 }
 
-void Map::drawSelection(int i, int w, QPainter *painter) {
+void Map::drawSelection(int i, int w, int selectionWidth, int selectionHeight, QPainter *painter) {
     int x = i % w;
     int y = i / w;
     painter->save();
 
     QColor penColor = smart_paths_enabled ? QColor(0xff, 0x0, 0xff) : QColor(0xff, 0xff, 0xff);
     painter->setPen(penColor);
-    int rectWidth = paint_tile_width * 16;
-    int rectHeight = paint_tile_height * 16;
+    int rectWidth = selectionWidth * 16;
+    int rectHeight = selectionHeight * 16;
     painter->drawRect(x * 16, y * 16, rectWidth - 1, rectHeight -1);
     painter->setPen(QColor(0, 0, 0));
     painter->drawRect(x * 16 - 1, y * 16 - 1, rectWidth + 1, rectHeight + 1);
@@ -487,7 +503,7 @@ QPixmap Map::renderMetatiles() {
         painter.drawImage(metatile_origin, metatile_image);
     }
 
-    drawSelection(paint_tile, width_, &painter);
+    drawSelection(paint_tile_index, width_, paint_tile_width, paint_tile_height, &painter);
 
     painter.end();
     return QPixmap::fromImage(image);
@@ -750,9 +766,10 @@ void Map::clearHoveredTile() {
     emit statusBarMessage(QString(""));
 }
 
-void Map::hoveredMetatileChanged(int block) {
+void Map::hoveredMetatileChanged(int blockIndex) {
+    int tile = getSelectedBlockIndex(blockIndex);
     emit statusBarMessage(QString("Block: 0x%1")
-                          .arg(QString("%1").arg(block, 3, 16, QChar('0')).toUpper()));
+                          .arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper()));
 }
 
 void Map::clearHoveredMetatile() {
diff --git a/map.h b/map.h
index b05a60ea..6d97ac69 100755
--- a/map.h
+++ b/map.h
@@ -112,6 +112,8 @@ public:
     int getHeight();
     Tileset* getBlockTileset(int);
     int getBlockIndex(int index);
+    int getSelectedBlockIndex(int index);
+    int getDisplayedBlockIndex(int index);
     Metatile* getMetatile(int);
     QImage getMetatileImage(int);
     QImage getMetatileTile(int);
@@ -128,7 +130,7 @@ public:
 
     QPixmap renderCollisionMetatiles();
     QPixmap renderElevationMetatiles();
-    void drawSelection(int i, int w, QPainter *painter);
+    void drawSelection(int i, int w, int selectionWidth, int selectionHeight, QPainter *painter);
 
     bool blockChanged(int, Blockdata*);
     Blockdata* cached_blockdata = NULL;
@@ -141,7 +143,7 @@ public:
     bool smart_paths_enabled = false;
     int paint_metatile_initial_x;
     int paint_metatile_initial_y;
-    int paint_tile;
+    int paint_tile_index;
     int paint_tile_width = 1;
     int paint_tile_height = 1;
     int paint_tile_initial_x;