porymap/src/ui/paintselection.cpp
2023-03-01 17:57:11 -06:00

127 lines
3.9 KiB
C++

#include "paintselection.h"
#include "project.h"
#include "metatile.h"
#include "log.h"
bool MetatileSelection::paintNormal(int index, Block *block, Map *map, int layer) {
MetatileSelectionItem item = this->metatileItems.at(index);
if (!item.enabled)
return false;
block->metatileId = item.metatileId;
if (this->hasCollision && this->collisionItems.length() == this->metatileItems.length()) {
CollisionSelectionItem collisionItem = this->collisionItems.at(index);
block->collision = collisionItem.collision;
block->elevation = collisionItem.elevation;
}
return true;
}
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;
}