diff --git a/texture.cpp b/texture.cpp index 9ad1d9b..71b5cd6 100644 --- a/texture.cpp +++ b/texture.cpp @@ -170,7 +170,7 @@ static void analyze_texture(unsigned char* texBytes, int numBytes, const Color p desaturate(outTexture.dominantColor.channel, outTexture.dominantColor.channel); } -bool process_textures(const world_t* world, TextureList& outTextures) // TODO: return TextureDescriptor structs, including average texture color +bool process_textures(const world_t* world, TextureList& outTextures) { using spaces_type = rectpack2D::empty_spaces; using rect_type = rectpack2D::output_rect_t; @@ -259,6 +259,8 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r printf("Constructing texture atlas...\n"); + std::unordered_map> animationFrames; + // Try to construct the texture atlas, see what we get for (int texNum = 0; texNum < world->mipheader.numtex; ++texNum) { @@ -269,10 +271,6 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r continue; } - char* outName = miptex->name; - if (*outName == '*' || *outName == '+') - outName++; - TextureDescriptor tex = { 0 }; for (int mipLevel = 0; mipLevel < 4; ++mipLevel) @@ -290,14 +288,33 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r tex.w = (u_char)rectangle.w; tex.h = (u_char)rectangle.h; - + u_short x = (rectangle.x / 2) + outTim.imgXoffs; // Divide by 2 to get the coordinate in 16-bit pixel units u_short y = rectangle.y + outTim.imgYoffs; tex.ps1tex.tpage = getTPage(outTim.format, 0, x, y); tex.uoffs = (u_char)((x % 64) << (2 - outTim.format)); tex.voffs = (u_char)(y & 0xFF); - // TODO: animated textures + + if (miptex->name[0] == '+') + { + // Animated texture + int frameNum = miptex->name[1] - '0'; + if (frameNum >= 0 && frameNum <= 9) + { + std::string animName = &miptex->name[2]; + animationFrames[animName][frameNum] = texNum; + } + else + { + frameNum = miptex->name[1] - 'a'; + if (frameNum >= 0 && frameNum <= 9) + { + std::string animName = std::string(&miptex->name[2]) + "_alt"; + animationFrames[animName][frameNum] = texNum; + } + } + } } } @@ -307,6 +324,24 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r outTextures.push_back(tex); } + // Link animated texture frames together + for (auto animIter = animationFrames.cbegin(); animIter != animationFrames.cend(); ++animIter) + { + const auto& frames = animIter->second; + for (auto frameIter = frames.cbegin(); frameIter != frames.cend(); ++frameIter) + { + int frameNum = frameIter->first; + int texNum = frameIter->second; + auto& texture = outTextures[texNum]; + + const auto& nextFrameIter = frames.find(frameNum + 1); + if (nextFrameIter != frames.cend()) + texture.ps1tex.nextframe = nextFrameIter->second; + else + texture.ps1tex.nextframe = frames.find(0)->second; + } + } + sprintf_s(path, _MAX_PATH, "atlas-%s.tim", world->name); tim::ExportFile(path, &outTim);