← Back to file list Raw

src/CAnimationCompiler.cpp

#include "CAnimationCompiler.h"
#include "CBinaryFile.h"
#include "CScopeExit.h"
#include "U_Log.h"
#include "U_Files.h"
#include <fstream>
bool CAnimationCompiler::CompileAnimation(const std::filesystem::path& srcpath)
{
std::ifstream objfile(srcpath);
if (!objfile.is_open()) { return false; }
CScopeExit streamExiter([&objfile]() { objfile.close(); });
std::filesystem::path outpath = FileUtils::get_executable_path() / "resources" / "anim" / (srcpath.stem().string() + ".eanm");
CBinaryFile outfile(outpath, false); //closed on destructor
if(!outfile.IsOpen()) { return false; }
size_t FramesCount = 100, BonesCount = 1;
double FPS = 30.0;
struct Bone
{
std::string Name;
glm::mat4 Matrix = glm::mat4(1.0f);
};
struct Frame
{
size_t FrameIndex = 0;
std::vector<std::string> Events; //events are being fired with interp argument and time of anim
std::vector<Bone> Bones;
void reset()
{
FrameIndex = 0;
Events.clear();
Bones.clear();
}
};
std::vector<Frame> Frames;
Frame curFrame;
std::string ReadLine;
while (!objfile.eof())
{
std::getline(objfile, ReadLine, '\n');
if(StringUtils::IsEmpty(ReadLine) || ReadLine.at(0) == '#') { continue; }
if(StringUtils::StartsWith(ReadLine, "frames:"))
{
auto splitted = StringUtils::split_str(ReadLine, ':');
if(splitted.size() < 2) { continue; }
auto removed = StringUtils::RemoveSpaces(splitted.at(1));
FramesCount = StringUtils::FromStr<size_t>(removed);
}
else if(StringUtils::StartsWith(ReadLine, "fps:"))
{
auto splitted = StringUtils::split_str(ReadLine, ':');
if(splitted.size() < 2) { continue; }
auto removed = StringUtils::RemoveSpaces(splitted.at(1));
FPS = StringUtils::FromStr<double>(removed);
}
else if(StringUtils::StartsWith(ReadLine, "bones:"))
{
auto splitted = StringUtils::split_str(ReadLine, ':');
if(splitted.size() < 2) { continue; }
auto removed = StringUtils::RemoveSpaces(splitted.at(1));
BonesCount = StringUtils::FromStr<size_t>(removed);
}
else if(StringUtils::StartsWith(ReadLine, "events:"))
{
if(!curFrame.Bones.empty()) //valid frame
{
curFrame.FrameIndex = Frames.size();
Frames.push_back(std::move(curFrame)); //std::move?
Log::Instance() << "Added frame #" << Frames.size() - 1 << Log::Endl;
curFrame.reset();
}
else
{
Log::Instance() << "empty bones" << Log::Endl;
}
auto splitted = StringUtils::split_str(ReadLine, ':');
if(splitted.size() < 2) { continue; }
if(StringUtils::IsEmpty(splitted.at(1))) { continue; }
auto removed = StringUtils::RemoveSpaces(splitted.at(1));
auto splitted_spaces = StringUtils::split_str(removed, ' ');
for(auto& s : splitted_spaces)
{
curFrame.Events.push_back(s);
Log::Instance() << "Added event \"" << s << "\"\n";
}
}
else
{
auto removed = StringUtils::RemoveSpaces(ReadLine);
auto splitted = StringUtils::split_str(removed, ' ');
if(splitted.size() != 17) { continue; }
Bone bone;
bone.Name = splitted.at(0);
for (size_t y = 0; y < glm::mat4::length(); y++)
{
for (size_t x = 0; x < glm::mat4::length(); x++)
{
bone.Matrix[x][y] = StringUtils::FromStr<float>(splitted.at((x + (y * glm::mat4::length())) + 1));
}
}
//Log::Instance() << "at Frame #" << Frames.size() << Log::Endl;
//Log::Instance() << "Bone \"" << bone.Name << "\" with matrix " << glm::determinant(bone.Matrix) << Log::Endl;
curFrame.Bones.push_back(std::move(bone));
}
}
if(!curFrame.Bones.empty()) //valid frame
{
curFrame.FrameIndex = Frames.size();
Frames.push_back(std::move(curFrame)); //std::move?
Log::Instance() << "Added frame #" << Frames.size() - 1 << Log::Endl;
}
//FramesCount isn't necessary to be stated manually
outfile.Write<std::uint32_t>(Frames.size());
outfile.Write<double>(FPS);
//outfile.Write<std::uint16_t>(BonesCount); //bones count doesn't matter
for(auto& frame : Frames)
{
outfile.Write<std::uint8_t>(frame.Events.size());
outfile.Write<std::uint16_t>(frame.Bones.size());
for(auto& event : frame.Events)
{
outfile.WriteLenString<std::uint8_t>(event);
}
for(auto& bone : frame.Bones)
{
outfile.WriteLenString<std::uint8_t>(bone.Name);
outfile.Write<glm::mat4>(bone.Matrix);
}
}
Log::Instance() << "FramesCount var is " << FramesCount << Log::Endl;
Log::Instance() << "Actual frames count is " << Frames.size() << Log::Endl;
Log::Instance() << "FPS is " << FPS << Log::Endl;
Log::Instance() << "Bones count is " << BonesCount << Log::Endl;
Log::Instance() << "Animation compiled!\n";
return true;
}