Skip to content

Commit

Permalink
Throw error when importing tiles with triple layer content in dual la…
Browse files Browse the repository at this point in the history
…yer mode
  • Loading branch information
grunt-lucas committed Aug 10, 2023
1 parent 43e33a2 commit 84ec393
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 33 deletions.
23 changes: 19 additions & 4 deletions include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,16 @@ struct RGBATile {
* Porytiles to give much more detailed error messages.
*/
TileType type;

// raw tile index, used for FREESTANDING and ANIM types
std::size_t tileIndex;

// LAYERED specific metadata
TileLayer layer;
// metatileIndex is which metatile on the sheet, used in compile-primary and compile-secondary
std::size_t metatileIndex;
// Subtile within the metatile
Subtile subtile;

// ANIM specific metadata
std::string anim;
std::string frame;

Expand All @@ -160,6 +164,16 @@ struct RGBATile {
return pixels[row * TILE_SIDE_LENGTH + col];
}

[[nodiscard]] bool transparent(const RGBA32 &transparencyColor) const
{
for (std::size_t i = 0; i < pixels.size(); i++) {
if (pixels[i] != transparencyColor && pixels[i].alpha != ALPHA_TRANSPARENT) {
return false;
}
}
return true;
}

auto operator==(const RGBATile &other) const { return this->pixels == other.pixels; }

// Ignore the other fields for purposes of ordering the tiles
Expand All @@ -174,7 +188,7 @@ struct RGBATile {
return std::strong_ordering::greater;
}

friend std::ostream &operator<<(std::ostream &, const RGBATile &);
friend std::ostream &operator<<(std::ostream &os, const RGBATile &tile);
};

extern const RGBATile RGBA_TILE_BLACK;
Expand Down Expand Up @@ -612,8 +626,9 @@ struct CompilerConfig {
CompilerMode mode;
RGBA32 transparencyColor;
std::size_t maxRecurseCount;
bool tripleLayer;

CompilerConfig() : mode{}, transparencyColor{RGBA_MAGENTA}, maxRecurseCount{2'000'000} {}
CompilerConfig() : mode{}, transparencyColor{RGBA_MAGENTA}, maxRecurseCount{2'000'000}, tripleLayer{true} {}
};

struct CompilerContext {
Expand Down
80 changes: 53 additions & 27 deletions src/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ DecompiledTileset importTilesFromPng(PtContext &ctx, const png::image<png::rgba_
std::size_t pngWidthInTiles = png.get_width() / TILE_SIDE_LENGTH;
std::size_t pngHeightInTiles = png.get_height() / TILE_SIDE_LENGTH;

for (size_t tileIndex = 0; tileIndex < pngWidthInTiles * pngHeightInTiles; tileIndex++) {
size_t tileRow = tileIndex / pngWidthInTiles;
size_t tileCol = tileIndex % pngWidthInTiles;
for (std::size_t tileIndex = 0; tileIndex < pngWidthInTiles * pngHeightInTiles; tileIndex++) {
std::size_t tileRow = tileIndex / pngWidthInTiles;
std::size_t tileCol = tileIndex % pngWidthInTiles;
RGBATile tile{};
tile.type = TileType::FREESTANDING;
tile.tileIndex = tileIndex;
for (size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
size_t pixelRow = (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
size_t pixelCol = (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
for (std::size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
std::size_t pixelRow = (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
std::size_t pixelCol = (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
tile.pixels[pixelIndex].red = png[pixelRow][pixelCol].red;
tile.pixels[pixelIndex].green = png[pixelRow][pixelCol].green;
tile.pixels[pixelIndex].blue = png[pixelRow][pixelCol].blue;
Expand Down Expand Up @@ -91,69 +91,95 @@ DecompiledTileset importLayeredTilesFromPngs(PtContext &ctx, const png::image<pn
for (size_t metatileIndex = 0; metatileIndex < widthInMetatiles * heightInMetatiles; metatileIndex++) {
size_t metatileRow = metatileIndex / widthInMetatiles;
size_t metatileCol = metatileIndex % widthInMetatiles;
for (size_t bottomTileIndex = 0; bottomTileIndex < METATILE_TILE_SIDE_LENGTH * METATILE_TILE_SIDE_LENGTH;
std::vector<RGBATile> bottomTiles{};
std::vector<RGBATile> middleTiles{};
std::vector<RGBATile> topTiles{};
for (std::size_t bottomTileIndex = 0; bottomTileIndex < METATILE_TILE_SIDE_LENGTH * METATILE_TILE_SIDE_LENGTH;
bottomTileIndex++) {
size_t tileRow = bottomTileIndex / METATILE_TILE_SIDE_LENGTH;
size_t tileCol = bottomTileIndex % METATILE_TILE_SIDE_LENGTH;
std::size_t tileRow = bottomTileIndex / METATILE_TILE_SIDE_LENGTH;
std::size_t tileCol = bottomTileIndex % METATILE_TILE_SIDE_LENGTH;
RGBATile bottomTile{};
bottomTile.type = TileType::LAYERED;
bottomTile.layer = TileLayer::BOTTOM;
bottomTile.metatileIndex = metatileIndex;
bottomTile.subtile = static_cast<Subtile>(bottomTileIndex);
for (std::size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
size_t pixelRow =
std::size_t pixelRow =
(metatileRow * METATILE_SIDE_LENGTH) + (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
size_t pixelCol =
std::size_t pixelCol =
(metatileCol * METATILE_SIDE_LENGTH) + (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
bottomTile.pixels[pixelIndex].red = bottom[pixelRow][pixelCol].red;
bottomTile.pixels[pixelIndex].green = bottom[pixelRow][pixelCol].green;
bottomTile.pixels[pixelIndex].blue = bottom[pixelRow][pixelCol].blue;
bottomTile.pixels[pixelIndex].alpha = bottom[pixelRow][pixelCol].alpha;
}
decompiledTiles.tiles.push_back(bottomTile);
bottomTiles.push_back(bottomTile);
}
for (size_t middleTileIndex = 0; middleTileIndex < METATILE_TILE_SIDE_LENGTH * METATILE_TILE_SIDE_LENGTH;
for (std::size_t middleTileIndex = 0; middleTileIndex < METATILE_TILE_SIDE_LENGTH * METATILE_TILE_SIDE_LENGTH;
middleTileIndex++) {
size_t tileRow = middleTileIndex / METATILE_TILE_SIDE_LENGTH;
size_t tileCol = middleTileIndex % METATILE_TILE_SIDE_LENGTH;
std::size_t tileRow = middleTileIndex / METATILE_TILE_SIDE_LENGTH;
std::size_t tileCol = middleTileIndex % METATILE_TILE_SIDE_LENGTH;
RGBATile middleTile{};
middleTile.type = TileType::LAYERED;
middleTile.layer = TileLayer::MIDDLE;
middleTile.metatileIndex = metatileIndex;
middleTile.subtile = static_cast<Subtile>(middleTileIndex);
for (std::size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
size_t pixelRow =
std::size_t pixelRow =
(metatileRow * METATILE_SIDE_LENGTH) + (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
size_t pixelCol =
std::size_t pixelCol =
(metatileCol * METATILE_SIDE_LENGTH) + (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
middleTile.pixels[pixelIndex].red = middle[pixelRow][pixelCol].red;
middleTile.pixels[pixelIndex].green = middle[pixelRow][pixelCol].green;
middleTile.pixels[pixelIndex].blue = middle[pixelRow][pixelCol].blue;
middleTile.pixels[pixelIndex].alpha = middle[pixelRow][pixelCol].alpha;
}
decompiledTiles.tiles.push_back(middleTile);
middleTiles.push_back(middleTile);
}
for (size_t topTileIndex = 0; topTileIndex < METATILE_TILE_SIDE_LENGTH * METATILE_TILE_SIDE_LENGTH;
for (std::size_t topTileIndex = 0; topTileIndex < METATILE_TILE_SIDE_LENGTH * METATILE_TILE_SIDE_LENGTH;
topTileIndex++) {
size_t tileRow = topTileIndex / METATILE_TILE_SIDE_LENGTH;
size_t tileCol = topTileIndex % METATILE_TILE_SIDE_LENGTH;
std::size_t tileRow = topTileIndex / METATILE_TILE_SIDE_LENGTH;
std::size_t tileCol = topTileIndex % METATILE_TILE_SIDE_LENGTH;
RGBATile topTile{};
topTile.type = TileType::LAYERED;
topTile.layer = TileLayer::TOP;
topTile.metatileIndex = metatileIndex;
topTile.subtile = static_cast<Subtile>(topTileIndex);
for (std::size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
size_t pixelRow =
std::size_t pixelRow =
(metatileRow * METATILE_SIDE_LENGTH) + (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
size_t pixelCol =
std::size_t pixelCol =
(metatileCol * METATILE_SIDE_LENGTH) + (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
topTile.pixels[pixelIndex].red = top[pixelRow][pixelCol].red;
topTile.pixels[pixelIndex].green = top[pixelRow][pixelCol].green;
topTile.pixels[pixelIndex].blue = top[pixelRow][pixelCol].blue;
topTile.pixels[pixelIndex].alpha = top[pixelRow][pixelCol].alpha;
}
decompiledTiles.tiles.push_back(topTile);
topTiles.push_back(topTile);
}

// If we are in dual-layer mode, we need to generate errors if the user specified content on all three layers
if (!ctx.compilerConfig.tripleLayer) {
for (std::size_t i = 0; i < bottomTiles.size(); i++) {
auto bottomTile = bottomTiles.at(i);
auto middleTile = middleTiles.at(i);
auto topTile = topTiles.at(i);
if (!bottomTile.transparent(ctx.compilerConfig.transparencyColor) &&
!middleTile.transparent(ctx.compilerConfig.transparencyColor) &&
!topTile.transparent(ctx.compilerConfig.transparencyColor)) {
// TODO : better error context
throw PtException{"all three tiles had content but dual layer mode"};
}
}
}
}

if (ctx.err.errCount > 0) {
die_errorCount(ctx.err, ctx.inputPaths.modeBasedInputPath(ctx.compilerConfig.mode),
"errors generated during layered tile import");
}

return decompiledTiles;
Expand Down Expand Up @@ -205,18 +231,18 @@ void importAnimTiles(PtContext &ctx, const std::vector<std::vector<AnimationPng<

std::size_t pngWidthInTiles = rawFrame.png.get_width() / TILE_SIDE_LENGTH;
std::size_t pngHeightInTiles = rawFrame.png.get_height() / TILE_SIDE_LENGTH;
for (size_t tileIndex = 0; tileIndex < pngWidthInTiles * pngHeightInTiles; tileIndex++) {
size_t tileRow = tileIndex / pngWidthInTiles;
size_t tileCol = tileIndex % pngWidthInTiles;
for (std::size_t tileIndex = 0; tileIndex < pngWidthInTiles * pngHeightInTiles; tileIndex++) {
std::size_t tileRow = tileIndex / pngWidthInTiles;
std::size_t tileCol = tileIndex % pngWidthInTiles;
RGBATile tile{};
tile.type = TileType::ANIM;
tile.anim = rawFrame.animName;
tile.frame = rawFrame.frame;
tile.tileIndex = tileIndex;

for (size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
size_t pixelRow = (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
size_t pixelCol = (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
for (std::size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
std::size_t pixelRow = (tileRow * TILE_SIDE_LENGTH) + (pixelIndex / TILE_SIDE_LENGTH);
std::size_t pixelCol = (tileCol * TILE_SIDE_LENGTH) + (pixelIndex % TILE_SIDE_LENGTH);
tile.pixels[pixelIndex].red = rawFrame.png[pixelRow][pixelCol].red;
tile.pixels[pixelIndex].green = rawFrame.png[pixelRow][pixelCol].green;
tile.pixels[pixelIndex].blue = rawFrame.png[pixelRow][pixelCol].blue;
Expand Down
4 changes: 2 additions & 2 deletions src/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace porytiles {
static RGBATile uniformTile(const RGBA32 &color) noexcept
{
RGBATile tile{};
for (size_t i = 0; i < TILE_NUM_PIX; i++) {
for (std::size_t i = 0; i < TILE_NUM_PIX; i++) {
tile.pixels[i] = color;
}
return tile;
Expand All @@ -19,7 +19,7 @@ static RGBATile uniformTile(const RGBA32 &color) noexcept
static GBATile uniformTile(const uint8_t &index) noexcept
{
GBATile tile{};
for (size_t i = 0; i < TILE_NUM_PIX; i++) {
for (std::size_t i = 0; i < TILE_NUM_PIX; i++) {
tile.colorIndexes[i] = index;
}
return tile;
Expand Down

0 comments on commit 84ec393

Please sign in to comment.