From 95a1da19302a5d1910cc847a53f4681ae2dbf0b2 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 1 Mar 2023 17:57:11 -0600 Subject: [PATCH] First stab at generating metatiles --- include/ui/paintselection.h | 7 ++- src/ui/mappixmapitem.cpp | 2 +- src/ui/paintselection.cpp | 112 +++++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 7 deletions(-) diff --git a/include/ui/paintselection.h b/include/ui/paintselection.h index 52f07888..0e6623a0 100644 --- a/include/ui/paintselection.h +++ b/include/ui/paintselection.h @@ -3,6 +3,7 @@ #define PAINTSELECTION_H #include "block.h" +#include "map.h" #include #include @@ -24,7 +25,7 @@ class PaintSelection { public: QPoint dimensions; - virtual bool paintNormal(int, Block*) = 0; + virtual bool paintNormal(int, Block*, Map*, int layer) = 0; }; class MetatileSelection: public PaintSelection @@ -37,7 +38,7 @@ public: this->metatileItems = other.metatileItems; this->collisionItems = other.collisionItems; } - bool paintNormal(int index, Block *block) override; + bool paintNormal(int index, Block *block, Map*, int layer) override; bool hasCollision = false; QList metatileItems; QList collisionItems; @@ -47,7 +48,7 @@ class StampSelection: public PaintSelection { public: StampSelection() {} - bool paintNormal(int index, Block *block) override; + bool paintNormal(int index, Block *block, Map*, int layer) override; QList stampIds; }; diff --git a/src/ui/mappixmapitem.cpp b/src/ui/mappixmapitem.cpp index f75203f7..dbdac39e 100644 --- a/src/ui/mappixmapitem.cpp +++ b/src/ui/mappixmapitem.cpp @@ -137,7 +137,7 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { Block block; if (map->getBlock(actualX, actualY, &block)) { int index = j * selectionWidth + i; - if (selection->paintNormal(index, &block)) { + if (selection->paintNormal(index, &block, map, 2)) { map->setBlock(actualX, actualY, block, !fromScriptCall); } } diff --git a/src/ui/paintselection.cpp b/src/ui/paintselection.cpp index 66ce7582..bec5d8ea 100644 --- a/src/ui/paintselection.cpp +++ b/src/ui/paintselection.cpp @@ -1,7 +1,9 @@ #include "paintselection.h" +#include "project.h" +#include "metatile.h" #include "log.h" -bool MetatileSelection::paintNormal(int index, Block *block) { +bool MetatileSelection::paintNormal(int index, Block *block, Map *map, int layer) { MetatileSelectionItem item = this->metatileItems.at(index); if (!item.enabled) return false; @@ -15,7 +17,111 @@ bool MetatileSelection::paintNormal(int index, Block *block) { return true; } -bool StampSelection::paintNormal(int index, Block *block) { - block->metatileId = 1; +void adjustMetatileForLayer(int layer, int *baseOffset, Metatile *metatile) { + switch (metatile->layerType) + { + default: + case METATILE_LAYER_MIDDLE_TOP: + switch (layer) + { + case 0: + *baseOffset = 0; + metatile->layerType = METATILE_LAYER_BOTTOM_TOP; + for (int i = 0; i < 4; i++) { + metatile->tiles[i+4] = metatile->tiles[i]; + } + break; + case 1: + *baseOffset = 0; + break; + case 2: + *baseOffset = 4; + break; + } + break; + case METATILE_LAYER_BOTTOM_MIDDLE: + switch (layer) + { + case 0: + *baseOffset = 0; + break; + case 1: + *baseOffset = 4; + break; + case 2: + *baseOffset = 4; + metatile->layerType = METATILE_LAYER_MIDDLE_TOP; + for (int i = 0; i < 4; i++) { + metatile->tiles[i] = metatile->tiles[i+4]; + } + break; + } + break; + case METATILE_LAYER_BOTTOM_TOP: + switch (layer) + { + case 0: + *baseOffset = 0; + break; + case 1: + *baseOffset = 4; + metatile->layerType = METATILE_LAYER_BOTTOM_MIDDLE; + break; + case 2: + *baseOffset = 4; + break; + } + break; + } +} + +bool StampSelection::paintNormal(int index, Block *block, Map *map, int layer) { + Tileset *primaryTileset = map->layout->tileset_primary; + Tileset *secondaryTileset = map->layout->tileset_secondary; + // 1. Build metatile by applying the stamp to the existing block. + Metatile metatile = *(Tileset::getMetatile(block->metatileId, map->layout->tileset_primary, map->layout->tileset_secondary)); + int baseOffset; + adjustMetatileForLayer(layer, &baseOffset, &metatile); + metatile.tiles[baseOffset] = Tile(0x5, false, false, 2); + metatile.tiles[baseOffset + 1] = Tile(0x5, true, false, 2); + metatile.tiles[baseOffset + 2] = Tile(0x15, false, false, 2); + metatile.tiles[baseOffset + 3] = Tile(0x15, true, false, 2); + + // 2. Check if the metatile already exists in the map layout's primary or secondary tilesets. + bool exists = false; + uint16_t metatileId = 0; + uint16_t i = 0; + for (auto m : primaryTileset->metatiles) { + if (*m == metatile) { + exists = true; + metatileId = i; + break; + } + i++; + } + if (!exists) { + i = Project::getNumMetatilesPrimary(); + for (auto m : secondaryTileset->metatiles) { + if (*m == metatile) { + exists = true; + metatileId = i; + break; + } + i++; + } + } + + // 3. If the metatile doesn't exist, append the new metatile to the secondary tileset. + if (!exists) { + int maxSecondaryMetatiles = Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary(); + if (secondaryTileset->metatiles.length() >= maxSecondaryMetatiles) { + return false; + } + secondaryTileset->metatiles.append(new Metatile(metatile)); + metatileId = Project::getNumMetatilesPrimary() + secondaryTileset->metatiles.length() - 1; + } + + // 4. Set the block's metatile id. + block->metatileId = metatileId; return true; }