poking around the scenegraph pattern implemented with EnTT

This commit is contained in:
Hartmut Seichter 2020-12-09 00:16:08 +01:00
parent cea83d06e8
commit 1f390f5a4d
5 changed files with 86 additions and 27 deletions

View file

@ -16,7 +16,10 @@ void register_scene_function(sol::state&,sol::table &ns)
ns.new_usertype<entity>("entity", ns.new_usertype<entity>("entity",
sol::constructors<entity>()); sol::constructors<entity(),entity(scene&)>(),
"add_child",&entity::add_child,
"child_count",sol::readonly_property(&entity::child_count)
);
ns.new_usertype<node>("node", ns.new_usertype<node>("node",

View file

@ -54,12 +54,17 @@ public:
} }
template<typename T> template<typename T>
T& get_component() { T& get_component() const {
return _registry->get<T>(_entity); return _registry->get<T>(_entity);
} }
template <typename T,typename... Args>
T& get_or_create_component(Args&&... args) {
return _registry->get_or_emplace<T>(this->_entity,std::forward<Args>(args)...);
}
template<typename T> template<typename T>
bool has_component(){ return _registry->valid(_entity);} bool has_component() const { return _registry->valid(_entity);}
void destroy(); void destroy();
@ -69,6 +74,14 @@ public:
bool valid() const { return _registry->valid(_entity); } bool valid() const { return _registry->valid(_entity); }
void add_child(entity &child);
void remove_child(entity &child);
size_t child_count() const;
private: private:
std::shared_ptr<entt::registry> _registry; std::shared_ptr<entt::registry> _registry;

View file

@ -1,42 +1,68 @@
#include "pw/scene/entity.hpp" #include "pw/scene/entity.hpp"
#include "pw/scene/scene.hpp" #include "pw/scene/scene.hpp"
namespace pw { #include "pw/core/debug.hpp"
namespace test { namespace pw {
struct relationship { struct relationship {
std::vector<entt::entity> children; std::vector<entt::entity> children;
entt::entity parent { entt::null }; entt::entity parent { entt::null };
static void add_child(entt::registry& r,entt::entity p,entt::entity c)
{
// auto child_rels = r.view<relationship>(c);
// remove potential parents
}
}; };
void testbed()
{
using namespace entt;
registry r;
auto e = r.create();
}
}
entity::entity(scene &s) entity::entity(scene &s)
: _registry(s._registry) : _registry(s._registry)
, _entity(s._registry->create()) , _entity(s._registry ? _registry->create() : entt::null)
{ {
} }
void entity::add_child(entity& child)
{
if (child._registry != this->_registry) {
debug::e() << "Cannot mix entities from different scenes";
return;
}
// TODO: check circular dependencies
// declare child relationship
auto r = get_or_create_component<relationship>();
r.children.push_back(child._entity);
// declare parent
auto p_r = child.get_or_create_component<relationship>();
p_r.parent = _entity;
}
void entity::remove_child(entity& child)
{
if (child._registry != this->_registry) {
debug::e() << "Cannot mix entities from different scenes";
return;
}
// both need to have a relationship component
if (has_component<relationship>() && child.has_component<relationship>())
{
// we need to check if the child is related to the parent
auto r_p = child.get_component<relationship>();
if (r_p.parent == _entity)
{
// now go ahead
r_p.parent = entt::null;
auto r = get_component<relationship>();
std::remove(r.children.begin(),r.children.end(),child._entity);
}
}
}
size_t entity::child_count() const
{
return has_component<relationship>() ? get_component<relationship>().children.size() : 0;
}
entity::~entity() entity::~entity()
{ {
this->destroy(); this->destroy();

View file

@ -29,6 +29,14 @@ void test_stack()
std::cout << t.val << std::endl; std::cout << t.val << std::endl;
auto e2 = entity(s);
e.add_child(e2);
std::cout << e.child_count() << std::endl;
} }
void test_heap() void test_heap()

View file

@ -9,4 +9,13 @@ print("hello pixwerx!")
local s = pw.scene.new() local s = pw.scene.new()
local e = pw.entity.new(s)
local e2 = pw.entity.new(s)
e.add_child(e2)
print(s)
print(e.child_count)