Skip to content

Commit

Permalink
Compiled anims now imported
Browse files Browse the repository at this point in the history
  • Loading branch information
grunt-lucas committed Sep 15, 2023
1 parent aa85973 commit b2db41a
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 27 deletions.
4 changes: 2 additions & 2 deletions include/errors_warnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void internalerror_unknownDecompilerMode(std::string context);
void error_freestandingDimensionNotDivisibleBy8(ErrorsAndWarnings &err, const CompilerSourcePaths &srcs,
std::string dimensionName, png::uint_32 dimension);

void error_animDimensionNotDivisibleBy8(ErrorsAndWarnings &err, std::string animName, std::string frame,
void error_animDimensionNotDivisibleBy8(ErrorsAndWarnings &err, std::string animName, std::string frameName,
std::string dimensionName, png::uint_32 dimension);

void error_layerHeightNotDivisibleBy16(ErrorsAndWarnings &err, TileLayer layer, png::uint_32 height);
Expand Down Expand Up @@ -153,7 +153,7 @@ void fatalerror_tooManyUniqueColorsTotal(const ErrorsAndWarnings &err, const Com
CompilerMode mode, std::size_t allowed, std::size_t found);

void fatalerror_animFrameDimensionsDoNotMatchOtherFrames(const ErrorsAndWarnings &err, const CompilerSourcePaths &srcs,
CompilerMode mode, std::string animName, std::string frame,
CompilerMode mode, std::string animName, std::string frameName,
std::string dimensionName, png::uint_32 dimension);

void fatalerror_tooManyUniqueTiles(const ErrorsAndWarnings &err, const CompilerSourcePaths &srcs, CompilerMode mode,
Expand Down
9 changes: 6 additions & 3 deletions include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ constexpr std::uint8_t INVALID_INDEX_PIXEL_VALUE = 255;
template <typename T> struct AnimationPng {
png::image<T> png;
std::string animName;
std::string frame;
std::string frameName;

AnimationPng(png::image<T> png, std::string animName, std::string frame) : png{png}, animName{animName}, frame{frame}
AnimationPng(png::image<T> png, std::string animName, std::string frameName)
: png{png}, animName{animName}, frameName{frameName}
{
}
};
Expand Down Expand Up @@ -714,6 +715,8 @@ struct CompilerSourcePaths {
return path / "top.png";
}

// FIXME : dir name should be 'anim' not 'anims'

std::filesystem::path primaryAnims() const
{
std::filesystem::path path{primarySourcePath};
Expand Down Expand Up @@ -779,7 +782,7 @@ struct DecompilerSourcePaths {
std::filesystem::path primaryAnims() const
{
std::filesystem::path path{primarySourcePath};
return path / "anims";
return path / "anim";
}

std::filesystem::path modeBasedSrcPath(DecompilerMode mode) const;
Expand Down
19 changes: 13 additions & 6 deletions src/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,19 @@ prepareDecompiledAnimsForImport(PtContext &ctx, std::filesystem::path animationP
for (const auto &frameFile : std::filesystem::directory_iterator(animDir)) {
std::string fileName = frameFile.path().filename().string();
std::string extension = frameFile.path().extension().string();
/*
* FIXME : format is actually 0.png, not 00.png. We used 00.png so that default alphabetical
* order would also yield the frame order. However, the frames don't actually follow this
* format. It would be better to read and then sort, especially since the decompiler has to
* use the 0.png format.
*/
if (!std::regex_match(fileName, std::regex("^[0-9][0-9]\\.png$"))) {
if (fileName != "key.png") {
pt_logln(ctx, stderr, "skipping file: {}", frameFile.path().string());
}
continue;
}
std::size_t index = std::stoi(fileName, 0, 10) + 1;
std::size_t index = std::stoi(fileName, nullptr, 10) + 1;
frames.insert(std::pair{index, frameFile.path()});
pt_logln(ctx, stderr, "found frame file: {}, index={}", frameFile.path().string(), index);
}
Expand Down Expand Up @@ -372,26 +378,27 @@ prepareCompiledAnimsForImport(PtContext &ctx, std::filesystem::path animationPat
for (const auto &frameFile : std::filesystem::directory_iterator(animDir)) {
std::string fileName = frameFile.path().filename().string();
std::string extension = frameFile.path().extension().string();
if (!std::regex_match(fileName, std::regex("^[0-9][0-9]\\.png$"))) {
if (!std::regex_match(fileName, std::regex("^[0-9]\\.png$")) &&
!std::regex_match(fileName, std::regex("^[0-9][0-9]\\.png$"))) {
pt_logln(ctx, stderr, "skipping file: {}", frameFile.path().string());
continue;
}
std::size_t index = std::stoi(fileName, 0, 10) + 1;
std::size_t index = std::stoi(fileName, nullptr, 10) + 1;
frames.insert(std::pair{index, frameFile.path()});
pt_logln(ctx, stderr, "found frame file: {}, index={}", frameFile.path().string(), index);
}

std::vector<AnimationPng<png::index_pixel>> framePngs{};
if (frames.size() == 0) {
// TODO : better error
throw std::runtime_error{"TODO : error for import decompiled anims"};
throw std::runtime_error{"TODO : error for import decompiled anims frames.size() == 0"};
// fatalerror_missingRequiredAnimFrameFile(ctx.err, ctx.compilerSrcPaths, ctx.compilerConfig.mode,
// animDir.filename().string(), 0);
}
for (std::size_t i = 1; i <= frames.size(); i++) {
if (!frames.contains(i)) {
// TODO : better error
throw std::runtime_error{"TODO : error for import decompiled anims"};
throw std::runtime_error{"TODO : error for import decompiled anims !frames.contains(i)"};
// fatalerror_missingRequiredAnimFrameFile(ctx.err, ctx.compilerSrcPaths, ctx.compilerConfig.mode,
// animDir.filename().string(), i - 1);
}
Expand All @@ -404,7 +411,7 @@ prepareCompiledAnimsForImport(PtContext &ctx, std::filesystem::path animationPat
}
catch (const std::exception &exception) {
// TODO : better error
throw std::runtime_error{"TODO : error for import decompiled anims"};
throw std::runtime_error{fmt::format("TODO : error for import decompiled anims, frame index {} was not PNG", i)};
// error_animFrameWasNotAPng(ctx.err, animDir.filename().string(), frames.at(i).filename().string());
}
}
Expand Down
87 changes: 71 additions & 16 deletions src/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,14 @@ void importAnimTiles(PtContext &ctx, const std::vector<std::vector<AnimationPng<
std::string animName = rawAnim.at(0).animName;
DecompiledAnimation anim{animName};
for (const auto &rawFrame : rawAnim) {
DecompiledAnimFrame animFrame{rawFrame.frame};
DecompiledAnimFrame animFrame{rawFrame.frameName};

if (rawFrame.png.get_height() % TILE_SIDE_LENGTH != 0) {
error_animDimensionNotDivisibleBy8(ctx.err, rawFrame.animName, rawFrame.frame, "height",
error_animDimensionNotDivisibleBy8(ctx.err, rawFrame.animName, rawFrame.frameName, "height",
rawFrame.png.get_height());
}
if (rawFrame.png.get_width() % TILE_SIDE_LENGTH != 0) {
error_animDimensionNotDivisibleBy8(ctx.err, rawFrame.animName, rawFrame.frame, "width",
error_animDimensionNotDivisibleBy8(ctx.err, rawFrame.animName, rawFrame.frameName, "width",
rawFrame.png.get_width());
}

Expand All @@ -372,12 +372,12 @@ void importAnimTiles(PtContext &ctx, const std::vector<std::vector<AnimationPng<
frameHeights.insert(rawFrame.png.get_height());
if (frameWidths.size() != 1) {
fatalerror_animFrameDimensionsDoNotMatchOtherFrames(ctx.err, ctx.compilerSrcPaths, ctx.compilerConfig.mode,
rawFrame.animName, rawFrame.frame, "width",
rawFrame.animName, rawFrame.frameName, "width",
rawFrame.png.get_width());
}
if (frameHeights.size() != 1) {
fatalerror_animFrameDimensionsDoNotMatchOtherFrames(ctx.err, ctx.compilerSrcPaths, ctx.compilerConfig.mode,
rawFrame.animName, rawFrame.frame, "height",
rawFrame.animName, rawFrame.frameName, "height",
rawFrame.png.get_height());
}

Expand All @@ -389,7 +389,7 @@ void importAnimTiles(PtContext &ctx, const std::vector<std::vector<AnimationPng<
RGBATile tile{};
tile.type = TileType::ANIM;
tile.anim = rawFrame.animName;
tile.frame = rawFrame.frame;
tile.frame = rawFrame.frameName;
tile.tileIndex = tileIndex;

for (std::size_t pixelIndex = 0; pixelIndex < TILE_NUM_PIX; pixelIndex++) {
Expand Down Expand Up @@ -804,21 +804,65 @@ importCompiledMetatileAttributes(PtContext &ctx, std::ifstream &metatileAttribut
return attributesMap;
}

// TODO : make this static
std::vector<CompiledAnimation>
importCompiledAnimations(PtContext &ctx, const std::vector<std::vector<AnimationPng<png::index_pixel>>> &compiledAnims)
static std::vector<CompiledAnimation>
importCompiledAnimations(PtContext &ctx, const std::vector<std::vector<AnimationPng<png::index_pixel>>> &rawAnims)
{
std::vector<CompiledAnimation> anims{};

for (const auto &frames : compiledAnims) {
if (frames.size() == 0) {
for (const auto &rawAnim : rawAnims) {
std::set<png::uint_32> frameWidths{};
std::set<png::uint_32> frameHeights{};
if (rawAnim.size() == 0) {
internalerror("importer::importCompiledAnimations frames.size() was 0");
}
CompiledAnimation anim{frames.at(0).animName};
for (const auto &frame : frames) {
// TODO : impl importCompiledAnimations
CompiledAnimation compiledAnim{rawAnim.at(0).animName};
for (const auto &animPng : rawAnim) {
CompiledAnimFrame animFrame{animPng.frameName};

if (animPng.png.get_height() % TILE_SIDE_LENGTH != 0) {
// TODO : fill in real error
throw std::runtime_error{"TODO : frame.png.get_height() % TILE_SIDE_LENGTH != 0"};
// error_animDimensionNotDivisibleBy8(ctx.err, frame.animName, frame.frameName, "height",
// frame.png.get_height());
}
if (animPng.png.get_width() % TILE_SIDE_LENGTH != 0) {
// TODO : fill in real error
throw std::runtime_error{"TODO : frame.png.get_width() % TILE_SIDE_LENGTH != 0"};
// error_animDimensionNotDivisibleBy8(ctx.err, frame.animName, frame.frameName, "width", frame.png.get_width());
}

frameWidths.insert(animPng.png.get_width());
frameHeights.insert(animPng.png.get_height());
if (frameWidths.size() != 1) {
// TODO : fill in real error
throw std::runtime_error{"TODO : frameWidths.size() != 1"};
// fatalerror_animFrameDimensionsDoNotMatchOtherFrames(ctx.err, ctx.compilerSrcPaths, ctx.compilerConfig.mode,
// frame.animName, frame.frameName, "width",
// frame.png.get_width());
}
if (frameHeights.size() != 1) {
// TODO : fill in real error
throw std::runtime_error{"TODO : frameHeights.size() != 1"};
// fatalerror_animFrameDimensionsDoNotMatchOtherFrames(ctx.err, ctx.compilerSrcPaths, ctx.compilerConfig.mode,
// frame.animName, frame.frameName, "height",
// frame.png.get_height());
}

std::size_t pngWidthInTiles = animPng.png.get_width() / TILE_SIDE_LENGTH;
std::size_t pngHeightInTiles = animPng.png.get_height() / TILE_SIDE_LENGTH;
for (std::size_t tileIndex = 0; tileIndex < pngWidthInTiles * pngHeightInTiles; tileIndex++) {
std::size_t tileRow = tileIndex / pngWidthInTiles;
std::size_t tileCol = tileIndex % pngWidthInTiles;
GBATile tile{};
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.colorIndexes[pixelIndex] = animPng.png[pixelRow][pixelCol];
}
animFrame.tiles.push_back(tile);
}
compiledAnim.frames.push_back(animFrame);
}
anims.push_back(anim);
anims.push_back(compiledAnim);
}

return anims;
Expand All @@ -838,6 +882,17 @@ importCompiledTileset(PtContext &ctx, std::ifstream &metatiles, std::ifstream &a
tileset.assignments = importCompiledMetatiles(ctx, metatiles, attributesMap);
tileset.anims = importCompiledAnimations(ctx, compiledAnims);

// for (const auto &anim : tileset.anims) {
// std::cout << "Found anim:" << std::endl;
// std::cout << anim.animName << std::endl;
// for (const auto &frame : anim.frames) {
// std::cout << frame.frameName << std::endl;
// }
// std::cout << "----------------" << std::endl;
// }

// TODO : perform key frame inference here

return {tileset, attributesMap};
}

Expand Down

0 comments on commit b2db41a

Please sign in to comment.