Index: ps/trunk/source/graphics/Model.h =================================================================== --- ps/trunk/source/graphics/Model.h +++ ps/trunk/source/graphics/Model.h @@ -32,7 +32,6 @@ class CObjectEntry; class CSkeletonAnim; class CSkeletonAnimDef; -class CSkeletonAnimManager; class CSimulation2; #define MODELFLAG_CASTSHADOWS (1<<0) @@ -77,7 +76,7 @@ public: // constructor - CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation); + CModel(CSimulation2& simulation); // destructor ~CModel(); @@ -188,21 +187,6 @@ } /** - * Load raw animation frame animation from given file, and build an - * animation specific to this model. - * @param pathname animation file to load - * @param name animation name (e.g. "idle") - * @param ID specific ID of the animation, to sync with props - * @param frequency influences the random choices - * @param speed animation speed as a factor of the default animation speed - * @param actionpos offset of 'action' event, in range [0, 1] - * @param actionpos2 offset of 'action2' event, in range [0, 1] - * @param sound offset of 'sound' event, in range [0, 1] - * @return new animation, or NULL on error - */ - CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, const CStr& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos); - - /** * Add a prop to the model on the given point. */ void AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry, float minHeight = 0.f, float maxHeight = 0.f, bool selectable = true); @@ -290,9 +274,6 @@ * If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop */ size_t m_AmmoLoadedProp; - - // manager object which can load animations for us - CSkeletonAnimManager& m_SkeletonAnimManager; }; #endif Index: ps/trunk/source/graphics/Model.cpp =================================================================== --- ps/trunk/source/graphics/Model.cpp +++ ps/trunk/source/graphics/Model.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,7 +25,6 @@ #include "graphics/ObjectEntry.h" #include "graphics/SkeletonAnim.h" #include "graphics/SkeletonAnimDef.h" -#include "graphics/SkeletonAnimManager.h" #include "maths/BoundingBoxAligned.h" #include "maths/Quaternion.h" #include "lib/sysdep/rtl.h" @@ -40,10 +39,9 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Constructor -CModel::CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation) +CModel::CModel(CSimulation2& simulation) : m_Flags(0), m_Anim(NULL), m_AnimTime(0), m_Simulation(simulation), - m_BoneMatrices(NULL), m_AmmoPropPoint(NULL), m_AmmoLoadedProp(0), - m_SkeletonAnimManager(skeletonAnimManager) + m_BoneMatrices(NULL), m_AmmoPropPoint(NULL), m_AmmoLoadedProp(0) { } @@ -199,43 +197,6 @@ } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// BuildAnimation: load raw animation frame animation from given file, and build a -// animation specific to this model -CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, const CStr& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos) -{ - CSkeletonAnimDef* def = m_SkeletonAnimManager.GetAnimation(pathname); - if (!def) - return NULL; - - CSkeletonAnim* anim = new CSkeletonAnim(); - anim->m_Name = name; - anim->m_ID = ID; - anim->m_Frequency = frequency; - anim->m_AnimDef = def; - anim->m_Speed = speed; - - if (actionpos == -1.f) - anim->m_ActionPos = -1.f; - else - anim->m_ActionPos = actionpos * anim->m_AnimDef->GetDuration(); - - if (actionpos2 == -1.f) - anim->m_ActionPos2 = -1.f; - else - anim->m_ActionPos2 = actionpos2 * anim->m_AnimDef->GetDuration(); - - if (soundpos == -1.f) - anim->m_SoundPos = -1.f; - else - anim->m_SoundPos = soundpos * anim->m_AnimDef->GetDuration(); - - anim->m_ObjectBounds.SetEmpty(); - InvalidateBounds(); - - return anim; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Update: update this model to the given time, in msec void CModel::UpdateTo(float time) { @@ -533,7 +494,7 @@ // Clone: return a clone of this model CModelAbstract* CModel::Clone() const { - CModel* clone = new CModel(m_SkeletonAnimManager, m_Simulation); + CModel* clone = new CModel(m_Simulation); clone->m_ObjectBounds = m_ObjectBounds; clone->InitModel(m_pModelDef); clone->SetMaterial(m_Material); Index: ps/trunk/source/graphics/ObjectEntry.h =================================================================== --- ps/trunk/source/graphics/ObjectEntry.h +++ ps/trunk/source/graphics/ObjectEntry.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,6 +25,7 @@ class CSimulation2; #include +#include #include #include @@ -83,7 +84,7 @@ CSimulation2& m_Simulation; - typedef std::multimap SkeletonAnimMap; + using SkeletonAnimMap = std::multimap>; SkeletonAnimMap m_Animations; // TODO: something more memory-efficient than storing loads of similar strings for each unit? }; Index: ps/trunk/source/graphics/ObjectEntry.cpp =================================================================== --- ps/trunk/source/graphics/ObjectEntry.cpp +++ ps/trunk/source/graphics/ObjectEntry.cpp @@ -30,6 +30,7 @@ #include "graphics/ObjectManager.h" #include "graphics/ParticleManager.h" #include "graphics/SkeletonAnim.h" +#include "graphics/SkeletonAnimManager.h" #include "graphics/TextureManager.h" #include "lib/rand.h" #include "ps/CLogger.h" @@ -48,9 +49,6 @@ CObjectEntry::~CObjectEntry() { - for (const std::pair& anim : m_Animations) - delete anim.second; - delete m_Model; } @@ -130,7 +128,7 @@ } // delete old model, create new - CModel* model = new CModel(objectManager.GetSkeletonAnimManager(), m_Simulation); + CModel* model = new CModel(m_Simulation); delete m_Model; m_Model = model; model->SetMaterial(g_Renderer.GetSceneRenderer().GetMaterialManager().LoadMaterial(m_Base->m_Material)); @@ -169,7 +167,7 @@ if (it->second.m_FileName.empty()) continue; - CSkeletonAnim* anim = model->BuildAnimation( + std::unique_ptr anim = objectManager.GetSkeletonAnimManager().BuildAnimation( it->second.m_FileName, name, it->second.m_ID, @@ -179,13 +177,13 @@ it->second.m_ActionPos2, it->second.m_SoundPos); if (anim) - m_Animations.insert(std::make_pair(name, anim)); + m_Animations.emplace(name, std::move(anim)); } // ensure there's always an idle animation if (m_Animations.find("idle") == m_Animations.end()) { - CSkeletonAnim* anim = new CSkeletonAnim(); + std::unique_ptr anim = std::make_unique(); anim->m_Name = "idle"; anim->m_ID = ""; anim->m_AnimDef = NULL; @@ -194,10 +192,10 @@ anim->m_ActionPos = 0.f; anim->m_ActionPos2 = 0.f; anim->m_SoundPos = 0.f; - m_Animations.insert(std::make_pair("idle", anim)); + SkeletonAnimMap::const_iterator it = m_Animations.emplace("idle", std::move(anim)); // Ignore errors, since they're probably saying this is a non-animated model - model->SetAnimation(anim); + model->SetAnimation(it->second.get()); } else { @@ -302,7 +300,7 @@ for (SkeletonAnimMap::const_iterator it = lower; it != upper; ++it) { if (ID.empty() || it->second->m_ID == ID) - anims.push_back(it->second); + anims.push_back(it->second.get()); } if (anims.empty()) @@ -310,7 +308,7 @@ lower = m_Animations.lower_bound("idle"); upper = m_Animations.upper_bound("idle"); for (SkeletonAnimMap::const_iterator it = lower; it != upper; ++it) - anims.push_back(it->second); + anims.push_back(it->second.get()); } ENSURE(!anims.empty()); Index: ps/trunk/source/graphics/SkeletonAnimManager.h =================================================================== --- ps/trunk/source/graphics/SkeletonAnimManager.h +++ ps/trunk/source/graphics/SkeletonAnimManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -29,6 +29,8 @@ class CColladaManager; class CSkeletonAnimDef; +class CSkeletonAnim; +class CStr8; /////////////////////////////////////////////////////////////////////////////// // CSkeletonAnimManager : owner class of all skeleton anims - manages creation, @@ -45,6 +47,21 @@ // refer to valid animation file CSkeletonAnimDef* GetAnimation(const VfsPath& pathname); + /** + * Load raw animation frame animation from given file, and build an + * animation specific to this model. + * @param pathname animation file to load + * @param name animation name (e.g. "idle") + * @param ID specific ID of the animation, to sync with props + * @param frequency influences the random choices + * @param speed animation speed as a factor of the default animation speed + * @param actionpos offset of 'action' event, in range [0, 1] + * @param actionpos2 offset of 'action2' event, in range [0, 1] + * @param sound offset of 'sound' event, in range [0, 1] + * @return new animation, or NULL on error + */ + std::unique_ptr BuildAnimation(const VfsPath& pathname, const CStr8& name, const CStr8& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos); + private: // map of all known animations. Value is NULL if it failed to load. std::unordered_map> m_Animations; Index: ps/trunk/source/graphics/SkeletonAnimManager.cpp =================================================================== --- ps/trunk/source/graphics/SkeletonAnimManager.cpp +++ ps/trunk/source/graphics/SkeletonAnimManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,8 +25,10 @@ #include "graphics/ColladaManager.h" #include "graphics/Model.h" +#include "graphics/SkeletonAnim.h" #include "graphics/SkeletonAnimDef.h" #include "ps/CLogger.h" +#include "ps/CStr.h" #include "ps/FileIo.h" /////////////////////////////////////////////////////////////////////////////// @@ -79,3 +81,40 @@ // Add to map, NULL if failed to load - we won't try loading it again return m_Animations.insert_or_assign(name, std::move(def)).first->second.get(); } + +/** + * BuildAnimation: load raw animation frame animation from given file, and build a + * animation specific to this model + */ +std::unique_ptr CSkeletonAnimManager::BuildAnimation(const VfsPath& pathname, const CStr8& name, const CStr8& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos) +{ + CSkeletonAnimDef* def = GetAnimation(pathname); + if (!def) + return nullptr; + + std::unique_ptr anim = std::make_unique(); + anim->m_Name = name; + anim->m_ID = ID; + anim->m_Frequency = frequency; + anim->m_AnimDef = def; + anim->m_Speed = speed; + + if (actionpos == -1.f) + anim->m_ActionPos = -1.f; + else + anim->m_ActionPos = actionpos * anim->m_AnimDef->GetDuration(); + + if (actionpos2 == -1.f) + anim->m_ActionPos2 = -1.f; + else + anim->m_ActionPos2 = actionpos2 * anim->m_AnimDef->GetDuration(); + + if (soundpos == -1.f) + anim->m_SoundPos = -1.f; + else + anim->m_SoundPos = soundpos * anim->m_AnimDef->GetDuration(); + + anim->m_ObjectBounds.SetEmpty(); + + return anim; +}