diff options
Diffstat (limited to 'src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp')
| -rw-r--r-- | src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp b/src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp new file mode 100644 index 00000000..7c6da1b0 --- /dev/null +++ b/src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp @@ -0,0 +1,132 @@ +#include "KingSystem/Resource/Actor/resResourceAnimInfo.h" +#include "KingSystem/Utils/Byaml/Byaml.h" +#include "KingSystem/Utils/SafeDelete.h" + +namespace ksys::res { + +AnimInfo::AnimInfo() : ParamIO("animinfo", 0) {} + +AnimInfo::~AnimInfo() { + mAnims.freeBuffer(); + + if (mSwordBlurInfo) { + mSwordBlurInfo->finalize(); + util::safeDelete(mSwordBlurInfo); + } +} + +void AnimInfo::SwordBlurInfo::finalize() { + if (!entries) + return; + + for (int i = 0; i < num_entries; ++i) { + SwordBlur& entry = entries[i]; + auto* h = heap; + if (entry.frames) { + h->free(entry.frames); + entry.frames = nullptr; + } + if (entry._18) { + h->free(entry._18); + entry._18 = nullptr; + } + } + + heap->free(entries); + entries = nullptr; +} + +void AnimInfo::doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) {} + +bool AnimInfo::parse_(u8* data, size_t size, sead::Heap* heap) { + al::ByamlIter root_iter{data}; + + const int num_entries = root_iter.getSize(); + int num_anims = num_entries - 1; + if (num_entries < 1) + return true; + + al::ByamlIter iter; + int double_attack_anm_num = 0; + int num = 0; + bool allocate_anims = false; + if (root_iter.isExistKey("_sword_blur")) { + iter = root_iter.getIterByKey("_sword_blur"); + const int num_sword_blurs = iter.getSize(); + iter.tryGetIntByKey(&double_attack_anm_num, "double_attack_anm_num"); + num = num_sword_blurs - 1; + if (num_entries > 1) + allocate_anims = true; + } else { + num = 0; + num_anims = num_entries; + allocate_anims = true; + } + + if (allocate_anims) { + if (!mAnims.tryAllocBuffer(num_anims, heap)) + return false; + + for (int i = 0; i < num_anims; ++i) { + auto& anim = mAnims[i]; + anim.scale.e.fill(0.0); + + al::ByamlIter entry_iter; + if (root_iter.tryGetIterByIndex(&entry_iter, i)) { + const char* name_c; + if (root_iter.getKeyName(&name_c, i)) { + if (std::strcmp(name_c, "_sword_blur") == 0) + continue; + anim.name = name_c; + } else { + anim.name = ""; + } + entry_iter.tryGetFloatByKey(&anim.scale.x, "scaleX"); + entry_iter.tryGetFloatByKey(&anim.scale.y, "scaleY"); + entry_iter.tryGetFloatByKey(&anim.scale.z, "scaleZ"); + } else { + anim.name = ""; + } + } + } + + if (num >= 1) { + if (!mSwordBlurInfo) { + auto* info = new (heap) SwordBlurInfo; + info->entries = nullptr; + mSwordBlurInfo = info; + info->heap = heap; + info->num_entries = double_attack_anm_num; + /// @bug SwordBlur is not trivially constructible and not trivially copyable. + /// The only reason using SwordBlur::name doesn't crash is that Clang and GHS + /// are smart enough to devirtualize sead::SafeString virtual function calls, + /// which removes the need to go through the vtable. +#ifdef AVOID_UB + info->entries = new (heap) SwordBlur[info->num_entries]; +#else + info->entries = static_cast<SwordBlur*>( + heap->tryAlloc(sizeof(SwordBlur) * info->num_entries, alignof(SwordBlur))); + std::memset(info->entries, 0, sizeof(SwordBlur) * info->num_entries); +#endif + } + + // TODO / FIXME: finish this + } + + return true; +} + +const AnimInfo::Anim* AnimInfo::getAnim(const sead::SafeString& name) const { + const auto idx = findAnimIndex(name); + if (idx < 0) + return nullptr; + return &mAnims[idx]; +} + +int AnimInfo::findAnimIndex(const sead::SafeString& name) const { + return mAnims.binarySearch( + name, + +[](const Anim& anim, const sead::SafeString& key) { return anim.name.compare(key); }); +} + +} // namespace ksys::res |
