diff --git a/src/AnimGraph/AnimLibrary.h b/src/AnimGraph/AnimLibrary.h index bef2e34..71ad607 100644 --- a/src/AnimGraph/AnimLibrary.h +++ b/src/AnimGraph/AnimLibrary.h @@ -2,8 +2,8 @@ // Created by martin on 11.04.25. // -#ifndef ANIMATIONLIBRARY_H -#define ANIMATIONLIBRARY_H +#ifndef ANIMLIBRARY_H +#define ANIMLIBRARY_H #include @@ -12,29 +12,27 @@ #include "ozz/base/io/stream.h" #include "ozz/base/log.h" +/** Manage a set of animations used for an AnimGraph. + * + * By default it behaves like a resource that allows to resolve animation names to + * AnimationResources. However, it can also trigger loading of the referenced resources from their + * filenames. This only happens on-demand. + */ struct AnimLibrary { typedef std::map AnimationResourceMap; AnimationResourceMap mAnimations = {}; std::vector mManagedAnimations = {}; + static constexpr const char* EXTERNAL_ANIMATION = ""; AnimLibrary() = default; ~AnimLibrary() { Reset(); } - // Move operators. Needed to avoid duplicate frees on the managed animations. - AnimLibrary(AnimLibrary&& other) - : mAnimations(std::move(other.mAnimations)), - mManagedAnimations(std::move(other.mManagedAnimations)) {}; - AnimLibrary& operator=(AnimLibrary&& other) { - mAnimations = other.mAnimations; - mManagedAnimations = std::move(other.mManagedAnimations); - return *this; - } - bool AddAnimation( const std::string& name, ozz::animation::Animation* animation) { AnimationResource animation_resource; animation_resource.m_name = name; + animation_resource.m_filename = EXTERNAL_ANIMATION; animation_resource.m_animation = animation; mAnimations[name] = animation_resource; @@ -48,30 +46,9 @@ struct AnimLibrary { return false; } - ozz::animation::Animation* animation = new ozz::animation::Animation; - - assert(!filename.empty()); - ozz::io::File file(filename.c_str(), "rb"); - if (!file.opened()) { - ozz::log::Err() << "Failed to open animation file " << filename << "." - << std::endl; - return false; - } - ozz::io::IArchive archive(&file); - if (!archive.TestTag()) { - ozz::log::Err() << "Failed to load animation instance from file " - << filename << "." << std::endl; - return false; - } - - // Once the tag is validated, reading cannot fail. - archive >> *animation; - - mManagedAnimations.push_back(animation); - AnimationResource animation_resource; animation_resource.m_name = name; - animation_resource.m_animation = animation; + animation_resource.m_animation = nullptr; animation_resource.m_filename = filename; mAnimations[name] = animation_resource; @@ -88,6 +65,40 @@ struct AnimLibrary { mManagedAnimations.clear(); mAnimations.clear(); } + + void LoadAnimations() { + for (AnimationResourceMap::iterator iter = mAnimations.begin(); + iter != mAnimations.end(); + ++iter) { + if (iter->second.m_filename == EXTERNAL_ANIMATION) { + continue; + } + + if (iter->second.m_animation != nullptr) { + continue; + } + + assert(!iter->second.m_filename.empty()); + ozz::io::File file(iter->second.m_filename.c_str(), "rb"); + if (!file.opened()) { + ozz::log::Err() << "Failed to open animation file " + << iter->second.m_filename << "." << std::endl; + continue; + } + ozz::io::IArchive archive(&file); + if (!archive.TestTag()) { + ozz::log::Err() << "Failed to load animation instance from file " + << iter->second.m_filename << "." << std::endl; + continue; + } + + iter->second.m_animation = new ozz::animation::Animation; + + archive >> *iter->second.m_animation; + + mManagedAnimations.push_back(iter->second.m_animation); + } + } }; inline void to_json(nlohmann::json& j, const AnimLibrary& animation_library) { @@ -130,4 +141,4 @@ inline void from_json(const nlohmann::json& j, AnimLibrary& animation_library) { } } -#endif //ANIMATIONLIBRARY_H +#endif //ANIMLIBRARY_H diff --git a/tests/AnimDataTests.cc b/tests/AnimDataTests.cc index d323fbd..7b203c0 100644 --- a/tests/AnimDataTests.cc +++ b/tests/AnimDataTests.cc @@ -21,6 +21,10 @@ TEST_CASE("Serialize AnimLibrary", "[AnimLibrary]") { "translation_y", single_bone_testdata.animation_translate_y_resource.m_filename)); + // We're not actually doing anything with the animations, however loading them here ensures that + // when running valgrind a memory leak is detected. + library.LoadAnimations(); + // serialize json library_data; library_data = library;