#ifndef _DNAMP1_ANIM_HPP_ #define _DNAMP1_ANIM_HPP_ #include "hecl/Blender/BlenderConnection.hpp" #include "DNAMP1.hpp" #include "../DNACommon/ANIM.hpp" #include "DataSpec/DNACommon/RigInverter.hpp" #include "CINF.hpp" namespace DataSpec { namespace DNAMP1 { struct ANIM : BigDNA { Delete expl; struct IANIM : BigDNA { Delete expl; atUint32 m_version; IANIM(atUint32 version) : m_version(version) {} std::vector> bones; std::vector frames; std::vector channels; std::vector> chanKeys; float mainInterval = 0.0; UniqueID32 evnt; bool looping = false; void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter& rig) const; }; struct ANIM0 : IANIM { DECL_EXPLICIT_DNA ANIM0() : IANIM(0) {} struct Header : BigDNA { DECL_DNA Value duration; Value unk0; Value interval; Value unk1; Value keyCount; Value unk2; Value boneSlotCount; }; }; struct ANIM2 : IANIM { DECL_EXPLICIT_DNA ANIM2(bool pc) : IANIM(pc ? 3 : 2) {} struct Header : BigDNA { DECL_DNA Value scratchSize; UniqueID32 evnt; Value unk0 = 1; Value duration; Value interval; Value rootBoneId = 3; Value looping = 0; Value rotDiv; Value translationMult; Value boneChannelCount; Value unk3; Value keyBitmapBitCount; }; struct ChannelDesc : BigDNA { Delete expl; Value id = 0; Value keyCount1 = 0; Value initRX = 0; Value qRX = 0; Value initRY = 0; Value qRY = 0; Value initRZ = 0; Value qRZ = 0; Value keyCount2 = 0; Value initTX = 0; Value qTX = 0; Value initTY = 0; Value qTY = 0; Value initTZ = 0; Value qTZ = 0; void read(athena::io::IStreamReader& reader) { id = reader.readUint32Big(); keyCount1 = reader.readUint16Big(); initRX = reader.readInt16Big(); qRX = reader.readUByte(); initRY = reader.readInt16Big(); qRY = reader.readUByte(); initRZ = reader.readInt16Big(); qRZ = reader.readUByte(); keyCount2 = reader.readUint16Big(); if (keyCount2) { initTX = reader.readInt16Big(); qTX = reader.readUByte(); initTY = reader.readInt16Big(); qTY = reader.readUByte(); initTZ = reader.readInt16Big(); qTZ = reader.readUByte(); } } void write(athena::io::IStreamWriter& writer) const { writer.writeUint32Big(id); writer.writeUint16Big(keyCount1); writer.writeInt16Big(initRX); writer.writeUByte(qRX); writer.writeInt16Big(initRY); writer.writeUByte(qRY); writer.writeInt16Big(initRZ); writer.writeUByte(qRZ); writer.writeUint16Big(keyCount2); if (keyCount2) { writer.writeInt16Big(initTX); writer.writeUByte(qTX); writer.writeInt16Big(initTY); writer.writeUByte(qTY); writer.writeInt16Big(initTZ); writer.writeUByte(qTZ); } } size_t binarySize(size_t __isz) const { __isz += 17; if (keyCount2) __isz += 9; return __isz; } }; struct ChannelDescPC : BigDNA { Delete expl; Value id = 0; Value keyCount1 = 0; Value QinitRX = 0; Value QinitRY = 0; Value QinitRZ = 0; Value keyCount2 = 0; Value QinitTX = 0; Value QinitTY = 0; Value QinitTZ = 0; void read(athena::io::IStreamReader& reader) { id = reader.readUint32Big(); keyCount1 = reader.readUint32Big(); QinitRX = reader.readUint32Big(); QinitRY = reader.readUint32Big(); QinitRZ = reader.readUint32Big(); keyCount2 = reader.readUint32Big(); if (keyCount2) { QinitTX = reader.readUint32Big(); QinitTY = reader.readUint32Big(); QinitTZ = reader.readUint32Big(); } } void write(athena::io::IStreamWriter& writer) const { writer.writeUint32Big(id); writer.writeUint32Big(keyCount1); writer.writeUint32Big(QinitRX); writer.writeUint32Big(QinitRY); writer.writeUint32Big(QinitRZ); writer.writeUint32Big(keyCount2); if (keyCount2) { writer.writeUint32Big(QinitTX); writer.writeUint32Big(QinitTY); writer.writeUint32Big(QinitTZ); } } size_t binarySize(size_t __isz) const { __isz += 24; if (keyCount2) __isz += 12; return __isz; } }; }; std::unique_ptr m_anim; void read(athena::io::IStreamReader& reader) { atUint32 version = reader.readUint32Big(); switch (version) { case 0: m_anim.reset(new struct ANIM0); m_anim->read(reader); break; case 2: m_anim.reset(new struct ANIM2(false)); m_anim->read(reader); break; case 3: m_anim.reset(new struct ANIM2(true)); m_anim->read(reader); break; default: Log.report(logvisor::Error, "unrecognized ANIM version"); break; } } void write(athena::io::IStreamWriter& writer) const { writer.writeUint32Big(m_anim->m_version); m_anim->write(writer); } size_t binarySize(size_t __isz) const { return m_anim->binarySize(__isz + 4); } void sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter& rig, bool) const { m_anim->sendANIMToBlender(os, rig); } bool isLooping() const { if (!m_anim) return false; return m_anim->looping; } using BlenderAction = hecl::BlenderConnection::DataStream::Actor::Action; ANIM() = default; ANIM(const BlenderAction& act, const std::unordered_map& idMap, const DNAANIM::RigInverter& rig, bool pc); }; } } #endif // _DNAMP1_ANIM_HPP_