First stab at generating metatiles

This commit is contained in:
Marcus Huderle 2023-03-01 17:57:11 -06:00
parent 23747d9822
commit 95a1da1930
3 changed files with 114 additions and 7 deletions

View file

@ -3,6 +3,7 @@
#define PAINTSELECTION_H
#include "block.h"
#include "map.h"
#include <QList>
#include <QPoint>
@ -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<MetatileSelectionItem> metatileItems;
QList<CollisionSelectionItem> 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<uint16_t> stampIds;
};

View file

@ -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);
}
}

View file

@ -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;
}