diff --git a/src/assets/Assets.hpp b/src/assets/Assets.hpp index c0853b0b4..ea0753aec 100644 --- a/src/assets/Assets.hpp +++ b/src/assets/Assets.hpp @@ -24,7 +24,8 @@ enum class AssetType { LAYOUT, SOUND, MODEL, - POST_EFFECT + POST_EFFECT, + SKELETON }; namespace assetload { diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 49ce5e04d..9729eedb8 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -36,6 +36,7 @@ AssetsLoader::AssetsLoader(Engine& engine, Assets& assets, const ResPaths& paths addLoader(AssetType::SOUND, assetload::sound); addLoader(AssetType::MODEL, assetload::model); addLoader(AssetType::POST_EFFECT, assetload::posteffect); + addLoader(AssetType::SKELETON, assetload::skeleton); } void AssetsLoader::addLoader(AssetType tag, aloader_func func) { @@ -141,6 +142,8 @@ static std::string assets_def_folder(AssetType tag) { return MODELS_FOLDER; case AssetType::POST_EFFECT: return POST_EFFECTS_FOLDER; + case AssetType::SKELETON: + return SKELETONS_FOLDER; } return ""; } @@ -263,21 +266,20 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) { add_layouts(pack->getEnvironment(), info.id, folder, loader); } - for (auto& entry : content->getSkeletons()) { - auto& skeleton = *entry.second; - for (auto& bone : skeleton.getBones()) { - std::string model = bone->model.name; - size_t pos = model.rfind('.'); - if (pos != std::string::npos) { - model = model.substr(0, pos); - } - if (!model.empty()) { - loader.add( - AssetType::MODEL, MODELS_FOLDER + "/" + model, model - ); - } + for (const auto& entry : content->getPacks()) { + io::path skeletonsDir = entry.first + ":skeletons"; + if (!io::is_directory(skeletonsDir)) { + continue; + } + for (const auto& file : io::directory_iterator(skeletonsDir)) { + loader.add( + AssetType::SKELETON, + file.string(), + entry.first + ":" + file.stem() + ); } } + for (const auto& [_, def] : content->blocks.getDefs()) { if (def->variants) { for (const auto& variant : def->variants->variants) { diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 1bf76e6af..f739aee7c 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -393,6 +393,32 @@ assetload::postfunc assetload::model( } } +assetload::postfunc assetload::skeleton( + AssetsLoader* loader, + const ResPaths& paths, + const std::string& file, + const std::string& name, + const std::shared_ptr& settings +) { + return [=](auto assets) { + std::string text = io::read_string(file); + auto skeleton = rigging::SkeletonConfig::parse(text, file, name); + for (auto& bone : skeleton->getBones()) { + std::string model = bone->model.name; + size_t pos = model.rfind('.'); + if (pos != std::string::npos) { + model = model.substr(0, pos); + } + if (!model.empty()) { + loader->add( + AssetType::MODEL, MODELS_FOLDER + "/" + model, model + ); + } + } + assets->store(std::move(skeleton), name); + }; +} + static void read_anim_file( const std::string& animFile, std::vector>& frameList diff --git a/src/assets/assetload_funcs.hpp b/src/assets/assetload_funcs.hpp index 97ed60ea1..50a255bb2 100644 --- a/src/assets/assetload_funcs.hpp +++ b/src/assets/assetload_funcs.hpp @@ -69,4 +69,12 @@ namespace assetload { const std::string& name, const std::shared_ptr& settings ); + + postfunc skeleton( + AssetsLoader*, + const ResPaths& paths, + const std::string& file, + const std::string& name, + const std::shared_ptr& settings + ); } diff --git a/src/content/Content.cpp b/src/content/Content.cpp index 0c697fd1d..15d68512b 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -8,7 +8,6 @@ #include "items/ItemDef.hpp" #include "logic/scripting/scripting.hpp" #include "objects/EntityDef.hpp" -#include "objects/rigging.hpp" #include "voxels/Block.hpp" #include "world/generator/VoxelFragment.hpp" #include "world/generator/GeneratorDef.hpp" @@ -33,7 +32,6 @@ Content::Content( ContentUnitDefs generators, UptrsMap packs, UptrsMap blockMaterials, - UptrsMap skeletons, ResourceIndicesSet resourceIndices, dv::value defaults, std::unordered_map tags @@ -41,7 +39,6 @@ Content::Content( : indices(std::move(indices)), packs(std::move(packs)), blockMaterials(std::move(blockMaterials)), - skeletons(std::move(skeletons)), defaults(std::move(defaults)), tags(std::move(tags)), blocks(std::move(blocks)), @@ -56,23 +53,6 @@ Content::Content( Content::~Content() = default; -const rigging::SkeletonConfig* Content::getSkeleton(const std::string& id -) const { - auto found = skeletons.find(id); - if (found == skeletons.end()) { - return nullptr; - } - return found->second.get(); -} - -const rigging::SkeletonConfig& Content::requireSkeleton(const std::string& id) const { - auto skeleton = getSkeleton(id); - if (skeleton == nullptr) { - throw std::runtime_error("skeleton '" + id + "' not loaded"); - } - return *skeleton; -} - const BlockMaterial* Content::findBlockMaterial(const std::string& id) const { auto found = blockMaterials.find(id); if (found == blockMaterials.end()) { @@ -104,8 +84,3 @@ const UptrsMap& Content::getBlockMaterials() const { const UptrsMap& Content::getPacks() const { return packs; } - -const UptrsMap& Content::getSkeletons( -) const { - return skeletons; -} diff --git a/src/content/Content.hpp b/src/content/Content.hpp index 12dc77d2f..dd0e30bf8 100644 --- a/src/content/Content.hpp +++ b/src/content/Content.hpp @@ -20,10 +20,6 @@ struct ItemDef; struct EntityDef; struct GeneratorDef; -namespace rigging { - class SkeletonConfig; -} - class namereuse_error : public std::runtime_error { ContentType type; public: @@ -183,7 +179,6 @@ class Content { std::unique_ptr indices; UptrsMap packs; UptrsMap blockMaterials; - UptrsMap skeletons; dv::value defaults = nullptr; std::unordered_map tags; public: @@ -203,7 +198,6 @@ public: ContentUnitDefs generators, UptrsMap packs, UptrsMap blockMaterials, - UptrsMap skeletons, ResourceIndicesSet resourceIndices, dv::value defaults, std::unordered_map tags @@ -230,13 +224,10 @@ public: return found->second; } - const rigging::SkeletonConfig* getSkeleton(const std::string& id) const; - const rigging::SkeletonConfig& requireSkeleton(const std::string& id) const; const BlockMaterial* findBlockMaterial(const std::string& id) const; const ContentPackRuntime* getPackRuntime(const std::string& id) const; ContentPackRuntime* getPackRuntime(const std::string& id); const UptrsMap& getBlockMaterials() const; const UptrsMap& getPacks() const; - const UptrsMap& getSkeletons() const; }; diff --git a/src/content/ContentBuilder.cpp b/src/content/ContentBuilder.cpp index d32cb2860..ce77434ed 100644 --- a/src/content/ContentBuilder.cpp +++ b/src/content/ContentBuilder.cpp @@ -1,17 +1,11 @@ #include "ContentBuilder.hpp" -#include "objects/rigging.hpp" - ContentBuilder::~ContentBuilder() = default; void ContentBuilder::add(std::unique_ptr pack) { packs[pack->getId()] = std::move(pack); } -void ContentBuilder::add(std::unique_ptr skeleton) { - skeletons[skeleton->getName()] = std::move(skeleton); -} - BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) { blockMaterials[id] = std::make_unique(); auto& material = *blockMaterials[id]; @@ -98,7 +92,6 @@ std::unique_ptr ContentBuilder::build() { generators.build(), std::move(packs), std::move(blockMaterials), - std::move(skeletons), std::move(resourceIndices), std::move(defaults), std::move(tags.map) diff --git a/src/content/ContentBuilder.hpp b/src/content/ContentBuilder.hpp index 8a938819b..b1c4d26c3 100644 --- a/src/content/ContentBuilder.hpp +++ b/src/content/ContentBuilder.hpp @@ -85,7 +85,6 @@ struct TagsIndices { class ContentBuilder { UptrsMap blockMaterials; - UptrsMap skeletons; UptrsMap packs; std::unordered_map allNames; public: @@ -100,7 +99,6 @@ public: ~ContentBuilder(); void add(std::unique_ptr pack); - void add(std::unique_ptr skeleton); BlockMaterial& createBlockMaterial(const std::string& id); diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index ed4ab34d8..e2bf81f2d 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -3,14 +3,12 @@ #include #include -#include #include "loading/ContentUnitLoader.hpp" #include "ContentBuilder.hpp" #include "ContentPack.hpp" #include "debug/Logger.hpp" #include "logic/scripting/scripting.hpp" -#include "objects/rigging.hpp" #include "util/listutil.hpp" #include "util/stringutil.hpp" #include "engine/EnginePaths.hpp" @@ -399,16 +397,6 @@ void ContentLoader::load() { } } - // Load skeletons - io::path skeletonsDir = folder / "skeletons"; - foreach_file(skeletonsDir, [this](const io::path& file) { - std::string name = pack->id + ":" + file.stem(); - std::string text = io::read_string(file); - builder.add( - rigging::SkeletonConfig::parse(text, file.string(), name) - ); - }); - // Process content.json and load defined content units auto contentFile = pack->getContentFile(); if (io::exists(contentFile)) { diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 0f93de8cc..02119b9ad 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -26,6 +26,7 @@ #include "logic/scripting/scripting_hud.hpp" #include "maths/voxmaths.hpp" #include "objects/Players.hpp" +#include "objects/Entities.hpp" #include "physics/Hitbox.hpp" #include "util/stringutil.hpp" #include "voxels/Chunks.hpp" @@ -49,6 +50,7 @@ LevelScreen::LevelScreen( gui(engine.getGUI()), input(engine.getInput()) { Level* level = levelPtr.get(); + level->entities->setAssets(*engine.getAssets()); auto& settings = engine.getSettings(); auto& assets = *engine.getAssets(); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 70195f927..7b505d868 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -23,6 +23,7 @@ #include "maths/voxmaths.hpp" #include "objects/Entities.hpp" #include "objects/Player.hpp" +#include "objects/rigging.hpp" #include "settings.hpp" #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" @@ -110,7 +111,7 @@ WorldRenderer::WorldRenderer( const auto& content = level.content; skeletons = std::make_unique(); - const auto& skeletonConfig = content.requireSkeleton( + const auto& skeletonConfig = assets->require( content.getDefaults()["hand-skeleton"].asString() ); hands = std::make_unique( diff --git a/src/logic/scripting/lua/libs/lib__skeleton.cpp b/src/logic/scripting/lua/libs/lib__skeleton.cpp index 3fd248725..be42c356e 100644 --- a/src/logic/scripting/lua/libs/lib__skeleton.cpp +++ b/src/logic/scripting/lua/libs/lib__skeleton.cpp @@ -1,6 +1,7 @@ #include "objects/rigging.hpp" #include "libentity.hpp" +#include "engine/Engine.hpp" #include "graphics/render/WorldRenderer.hpp" #include "graphics/render/NamedSkeletons.hpp" @@ -21,11 +22,14 @@ static int index_range_check( } static rigging::Skeleton* get_skeleton(lua::State* L) { + if (scripting::engine->isHeadless()) { + return nullptr; + } if (lua::isstring(L, 1)) { return scripting::renderer->skeletons->getSkeleton(lua::tostring(L, 1)); } if (auto entity = get_entity(L, 1)) { - return &entity->getSkeleton(); + return entity->getSkeleton(); } return nullptr; } diff --git a/src/logic/scripting/lua/libs/libentity.cpp b/src/logic/scripting/lua/libs/libentity.cpp index 5bf3e4d74..0ae21f3c7 100644 --- a/src/logic/scripting/lua/libs/libentity.cpp +++ b/src/logic/scripting/lua/libs/libentity.cpp @@ -1,5 +1,6 @@ #include "libentity.hpp" +#include "assets/Assets.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" #include "engine/Engine.hpp" @@ -82,7 +83,11 @@ static int l_despawn(lua::State* L) { static int l_get_skeleton(lua::State* L) { if (auto entity = get_entity(L, 1)) { - return lua::pushstring(L, entity->getSkeleton().config->getName()); + auto skeleton = entity->getSkeleton(); + if (skeleton == nullptr) { + return 0; + } + return lua::pushstring(L, skeleton->config->getName()); } return 0; } @@ -97,9 +102,13 @@ static int l_get_player(lua::State* L) { } static int l_set_skeleton(lua::State* L) { + auto assets = engine->getAssets(); + if (assets == nullptr) { + return 0; + } if (auto entity = get_entity(L, 1)) { std::string skeletonName = lua::require_string(L, 2); - auto rigConfig = content->getSkeleton(skeletonName); + auto rigConfig = assets->get(skeletonName); if (rigConfig == nullptr) { throw std::runtime_error( "skeleton not found '" + skeletonName + "'" diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index 3b4e53627..522ba6a0a 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -1,6 +1,7 @@ #define VC_ENABLE_REFLECTION #include "Entities.hpp" +#include #include #include @@ -25,15 +26,22 @@ static debug::Logger logger("entities"); Entities::Entities(Level& level) - : level(level), + : registry(std::make_unique()), + level(level), sensorsTickClock(20, 3), updateTickClock(20, 3) { } +Entities::~Entities() = default; + +void Entities::setAssets(Assets& assets) { + this->assets = &assets; +} + std::optional Entities::get(entityid_t id) { const auto& found = entities.find(id); - if (found != entities.end() && registry.valid(found->second)) { - return Entity(*this, id, registry, found->second); + if (found != entities.end() && registry->valid(found->second)) { + return Entity(*this, id, *registry, found->second); } return std::nullopt; } @@ -45,9 +53,12 @@ entityid_t Entities::spawn( dv::value saved, entityid_t uid ) { - auto skeleton = level.content.getSkeleton(def.skeletonName); - if (skeleton == nullptr) { - throw std::runtime_error("skeleton " + def.skeletonName + " not found"); + rigging::SkeletonConfig* skeleton = nullptr; + if (assets) { + skeleton = assets->get(def.skeletonName); + if (skeleton == nullptr) { + throw std::runtime_error("skeleton " + def.skeletonName + " not found"); + } } entityid_t id; if (uid == 0) { @@ -64,12 +75,12 @@ entityid_t Entities::spawn( throw std::runtime_error(ss.str()); } } - auto entity = registry.create(); + auto entity = registry->create(); entities[id] = entity; uids[entity] = id; - registry.emplace(entity, static_cast(id), def); - const auto& tsf = registry.emplace( + registry->emplace(entity, static_cast(id), def); + const auto& tsf = registry->emplace( entity, position, glm::vec3(1.0f), @@ -77,7 +88,7 @@ entityid_t Entities::spawn( glm::mat4(1.0f), true ); - auto& body = registry.emplace( + auto& body = registry->emplace( entity, true, Hitbox {def.bodyType, position, def.hitbox * 0.5f}, @@ -85,8 +96,10 @@ entityid_t Entities::spawn( ); body.initialize(def, id, *this); - auto& scripting = registry.emplace(entity); - registry.emplace(entity, skeleton->instance()); + auto& scripting = registry->emplace(entity); + if (assets) { + registry->emplace(entity, skeleton->instance()); + } for (auto& instance : def.components) { auto component = std::make_unique( @@ -126,7 +139,7 @@ void Entities::loadEntity(const dv::value& map) { void Entities::loadEntity(const dv::value& map, Entity entity) { auto& transform = entity.getTransform(); auto& body = entity.getRigidbody(); - auto& skeleton = entity.getSkeleton(); + auto skeleton = entity.getSkeleton(); if (map.has(COMP_RIGIDBODY)) { body.deserialize(map[COMP_RIGIDBODY]); @@ -134,13 +147,16 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { if (map.has(COMP_TRANSFORM)) { transform.deserialize(map[COMP_TRANSFORM]); } - std::string skeletonName = skeleton.config->getName(); + if (skeleton == nullptr) { + return; + } + std::string skeletonName = skeleton->config->getName(); map.at("skeleton").get(skeletonName); - if (skeletonName != skeleton.config->getName()) { - skeleton.config = level.content.getSkeleton(skeletonName); + if (skeletonName != skeleton->config->getName()) { + skeleton->config = assets->get(skeletonName); } if (auto foundSkeleton = map.at(COMP_SKELETON)) { - skeleton.deserialize(*foundSkeleton); + skeleton->deserialize(*foundSkeleton); } } @@ -148,7 +164,7 @@ std::optional Entities::rayCast( glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore ) { Ray ray(start, dir); - auto view = registry.view(); + auto view = registry->view(); entityid_t foundUID = 0; glm::ivec3 foundNormal; @@ -214,17 +230,17 @@ void Entities::despawn(std::vector entities) { void Entities::clean() { for (auto it = entities.begin(); it != entities.end();) { - if (!registry.get(it->second).destroyFlag) { + if (!registry->get(it->second).destroyFlag) { ++it; } else { - auto& rigidbody = registry.get(it->second); + auto& rigidbody = registry->get(it->second); // todo: refactor auto physics = level.physics.get(); for (auto& sensor : rigidbody.sensors) { physics->removeSensor(&sensor); } uids.erase(it->second); - registry.destroy(it->second); + registry->destroy(it->second); it = entities.erase(it); } } @@ -266,7 +282,7 @@ void Entities::preparePhysics(float delta) { auto part = sensorsTickClock.getPart(); auto parts = sensorsTickClock.getParts(); - auto view = registry.view(); + auto view = registry->view(); auto physics = level.physics.get(); std::vector sensors; for (auto [entity, eid, transform, rigidbody] : view.each()) { @@ -285,7 +301,7 @@ void Entities::preparePhysics(float delta) { void Entities::updatePhysics(float delta) { preparePhysics(delta); - auto view = registry.view(); + auto view = registry->view(); auto physics = level.physics.get(); for (auto [entity, eid, transform, rigidbody] : view.each()) { if (!rigidbody.enabled || rigidbody.hitbox.type == BodyType::STATIC) { @@ -351,7 +367,7 @@ void Entities::renderDebug( { auto ctx = pctx.sub(&batch); ctx.setLineWidth(1); - auto view = registry.view(); + auto view = registry->view(); for (auto [entity, transform, rigidbody] : view.each()) { const auto& hitbox = rigidbody.hitbox; const auto& pos = transform.pos; @@ -374,7 +390,7 @@ void Entities::renderDebug( } } { - auto view = registry.view(); + auto view = registry->view(); auto ctx = pctx.sub(&batch); ctx.setDepthTest(false); ctx.setDepthMask(false); @@ -400,7 +416,7 @@ void Entities::render( bool pause, entityid_t fpsEntity ) { - auto view = registry.view(); + auto view = registry->view(); for (auto [entity, eid, transform, skeleton] : view.each()) { if (eid.uid == fpsEntity) { continue; @@ -425,7 +441,7 @@ void Entities::render( } bool Entities::hasBlockingInside(AABB aabb) { - auto view = registry.view(); + auto view = registry->view(); for (auto [entity, eid, body] : view.each()) { if (eid.def.blocking && aabb.intersect(body.hitbox.getAABB(), -0.05f)) { return true; @@ -436,7 +452,7 @@ bool Entities::hasBlockingInside(AABB aabb) { std::vector Entities::getAllInside(AABB aabb) { std::vector collected; - auto view = registry.view(); + auto view = registry->view(); for (auto [entity, eid, transform] : view.each()) { if (!eid.destroyFlag && aabb.contains(transform.pos)) { const auto& found = uids.find(entity); @@ -453,7 +469,7 @@ std::vector Entities::getAllInside(AABB aabb) { std::vector Entities::getAllInRadius(glm::vec3 center, float radius) { std::vector collected; - auto view = registry.view(); + auto view = registry->view(); for (auto [entity, transform] : view.each()) { if (glm::distance2(transform.pos, center) <= radius * radius) { const auto& found = uids.find(entity); diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 03fcec8cb..3b3a7e1a1 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -12,7 +12,7 @@ #include "typedefs.hpp" #include "util/Clock.hpp" -#include +#include #include struct EntityDef; @@ -31,14 +31,15 @@ namespace rigging { class SkeletonConfig; } -class Entities { - entt::registry registry; +class Entities final { + std::unique_ptr registry; Level& level; std::unordered_map entities; std::unordered_map uids; entityid_t nextID = 1; util::Clock sensorsTickClock; util::Clock updateTickClock; + Assets* assets = nullptr; void updateSensors( Rigidbody& body, const Transform& tsf, std::vector& sensors @@ -53,6 +54,10 @@ public: Entities(Level& level); + ~Entities(); + + void setAssets(Assets& assets); + void clean(); void updatePhysics(float delta); void update(float delta); diff --git a/src/objects/Entity.cpp b/src/objects/Entity.cpp index 24aa17362..82e67babf 100644 --- a/src/objects/Entity.cpp +++ b/src/objects/Entity.cpp @@ -13,13 +13,16 @@ static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA"; void Entity::setInterpolatedPosition(const glm::vec3& position) { - getSkeleton().interpolation.refresh(position); + if (auto skeleton = getSkeleton()) { + skeleton->interpolation.refresh(position); + } } glm::vec3 Entity::getInterpolatedPosition() const { - const auto& skeleton = getSkeleton(); - if (skeleton.interpolation.isEnabled()) { - return skeleton.interpolation.getCurrent(); + if (auto skeleton = getSkeleton()) { + if (skeleton->interpolation.isEnabled()) { + return skeleton->interpolation.getCurrent(); + } } return getTransform().pos; } @@ -30,8 +33,8 @@ void Entity::destroy() { } } -rigging::Skeleton& Entity::getSkeleton() const { - return registry.get(entity); +rigging::Skeleton* Entity::getSkeleton() const { + return registry.try_get(entity); } void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { @@ -50,8 +53,8 @@ dv::value Entity::serialize() const { const auto& def = eid.def; const auto& transform = getTransform(); const auto& rigidbody = getRigidbody(); - const auto& skeleton = getSkeleton(); const auto& scripts = getScripting(); + auto skeleton = getSkeleton(); auto root = dv::object(); root["def"] = def.name; @@ -61,13 +64,15 @@ dv::value Entity::serialize() const { root[COMP_RIGIDBODY] = rigidbody.serialize(def.save.body.velocity, def.save.body.settings); - if (skeleton.config->getName() != def.skeletonName) { - root["skeleton"] = skeleton.config->getName(); - } - if (def.save.skeleton.pose || def.save.skeleton.textures) { - root[COMP_SKELETON] = skeleton.serialize( - def.save.skeleton.pose, def.save.skeleton.textures - ); + if (skeleton != nullptr) { + if (skeleton->config->getName() != def.skeletonName) { + root["skeleton"] = skeleton->config->getName(); + } + if (def.save.skeleton.pose || def.save.skeleton.textures) { + root[COMP_SKELETON] = skeleton->serialize( + def.save.skeleton.pose, def.save.skeleton.textures + ); + } } if (!scripts.components.empty()) { auto& compsMap = root.object("comps"); diff --git a/src/objects/Entity.hpp b/src/objects/Entity.hpp index 4a306c862..ef00a1bf2 100644 --- a/src/objects/Entity.hpp +++ b/src/objects/Entity.hpp @@ -58,7 +58,7 @@ public: ScriptComponents& getScripting() const; - rigging::Skeleton& getSkeleton() const; + rigging::Skeleton* getSkeleton() const; void setRig(const rigging::SkeletonConfig* rigConfig);