Last active
January 14, 2023 19:52
-
-
Save oreyg/1255bca96e24edb5a549b0d8dcf735ce to your computer and use it in GitHub Desktop.
ECS EnTT transform
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 = [®istry](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