Skip to content

Instantly share code, notes, and snippets.

@oreyg
Last active January 14, 2023 19:52
Show Gist options
  • Save oreyg/1255bca96e24edb5a549b0d8dcf735ce to your computer and use it in GitHub Desktop.
Save oreyg/1255bca96e24edb5a549b0d8dcf735ce to your computer and use it in GitHub Desktop.
ECS EnTT transform
#pragma once
struct DirtyComponent
{
};
/*
struct VectorizeComponent
{
};
*/
struct TransformComponent
{
transform transform;
// hierarchy params
entt::entity parent { entt::null };
mat4x4 world_parent_inverse;
};
struct TransformSystem
{
//static void vectorization_ensure(entt::registry& registry, entt::entity entity, bool recursive = false);
//static void vectorization_forget(entt::registry& registry, entt::entity entity, bool recursive = false);
static void vectorization_apply(entt::registry& registry);
static uint32_t get_depth(entt::registry& registry, entt::entity entity);
static std::vector<entt::entity> get_children(const entt::registry& registry, const entt::entity entity, bool recursive = false);
static std::vector<entt::entity> get_parents(const entt::registry& registry, const entt::entity entity);
static entt::entity get_root_parent(entt::registry& registry, entt::entity entity);
static bool attach_safe(entt::registry& registry, entt::entity parent, entt::entity child);
static void attach_unsafe(entt::registry& registry, entt::entity parent, entt::entity child);
static void detach(entt::registry& registry, entt::entity child);
};
// -- *.cpp
/*
void TransformSystem::vectorization_ensure(entt::registry& registry, entt::entity entity, bool recursive)
{
registry.emplace_or_replace<VectorizeComponent>(entity);
if (recursive)
{
auto children = get_children(registry, entity, true);
for (auto child : children)
{
registry.emplace_or_replace<VectorizeComponent>(child);
}
}
}
void TransformSystem::vectorization_forget(entt::registry& registry, entt::entity entity, bool recursive)
{
registry.remove_if_exists<VectorizeComponent>(entity);
if (recursive)
{
auto children = get_children(registry, entity, true);
for (auto child : children)
{
registry.remove_if_exists<VectorizeComponent>(child);
}
}
}
*/
void TransformSystem::vectorization_apply(entt::registry& registry)
{
const auto sort_func = [&registry](const entt::entity lhs, const entt::entity rhs) {
const auto c1 = get_parents(registry, lhs);
const auto c2 = get_parents(registry, rhs);
const size_t size = min(c1.size(), c2.size());
const int cmp = memcmp(c1.data(), c2.data(), size * sizeof(entt::entity));
if (cmp == 0)
{
return c1.size() < c2.size();
}
return cmp < 0;
};
// With 'VectorizeComponent'
//auto group = registry.group<TransformComponent, VectorizeComponent>();
//group.sort(sort_func);
// Or without
registry.sort<TransformComponent>(sort_func);
}
std::vector<entt::entity> TransformSystem::get_children(const entt::registry& registry, const entt::entity entity, bool recursive)
{
std::vector<entt::entity> children;
auto scene_view = registry.view<TransformComponent>();
for (entt::entity child_entity : scene_view)
{
const TransformComponent& child = registry.get<TransformComponent>(child_entity);
if (child.parent == entity)
{
children.push_back(child_entity);
if (recursive)
{
auto subchildren = get_children(registry, child_entity, true);
children.insert(std::end(children), std::begin(subchildren), std::end(subchildren));
}
}
}
return children;
}
std::vector<entt::entity> TransformSystem::get_parents(const entt::registry& registry, const entt::entity entity)
{
std::vector<entt::entity> result;
entt::entity parent = entity;
while (parent != entt::null)
{
auto& child = registry.get<TransformComponent>(parent);
// Add safety check here
result.push_back(parent);
parent = child.parent;
}
std::reverse(result.begin(), result.end());
return result;
}
uint32_t TransformSystem::get_depth(entt::registry& registry, entt::entity entity)
{
uint32_t depth = 0;
entt::entity parent = entity;
while (parent != entt::null)
{
auto& child = registry.get<TransformComponent>(parent);
// Add safety check here
++depth;
parent = child.parent;
}
return depth;
}
entt::entity TransformSystem::get_root_parent(entt::registry& registry, entt::entity entity)
{
entt::entity root_parent = entt::null;
entt::entity test_parent = entity;
while (test_parent != entt::null)
{
auto& child = registry.get<TransformComponent>(test_parent);
// Add safety check here
root_parent = test_parent;
test_parent = child.parent;
}
return root_parent;
}
bool TransformSystem::attach_safe(entt::registry& registry, entt::entity parent, entt::entity child)
{
// Test for recursion
entt::entity test_parent = parent;
while (test_parent != entt::null && test_parent != child)
{
auto& child_transform = registry.get<TransformComponent>(test_parent);
// Add safety check here
test_parent = child_transform.parent;
}
// test_parent should be null, that means that there is no recursion
if (test_parent != entt::null)
{
return false;
}
attach_unsafe(registry, parent, child);
return true;
}
void TransformSystem::attach_unsafe(entt::registry& registry, entt::entity parent, entt::entity child)
{
if (parent != entt::null)
{
auto& child_transform = registry.get<TransformComponent>(child);
// Add safety check here
child_transform.parent = parent;
}
else
{
detach(registry, child);
}
}
void TransformSystem::detach(entt::registry& registry, entt::entity child)
{
auto& child_transform = registry.get<TransformComponent>(child);
// Add safety check here
child_transform.parent = entt::null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment