summaryrefslogtreecommitdiff
path: root/src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-06-15 17:47:03 +0200
committerLéo Lam <leo@leolam.fr>2021-06-15 18:04:39 +0200
commitdd0cc52ce99b9d78f1c7022c1bf13349149f263a (patch)
tree2eb5acd7d704d612181399bd8ab2be7b84fe450f /src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp
parent38e5e47b07696a0954145bf68148cb0301cf133c (diff)
ksys: Move ActorParam classes into separate folder to declutter Resource/
Diffstat (limited to 'src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp')
-rw-r--r--src/KingSystem/Resource/Actor/resResourceAnimInfo.cpp132
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