diff --git a/src/graphics/render/NamedSkeletons.cpp b/src/graphics/render/NamedSkeletons.cpp index 35dd57ec7..c30278a9c 100644 --- a/src/graphics/render/NamedSkeletons.cpp +++ b/src/graphics/render/NamedSkeletons.cpp @@ -7,9 +7,9 @@ using namespace rigging; NamedSkeletons::NamedSkeletons() = default; std::shared_ptr NamedSkeletons::createSkeleton( - const std::string& name, const SkeletonConfig* config + const std::string& name, std::shared_ptr config ) { - auto skeleton = std::make_shared(config); + auto skeleton = std::make_shared(std::move(config)); skeletons[name] = skeleton; return skeleton; } diff --git a/src/graphics/render/NamedSkeletons.hpp b/src/graphics/render/NamedSkeletons.hpp index 4e4fb77a1..4982443b6 100644 --- a/src/graphics/render/NamedSkeletons.hpp +++ b/src/graphics/render/NamedSkeletons.hpp @@ -14,7 +14,8 @@ public: NamedSkeletons(); std::shared_ptr createSkeleton( - const std::string& name, const rigging::SkeletonConfig* config + const std::string& name, + std::shared_ptr config ); rigging::Skeleton* getSkeleton(const std::string& name); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e1f683b96..9f173eb38 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -113,7 +113,9 @@ WorldRenderer::WorldRenderer( content.getDefaults()["hand-skeleton"].asString() ); hands = std::make_unique( - assets, *modelBatch, skeletons->createSkeleton("hand", &skeletonConfig) + assets, + *modelBatch, + skeletons->createSkeleton("hand", skeletonConfig.shared_from_this()) ); shadowMapping = std::make_unique(level); debugLines = std::make_unique(level); diff --git a/src/logic/scripting/lua/libs/libentity.cpp b/src/logic/scripting/lua/libs/libentity.cpp index 0ae21f3c7..d2c0c4bc5 100644 --- a/src/logic/scripting/lua/libs/libentity.cpp +++ b/src/logic/scripting/lua/libs/libentity.cpp @@ -108,13 +108,13 @@ static int l_set_skeleton(lua::State* L) { } if (auto entity = get_entity(L, 1)) { std::string skeletonName = lua::require_string(L, 2); - auto rigConfig = assets->get(skeletonName); + auto rigConfig = assets->getShared(skeletonName); if (rigConfig == nullptr) { throw std::runtime_error( "skeleton not found '" + skeletonName + "'" ); } - entity->setRig(rigConfig); + entity->setRig(std::move(rigConfig)); } return 0; } diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index dbdaa1881..c98349f3c 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -155,7 +155,7 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { std::string skeletonName = skeleton->config->getName(); map.at("skeleton-name").get(skeletonName); if (skeletonName != skeleton->config->getName()) { - skeleton->config = assets->get(skeletonName); + skeleton->config = assets->getShared(skeletonName); } if (auto foundSkeleton = map.at(COMP_SKELETON)) { skeleton->deserialize(*foundSkeleton); @@ -470,7 +470,7 @@ void Entities::render( continue; } - const auto* rigConfig = skeleton.config; + const auto& rigConfig = skeleton.config; if (rigConfig) { rigConfig->render( assets, batch, skeleton, transform.rot, pos, size diff --git a/src/objects/Entity.cpp b/src/objects/Entity.cpp index e8c276dd2..0bf898351 100644 --- a/src/objects/Entity.cpp +++ b/src/objects/Entity.cpp @@ -37,15 +37,9 @@ rigging::Skeleton* Entity::getSkeleton() const { return registry.try_get(entity); } -void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { +void Entity::setRig(std::shared_ptr rigConfig) { auto& skeleton = registry.get(entity); - skeleton.config = rigConfig; - skeleton.pose.matrices.resize( - rigConfig->getBones().size(), glm::mat4(1.0f) - ); - skeleton.calculated.matrices.resize( - rigConfig->getBones().size(), glm::mat4(1.0f) - ); + skeleton.setConfig(std::move(rigConfig)); } dv::value Entity::serialize() const { diff --git a/src/objects/Entity.hpp b/src/objects/Entity.hpp index ef00a1bf2..960bdfc9a 100644 --- a/src/objects/Entity.hpp +++ b/src/objects/Entity.hpp @@ -60,7 +60,7 @@ public: rigging::Skeleton* getSkeleton() const; - void setRig(const rigging::SkeletonConfig* rigConfig); + void setRig(std::shared_ptr rigConfig); entityid_t getUID() const; diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index d1a41bef7..f686bfbcf 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -39,7 +39,7 @@ void Bone::setModel(const std::string& name) { model = {name, nullptr, true}; } -Skeleton::Skeleton(const SkeletonConfig* config) +Skeleton::Skeleton(std::shared_ptr config) : config(config), pose(config->getBones().size()), calculated(config->getBones().size()), @@ -86,6 +86,16 @@ void Skeleton::deserialize(const dv::value& root) { } } +void Skeleton::setConfig(std::shared_ptr rigConfig) { + config = std::move(rigConfig); + pose.matrices.resize( + config->getBones().size(), glm::mat4(1.0f) + ); + calculated.matrices.resize( + config->getBones().size(), glm::mat4(1.0f) + ); +} + static void get_all_nodes(std::vector& nodes, Bone* node) { nodes[node->getIndex()] = node; for (auto& subnode : node->getBones()) { @@ -97,6 +107,7 @@ SkeletonConfig::SkeletonConfig( const std::string& name, std::unique_ptr root, size_t nodesCount ) : name(name), root(std::move(root)), nodes(nodesCount) { + assert(this->root.get() != nullptr); get_all_nodes(nodes, this->root.get()); } @@ -159,6 +170,9 @@ void SkeletonConfig::render( const glm::vec3& position, const glm::vec3& scale ) const { + if (skeleton.config->root == nullptr) { + return; + } update(skeleton, rotation, position, scale); if (!skeleton.visible) { diff --git a/src/objects/rigging.hpp b/src/objects/rigging.hpp index 7726d0b95..9e7fc75f6 100644 --- a/src/objects/rigging.hpp +++ b/src/objects/rigging.hpp @@ -78,7 +78,7 @@ namespace rigging { }; struct Skeleton { - const SkeletonConfig* config; + std::shared_ptr config; Pose pose; Pose calculated; std::vector flags; @@ -89,13 +89,15 @@ namespace rigging { util::VecInterpolation<3, float> interpolation {false}; - Skeleton(const SkeletonConfig* config); + Skeleton(std::shared_ptr config); dv::value serialize(bool saveTextures, bool savePose) const; void deserialize(const dv::value& root); + + void setConfig(std::shared_ptr config); }; - class SkeletonConfig { + class SkeletonConfig : public std::enable_shared_from_this { std::string name; std::unique_ptr root; std::unordered_map indices; @@ -135,7 +137,7 @@ namespace rigging { ) const; Skeleton instance() const { - return Skeleton(this); + return Skeleton(shared_from_this()); } const Bone* find(std::string_view str) const;