change: skeletons are assets now, not content units

This commit is contained in:
MihailRis 2026-01-16 00:34:20 +03:00
parent 587c140a6b
commit 42c4716be2
17 changed files with 144 additions and 120 deletions

View file

@ -24,7 +24,8 @@ enum class AssetType {
LAYOUT, LAYOUT,
SOUND, SOUND,
MODEL, MODEL,
POST_EFFECT POST_EFFECT,
SKELETON
}; };
namespace assetload { namespace assetload {

View file

@ -36,6 +36,7 @@ AssetsLoader::AssetsLoader(Engine& engine, Assets& assets, const ResPaths& paths
addLoader(AssetType::SOUND, assetload::sound); addLoader(AssetType::SOUND, assetload::sound);
addLoader(AssetType::MODEL, assetload::model); addLoader(AssetType::MODEL, assetload::model);
addLoader(AssetType::POST_EFFECT, assetload::posteffect); addLoader(AssetType::POST_EFFECT, assetload::posteffect);
addLoader(AssetType::SKELETON, assetload::skeleton);
} }
void AssetsLoader::addLoader(AssetType tag, aloader_func func) { void AssetsLoader::addLoader(AssetType tag, aloader_func func) {
@ -141,6 +142,8 @@ static std::string assets_def_folder(AssetType tag) {
return MODELS_FOLDER; return MODELS_FOLDER;
case AssetType::POST_EFFECT: case AssetType::POST_EFFECT:
return POST_EFFECTS_FOLDER; return POST_EFFECTS_FOLDER;
case AssetType::SKELETON:
return SKELETONS_FOLDER;
} }
return "<error>"; return "<error>";
} }
@ -263,21 +266,20 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
add_layouts(pack->getEnvironment(), info.id, folder, loader); add_layouts(pack->getEnvironment(), info.id, folder, loader);
} }
for (auto& entry : content->getSkeletons()) { for (const auto& entry : content->getPacks()) {
auto& skeleton = *entry.second; io::path skeletonsDir = entry.first + ":skeletons";
for (auto& bone : skeleton.getBones()) { if (!io::is_directory(skeletonsDir)) {
std::string model = bone->model.name; continue;
size_t pos = model.rfind('.'); }
if (pos != std::string::npos) { for (const auto& file : io::directory_iterator(skeletonsDir)) {
model = model.substr(0, pos); loader.add(
} AssetType::SKELETON,
if (!model.empty()) { file.string(),
loader.add( entry.first + ":" + file.stem()
AssetType::MODEL, MODELS_FOLDER + "/" + model, model );
);
}
} }
} }
for (const auto& [_, def] : content->blocks.getDefs()) { for (const auto& [_, def] : content->blocks.getDefs()) {
if (def->variants) { if (def->variants) {
for (const auto& variant : def->variants->variants) { for (const auto& variant : def->variants->variants) {

View file

@ -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<AssetCfg>& 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( static void read_anim_file(
const std::string& animFile, const std::string& animFile,
std::vector<std::pair<std::string, int>>& frameList std::vector<std::pair<std::string, int>>& frameList

View file

@ -69,4 +69,12 @@ namespace assetload {
const std::string& name, const std::string& name,
const std::shared_ptr<AssetCfg>& settings const std::shared_ptr<AssetCfg>& settings
); );
postfunc skeleton(
AssetsLoader*,
const ResPaths& paths,
const std::string& file,
const std::string& name,
const std::shared_ptr<AssetCfg>& settings
);
} }

View file

@ -8,7 +8,6 @@
#include "items/ItemDef.hpp" #include "items/ItemDef.hpp"
#include "logic/scripting/scripting.hpp" #include "logic/scripting/scripting.hpp"
#include "objects/EntityDef.hpp" #include "objects/EntityDef.hpp"
#include "objects/rigging.hpp"
#include "voxels/Block.hpp" #include "voxels/Block.hpp"
#include "world/generator/VoxelFragment.hpp" #include "world/generator/VoxelFragment.hpp"
#include "world/generator/GeneratorDef.hpp" #include "world/generator/GeneratorDef.hpp"
@ -33,7 +32,6 @@ Content::Content(
ContentUnitDefs<GeneratorDef> generators, ContentUnitDefs<GeneratorDef> generators,
UptrsMap<std::string, ContentPackRuntime> packs, UptrsMap<std::string, ContentPackRuntime> packs,
UptrsMap<std::string, BlockMaterial> blockMaterials, UptrsMap<std::string, BlockMaterial> blockMaterials,
UptrsMap<std::string, rigging::SkeletonConfig> skeletons,
ResourceIndicesSet resourceIndices, ResourceIndicesSet resourceIndices,
dv::value defaults, dv::value defaults,
std::unordered_map<std::string, int> tags std::unordered_map<std::string, int> tags
@ -41,7 +39,6 @@ Content::Content(
: indices(std::move(indices)), : indices(std::move(indices)),
packs(std::move(packs)), packs(std::move(packs)),
blockMaterials(std::move(blockMaterials)), blockMaterials(std::move(blockMaterials)),
skeletons(std::move(skeletons)),
defaults(std::move(defaults)), defaults(std::move(defaults)),
tags(std::move(tags)), tags(std::move(tags)),
blocks(std::move(blocks)), blocks(std::move(blocks)),
@ -56,23 +53,6 @@ Content::Content(
Content::~Content() = default; 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 { const BlockMaterial* Content::findBlockMaterial(const std::string& id) const {
auto found = blockMaterials.find(id); auto found = blockMaterials.find(id);
if (found == blockMaterials.end()) { if (found == blockMaterials.end()) {
@ -104,8 +84,3 @@ const UptrsMap<std::string, BlockMaterial>& Content::getBlockMaterials() const {
const UptrsMap<std::string, ContentPackRuntime>& Content::getPacks() const { const UptrsMap<std::string, ContentPackRuntime>& Content::getPacks() const {
return packs; return packs;
} }
const UptrsMap<std::string, rigging::SkeletonConfig>& Content::getSkeletons(
) const {
return skeletons;
}

View file

@ -20,10 +20,6 @@ struct ItemDef;
struct EntityDef; struct EntityDef;
struct GeneratorDef; struct GeneratorDef;
namespace rigging {
class SkeletonConfig;
}
class namereuse_error : public std::runtime_error { class namereuse_error : public std::runtime_error {
ContentType type; ContentType type;
public: public:
@ -183,7 +179,6 @@ class Content {
std::unique_ptr<ContentIndices> indices; std::unique_ptr<ContentIndices> indices;
UptrsMap<std::string, ContentPackRuntime> packs; UptrsMap<std::string, ContentPackRuntime> packs;
UptrsMap<std::string, BlockMaterial> blockMaterials; UptrsMap<std::string, BlockMaterial> blockMaterials;
UptrsMap<std::string, rigging::SkeletonConfig> skeletons;
dv::value defaults = nullptr; dv::value defaults = nullptr;
std::unordered_map<std::string, int> tags; std::unordered_map<std::string, int> tags;
public: public:
@ -203,7 +198,6 @@ public:
ContentUnitDefs<GeneratorDef> generators, ContentUnitDefs<GeneratorDef> generators,
UptrsMap<std::string, ContentPackRuntime> packs, UptrsMap<std::string, ContentPackRuntime> packs,
UptrsMap<std::string, BlockMaterial> blockMaterials, UptrsMap<std::string, BlockMaterial> blockMaterials,
UptrsMap<std::string, rigging::SkeletonConfig> skeletons,
ResourceIndicesSet resourceIndices, ResourceIndicesSet resourceIndices,
dv::value defaults, dv::value defaults,
std::unordered_map<std::string, int> tags std::unordered_map<std::string, int> tags
@ -230,13 +224,10 @@ public:
return found->second; 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 BlockMaterial* findBlockMaterial(const std::string& id) const;
const ContentPackRuntime* getPackRuntime(const std::string& id) const; const ContentPackRuntime* getPackRuntime(const std::string& id) const;
ContentPackRuntime* getPackRuntime(const std::string& id); ContentPackRuntime* getPackRuntime(const std::string& id);
const UptrsMap<std::string, BlockMaterial>& getBlockMaterials() const; const UptrsMap<std::string, BlockMaterial>& getBlockMaterials() const;
const UptrsMap<std::string, ContentPackRuntime>& getPacks() const; const UptrsMap<std::string, ContentPackRuntime>& getPacks() const;
const UptrsMap<std::string, rigging::SkeletonConfig>& getSkeletons() const;
}; };

View file

@ -1,17 +1,11 @@
#include "ContentBuilder.hpp" #include "ContentBuilder.hpp"
#include "objects/rigging.hpp"
ContentBuilder::~ContentBuilder() = default; ContentBuilder::~ContentBuilder() = default;
void ContentBuilder::add(std::unique_ptr<ContentPackRuntime> pack) { void ContentBuilder::add(std::unique_ptr<ContentPackRuntime> pack) {
packs[pack->getId()] = std::move(pack); packs[pack->getId()] = std::move(pack);
} }
void ContentBuilder::add(std::unique_ptr<rigging::SkeletonConfig> skeleton) {
skeletons[skeleton->getName()] = std::move(skeleton);
}
BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) { BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) {
blockMaterials[id] = std::make_unique<BlockMaterial>(); blockMaterials[id] = std::make_unique<BlockMaterial>();
auto& material = *blockMaterials[id]; auto& material = *blockMaterials[id];
@ -98,7 +92,6 @@ std::unique_ptr<Content> ContentBuilder::build() {
generators.build(), generators.build(),
std::move(packs), std::move(packs),
std::move(blockMaterials), std::move(blockMaterials),
std::move(skeletons),
std::move(resourceIndices), std::move(resourceIndices),
std::move(defaults), std::move(defaults),
std::move(tags.map) std::move(tags.map)

View file

@ -85,7 +85,6 @@ struct TagsIndices {
class ContentBuilder { class ContentBuilder {
UptrsMap<std::string, BlockMaterial> blockMaterials; UptrsMap<std::string, BlockMaterial> blockMaterials;
UptrsMap<std::string, rigging::SkeletonConfig> skeletons;
UptrsMap<std::string, ContentPackRuntime> packs; UptrsMap<std::string, ContentPackRuntime> packs;
std::unordered_map<std::string, ContentType> allNames; std::unordered_map<std::string, ContentType> allNames;
public: public:
@ -100,7 +99,6 @@ public:
~ContentBuilder(); ~ContentBuilder();
void add(std::unique_ptr<ContentPackRuntime> pack); void add(std::unique_ptr<ContentPackRuntime> pack);
void add(std::unique_ptr<rigging::SkeletonConfig> skeleton);
BlockMaterial& createBlockMaterial(const std::string& id); BlockMaterial& createBlockMaterial(const std::string& id);

View file

@ -3,14 +3,12 @@
#include <algorithm> #include <algorithm>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <iostream>
#include "loading/ContentUnitLoader.hpp" #include "loading/ContentUnitLoader.hpp"
#include "ContentBuilder.hpp" #include "ContentBuilder.hpp"
#include "ContentPack.hpp" #include "ContentPack.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "logic/scripting/scripting.hpp" #include "logic/scripting/scripting.hpp"
#include "objects/rigging.hpp"
#include "util/listutil.hpp" #include "util/listutil.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
#include "engine/EnginePaths.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 // Process content.json and load defined content units
auto contentFile = pack->getContentFile(); auto contentFile = pack->getContentFile();
if (io::exists(contentFile)) { if (io::exists(contentFile)) {

View file

@ -26,6 +26,7 @@
#include "logic/scripting/scripting_hud.hpp" #include "logic/scripting/scripting_hud.hpp"
#include "maths/voxmaths.hpp" #include "maths/voxmaths.hpp"
#include "objects/Players.hpp" #include "objects/Players.hpp"
#include "objects/Entities.hpp"
#include "physics/Hitbox.hpp" #include "physics/Hitbox.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
#include "voxels/Chunks.hpp" #include "voxels/Chunks.hpp"
@ -49,6 +50,7 @@ LevelScreen::LevelScreen(
gui(engine.getGUI()), gui(engine.getGUI()),
input(engine.getInput()) { input(engine.getInput()) {
Level* level = levelPtr.get(); Level* level = levelPtr.get();
level->entities->setAssets(*engine.getAssets());
auto& settings = engine.getSettings(); auto& settings = engine.getSettings();
auto& assets = *engine.getAssets(); auto& assets = *engine.getAssets();

View file

@ -23,6 +23,7 @@
#include "maths/voxmaths.hpp" #include "maths/voxmaths.hpp"
#include "objects/Entities.hpp" #include "objects/Entities.hpp"
#include "objects/Player.hpp" #include "objects/Player.hpp"
#include "objects/rigging.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "voxels/Block.hpp" #include "voxels/Block.hpp"
#include "voxels/Chunk.hpp" #include "voxels/Chunk.hpp"
@ -110,7 +111,7 @@ WorldRenderer::WorldRenderer(
const auto& content = level.content; const auto& content = level.content;
skeletons = std::make_unique<NamedSkeletons>(); skeletons = std::make_unique<NamedSkeletons>();
const auto& skeletonConfig = content.requireSkeleton( const auto& skeletonConfig = assets->require<rigging::SkeletonConfig>(
content.getDefaults()["hand-skeleton"].asString() content.getDefaults()["hand-skeleton"].asString()
); );
hands = std::make_unique<HandsRenderer>( hands = std::make_unique<HandsRenderer>(

View file

@ -1,6 +1,7 @@
#include "objects/rigging.hpp" #include "objects/rigging.hpp"
#include "libentity.hpp" #include "libentity.hpp"
#include "engine/Engine.hpp"
#include "graphics/render/WorldRenderer.hpp" #include "graphics/render/WorldRenderer.hpp"
#include "graphics/render/NamedSkeletons.hpp" #include "graphics/render/NamedSkeletons.hpp"
@ -21,11 +22,14 @@ static int index_range_check(
} }
static rigging::Skeleton* get_skeleton(lua::State* L) { static rigging::Skeleton* get_skeleton(lua::State* L) {
if (scripting::engine->isHeadless()) {
return nullptr;
}
if (lua::isstring(L, 1)) { if (lua::isstring(L, 1)) {
return scripting::renderer->skeletons->getSkeleton(lua::tostring(L, 1)); return scripting::renderer->skeletons->getSkeleton(lua::tostring(L, 1));
} }
if (auto entity = get_entity(L, 1)) { if (auto entity = get_entity(L, 1)) {
return &entity->getSkeleton(); return entity->getSkeleton();
} }
return nullptr; return nullptr;
} }

View file

@ -1,5 +1,6 @@
#include "libentity.hpp" #include "libentity.hpp"
#include "assets/Assets.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "content/ContentPack.hpp" #include "content/ContentPack.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
@ -82,7 +83,11 @@ static int l_despawn(lua::State* L) {
static int l_get_skeleton(lua::State* L) { static int l_get_skeleton(lua::State* L) {
if (auto entity = get_entity(L, 1)) { 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; return 0;
} }
@ -97,9 +102,13 @@ static int l_get_player(lua::State* L) {
} }
static int l_set_skeleton(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)) { if (auto entity = get_entity(L, 1)) {
std::string skeletonName = lua::require_string(L, 2); std::string skeletonName = lua::require_string(L, 2);
auto rigConfig = content->getSkeleton(skeletonName); auto rigConfig = assets->get<rigging::SkeletonConfig>(skeletonName);
if (rigConfig == nullptr) { if (rigConfig == nullptr) {
throw std::runtime_error( throw std::runtime_error(
"skeleton not found '" + skeletonName + "'" "skeleton not found '" + skeletonName + "'"

View file

@ -1,6 +1,7 @@
#define VC_ENABLE_REFLECTION #define VC_ENABLE_REFLECTION
#include "Entities.hpp" #include "Entities.hpp"
#include <entt/entity/registry.hpp>
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <sstream> #include <sstream>
@ -25,15 +26,22 @@
static debug::Logger logger("entities"); static debug::Logger logger("entities");
Entities::Entities(Level& level) Entities::Entities(Level& level)
: level(level), : registry(std::make_unique<entt::registry>()),
level(level),
sensorsTickClock(20, 3), sensorsTickClock(20, 3),
updateTickClock(20, 3) { updateTickClock(20, 3) {
} }
Entities::~Entities() = default;
void Entities::setAssets(Assets& assets) {
this->assets = &assets;
}
std::optional<Entity> Entities::get(entityid_t id) { std::optional<Entity> Entities::get(entityid_t id) {
const auto& found = entities.find(id); const auto& found = entities.find(id);
if (found != entities.end() && registry.valid(found->second)) { if (found != entities.end() && registry->valid(found->second)) {
return Entity(*this, id, registry, found->second); return Entity(*this, id, *registry, found->second);
} }
return std::nullopt; return std::nullopt;
} }
@ -45,9 +53,12 @@ entityid_t Entities::spawn(
dv::value saved, dv::value saved,
entityid_t uid entityid_t uid
) { ) {
auto skeleton = level.content.getSkeleton(def.skeletonName); rigging::SkeletonConfig* skeleton = nullptr;
if (skeleton == nullptr) { if (assets) {
throw std::runtime_error("skeleton " + def.skeletonName + " not found"); skeleton = assets->get<rigging::SkeletonConfig>(def.skeletonName);
if (skeleton == nullptr) {
throw std::runtime_error("skeleton " + def.skeletonName + " not found");
}
} }
entityid_t id; entityid_t id;
if (uid == 0) { if (uid == 0) {
@ -64,12 +75,12 @@ entityid_t Entities::spawn(
throw std::runtime_error(ss.str()); throw std::runtime_error(ss.str());
} }
} }
auto entity = registry.create(); auto entity = registry->create();
entities[id] = entity; entities[id] = entity;
uids[entity] = id; uids[entity] = id;
registry.emplace<EntityId>(entity, static_cast<entityid_t>(id), def); registry->emplace<EntityId>(entity, static_cast<entityid_t>(id), def);
const auto& tsf = registry.emplace<Transform>( const auto& tsf = registry->emplace<Transform>(
entity, entity,
position, position,
glm::vec3(1.0f), glm::vec3(1.0f),
@ -77,7 +88,7 @@ entityid_t Entities::spawn(
glm::mat4(1.0f), glm::mat4(1.0f),
true true
); );
auto& body = registry.emplace<Rigidbody>( auto& body = registry->emplace<Rigidbody>(
entity, entity,
true, true,
Hitbox {def.bodyType, position, def.hitbox * 0.5f}, Hitbox {def.bodyType, position, def.hitbox * 0.5f},
@ -85,8 +96,10 @@ entityid_t Entities::spawn(
); );
body.initialize(def, id, *this); body.initialize(def, id, *this);
auto& scripting = registry.emplace<ScriptComponents>(entity); auto& scripting = registry->emplace<ScriptComponents>(entity);
registry.emplace<rigging::Skeleton>(entity, skeleton->instance()); if (assets) {
registry->emplace<rigging::Skeleton>(entity, skeleton->instance());
}
for (auto& instance : def.components) { for (auto& instance : def.components) {
auto component = std::make_unique<UserComponent>( auto component = std::make_unique<UserComponent>(
@ -126,7 +139,7 @@ void Entities::loadEntity(const dv::value& map) {
void Entities::loadEntity(const dv::value& map, Entity entity) { void Entities::loadEntity(const dv::value& map, Entity entity) {
auto& transform = entity.getTransform(); auto& transform = entity.getTransform();
auto& body = entity.getRigidbody(); auto& body = entity.getRigidbody();
auto& skeleton = entity.getSkeleton(); auto skeleton = entity.getSkeleton();
if (map.has(COMP_RIGIDBODY)) { if (map.has(COMP_RIGIDBODY)) {
body.deserialize(map[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)) { if (map.has(COMP_TRANSFORM)) {
transform.deserialize(map[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); map.at("skeleton").get(skeletonName);
if (skeletonName != skeleton.config->getName()) { if (skeletonName != skeleton->config->getName()) {
skeleton.config = level.content.getSkeleton(skeletonName); skeleton->config = assets->get<rigging::SkeletonConfig>(skeletonName);
} }
if (auto foundSkeleton = map.at(COMP_SKELETON)) { if (auto foundSkeleton = map.at(COMP_SKELETON)) {
skeleton.deserialize(*foundSkeleton); skeleton->deserialize(*foundSkeleton);
} }
} }
@ -148,7 +164,7 @@ std::optional<Entities::RaycastResult> Entities::rayCast(
glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore
) { ) {
Ray ray(start, dir); Ray ray(start, dir);
auto view = registry.view<EntityId, Transform, Rigidbody>(); auto view = registry->view<EntityId, Transform, Rigidbody>();
entityid_t foundUID = 0; entityid_t foundUID = 0;
glm::ivec3 foundNormal; glm::ivec3 foundNormal;
@ -214,17 +230,17 @@ void Entities::despawn(std::vector<Entity> entities) {
void Entities::clean() { void Entities::clean() {
for (auto it = entities.begin(); it != entities.end();) { for (auto it = entities.begin(); it != entities.end();) {
if (!registry.get<EntityId>(it->second).destroyFlag) { if (!registry->get<EntityId>(it->second).destroyFlag) {
++it; ++it;
} else { } else {
auto& rigidbody = registry.get<Rigidbody>(it->second); auto& rigidbody = registry->get<Rigidbody>(it->second);
// todo: refactor // todo: refactor
auto physics = level.physics.get(); auto physics = level.physics.get();
for (auto& sensor : rigidbody.sensors) { for (auto& sensor : rigidbody.sensors) {
physics->removeSensor(&sensor); physics->removeSensor(&sensor);
} }
uids.erase(it->second); uids.erase(it->second);
registry.destroy(it->second); registry->destroy(it->second);
it = entities.erase(it); it = entities.erase(it);
} }
} }
@ -266,7 +282,7 @@ void Entities::preparePhysics(float delta) {
auto part = sensorsTickClock.getPart(); auto part = sensorsTickClock.getPart();
auto parts = sensorsTickClock.getParts(); auto parts = sensorsTickClock.getParts();
auto view = registry.view<EntityId, Transform, Rigidbody>(); auto view = registry->view<EntityId, Transform, Rigidbody>();
auto physics = level.physics.get(); auto physics = level.physics.get();
std::vector<Sensor*> sensors; std::vector<Sensor*> sensors;
for (auto [entity, eid, transform, rigidbody] : view.each()) { for (auto [entity, eid, transform, rigidbody] : view.each()) {
@ -285,7 +301,7 @@ void Entities::preparePhysics(float delta) {
void Entities::updatePhysics(float delta) { void Entities::updatePhysics(float delta) {
preparePhysics(delta); preparePhysics(delta);
auto view = registry.view<EntityId, Transform, Rigidbody>(); auto view = registry->view<EntityId, Transform, Rigidbody>();
auto physics = level.physics.get(); auto physics = level.physics.get();
for (auto [entity, eid, transform, rigidbody] : view.each()) { for (auto [entity, eid, transform, rigidbody] : view.each()) {
if (!rigidbody.enabled || rigidbody.hitbox.type == BodyType::STATIC) { if (!rigidbody.enabled || rigidbody.hitbox.type == BodyType::STATIC) {
@ -351,7 +367,7 @@ void Entities::renderDebug(
{ {
auto ctx = pctx.sub(&batch); auto ctx = pctx.sub(&batch);
ctx.setLineWidth(1); ctx.setLineWidth(1);
auto view = registry.view<Transform, Rigidbody>(); auto view = registry->view<Transform, Rigidbody>();
for (auto [entity, transform, rigidbody] : view.each()) { for (auto [entity, transform, rigidbody] : view.each()) {
const auto& hitbox = rigidbody.hitbox; const auto& hitbox = rigidbody.hitbox;
const auto& pos = transform.pos; const auto& pos = transform.pos;
@ -374,7 +390,7 @@ void Entities::renderDebug(
} }
} }
{ {
auto view = registry.view<Transform, rigging::Skeleton>(); auto view = registry->view<Transform, rigging::Skeleton>();
auto ctx = pctx.sub(&batch); auto ctx = pctx.sub(&batch);
ctx.setDepthTest(false); ctx.setDepthTest(false);
ctx.setDepthMask(false); ctx.setDepthMask(false);
@ -400,7 +416,7 @@ void Entities::render(
bool pause, bool pause,
entityid_t fpsEntity entityid_t fpsEntity
) { ) {
auto view = registry.view<EntityId, Transform, rigging::Skeleton>(); auto view = registry->view<EntityId, Transform, rigging::Skeleton>();
for (auto [entity, eid, transform, skeleton] : view.each()) { for (auto [entity, eid, transform, skeleton] : view.each()) {
if (eid.uid == fpsEntity) { if (eid.uid == fpsEntity) {
continue; continue;
@ -425,7 +441,7 @@ void Entities::render(
} }
bool Entities::hasBlockingInside(AABB aabb) { bool Entities::hasBlockingInside(AABB aabb) {
auto view = registry.view<EntityId, Rigidbody>(); auto view = registry->view<EntityId, Rigidbody>();
for (auto [entity, eid, body] : view.each()) { for (auto [entity, eid, body] : view.each()) {
if (eid.def.blocking && aabb.intersect(body.hitbox.getAABB(), -0.05f)) { if (eid.def.blocking && aabb.intersect(body.hitbox.getAABB(), -0.05f)) {
return true; return true;
@ -436,7 +452,7 @@ bool Entities::hasBlockingInside(AABB aabb) {
std::vector<Entity> Entities::getAllInside(AABB aabb) { std::vector<Entity> Entities::getAllInside(AABB aabb) {
std::vector<Entity> collected; std::vector<Entity> collected;
auto view = registry.view<EntityId, Transform>(); auto view = registry->view<EntityId, Transform>();
for (auto [entity, eid, transform] : view.each()) { for (auto [entity, eid, transform] : view.each()) {
if (!eid.destroyFlag && aabb.contains(transform.pos)) { if (!eid.destroyFlag && aabb.contains(transform.pos)) {
const auto& found = uids.find(entity); const auto& found = uids.find(entity);
@ -453,7 +469,7 @@ std::vector<Entity> Entities::getAllInside(AABB aabb) {
std::vector<Entity> Entities::getAllInRadius(glm::vec3 center, float radius) { std::vector<Entity> Entities::getAllInRadius(glm::vec3 center, float radius) {
std::vector<Entity> collected; std::vector<Entity> collected;
auto view = registry.view<Transform>(); auto view = registry->view<Transform>();
for (auto [entity, transform] : view.each()) { for (auto [entity, transform] : view.each()) {
if (glm::distance2(transform.pos, center) <= radius * radius) { if (glm::distance2(transform.pos, center) <= radius * radius) {
const auto& found = uids.find(entity); const auto& found = uids.find(entity);

View file

@ -12,7 +12,7 @@
#include "typedefs.hpp" #include "typedefs.hpp"
#include "util/Clock.hpp" #include "util/Clock.hpp"
#include <entt/entity/registry.hpp> #include <entt/entity/fwd.hpp>
#include <unordered_map> #include <unordered_map>
struct EntityDef; struct EntityDef;
@ -31,14 +31,15 @@ namespace rigging {
class SkeletonConfig; class SkeletonConfig;
} }
class Entities { class Entities final {
entt::registry registry; std::unique_ptr<entt::registry> registry;
Level& level; Level& level;
std::unordered_map<entityid_t, entt::entity> entities; std::unordered_map<entityid_t, entt::entity> entities;
std::unordered_map<entt::entity, entityid_t> uids; std::unordered_map<entt::entity, entityid_t> uids;
entityid_t nextID = 1; entityid_t nextID = 1;
util::Clock sensorsTickClock; util::Clock sensorsTickClock;
util::Clock updateTickClock; util::Clock updateTickClock;
Assets* assets = nullptr;
void updateSensors( void updateSensors(
Rigidbody& body, const Transform& tsf, std::vector<Sensor*>& sensors Rigidbody& body, const Transform& tsf, std::vector<Sensor*>& sensors
@ -53,6 +54,10 @@ public:
Entities(Level& level); Entities(Level& level);
~Entities();
void setAssets(Assets& assets);
void clean(); void clean();
void updatePhysics(float delta); void updatePhysics(float delta);
void update(float delta); void update(float delta);

View file

@ -13,13 +13,16 @@
static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA"; static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA";
void Entity::setInterpolatedPosition(const glm::vec3& position) { void Entity::setInterpolatedPosition(const glm::vec3& position) {
getSkeleton().interpolation.refresh(position); if (auto skeleton = getSkeleton()) {
skeleton->interpolation.refresh(position);
}
} }
glm::vec3 Entity::getInterpolatedPosition() const { glm::vec3 Entity::getInterpolatedPosition() const {
const auto& skeleton = getSkeleton(); if (auto skeleton = getSkeleton()) {
if (skeleton.interpolation.isEnabled()) { if (skeleton->interpolation.isEnabled()) {
return skeleton.interpolation.getCurrent(); return skeleton->interpolation.getCurrent();
}
} }
return getTransform().pos; return getTransform().pos;
} }
@ -30,8 +33,8 @@ void Entity::destroy() {
} }
} }
rigging::Skeleton& Entity::getSkeleton() const { rigging::Skeleton* Entity::getSkeleton() const {
return registry.get<rigging::Skeleton>(entity); return registry.try_get<rigging::Skeleton>(entity);
} }
void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { void Entity::setRig(const rigging::SkeletonConfig* rigConfig) {
@ -50,8 +53,8 @@ dv::value Entity::serialize() const {
const auto& def = eid.def; const auto& def = eid.def;
const auto& transform = getTransform(); const auto& transform = getTransform();
const auto& rigidbody = getRigidbody(); const auto& rigidbody = getRigidbody();
const auto& skeleton = getSkeleton();
const auto& scripts = getScripting(); const auto& scripts = getScripting();
auto skeleton = getSkeleton();
auto root = dv::object(); auto root = dv::object();
root["def"] = def.name; root["def"] = def.name;
@ -61,13 +64,15 @@ dv::value Entity::serialize() const {
root[COMP_RIGIDBODY] = root[COMP_RIGIDBODY] =
rigidbody.serialize(def.save.body.velocity, def.save.body.settings); rigidbody.serialize(def.save.body.velocity, def.save.body.settings);
if (skeleton.config->getName() != def.skeletonName) { if (skeleton != nullptr) {
root["skeleton"] = skeleton.config->getName(); 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( if (def.save.skeleton.pose || def.save.skeleton.textures) {
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()) { if (!scripts.components.empty()) {
auto& compsMap = root.object("comps"); auto& compsMap = root.object("comps");

View file

@ -58,7 +58,7 @@ public:
ScriptComponents& getScripting() const; ScriptComponents& getScripting() const;
rigging::Skeleton& getSkeleton() const; rigging::Skeleton* getSkeleton() const;
void setRig(const rigging::SkeletonConfig* rigConfig); void setRig(const rigging::SkeletonConfig* rigConfig);