127 lines
3.9 KiB
C++
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;
|
|
}
|