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