Program Listing for File hierarchysystem.cpp¶
↰ Return to documentation for file (/home/runner/work/Legion-Engine/Legion-Engine/legion/engine/core/defaults/hierarchysystem.cpp
)
#include <core/defaults/hierarchysystem.hpp>
void legion::core::HierarchySystem::onPositionModified(events::component_modification<position>* event)
{
OPTICK_EVENT();
if (!event->entity.has_component<hierarchy>())
return;
position diff = event->newValue - event->oldValue;
auto children = event->entity.children();
m_scheduler->queueJobs(children.size(), [&]()
{
auto& child = children[async::this_job::get_id()];
child.write_component<position>(child.read_component<position>() + diff);
}).wait();
}
void legion::core::HierarchySystem::onRotationModified(events::component_modification<rotation>* event)
{
OPTICK_EVENT();
if (!event->entity.has_component<hierarchy>())
return;
rotation diff = event->newValue * math::inverse(event->oldValue);
position pos = event->entity.read_component<position>();
auto children = event->entity.children();
m_scheduler->queueJobs(children.size(), [&]()
{
auto& child = children[async::this_job::get_id()];
child.write_component<position>(pos + (math::toMat3(diff) * (child.read_component<position>() - pos)));
child.write_component<rotation>(diff * child.read_component<rotation>());
}).wait();
}
void legion::core::HierarchySystem::onScaleModified(events::component_modification<scale>* event)
{
OPTICK_EVENT();
if (!event->entity.has_component<hierarchy>())
return;
scale diff = event->newValue / event->oldValue;
position pos = event->entity.read_component<position>();
auto children = event->entity.children();
m_scheduler->queueJobs(children.size(), [&]()
{
auto& child = children[async::this_job::get_id()];
child.write_component<position>(pos + (diff * (child.read_component<position>() - pos)));
child.write_component<scale>(child.read_component<scale>() * diff);
}).wait();
}
void legion::core::HierarchySystem::onPositionBulkModified(events::bulk_component_modification<position>* event)
{
OPTICK_EVENT();
const auto& entities = event->entities;
const auto& oldValues = event->oldValues;
const auto& newValues = event->newValues;
size_type count = entities.size();
ecs::component_container<position> diffs;
diffs.resize(count);
std::vector<byte> hasChildren;
hasChildren.resize(count);
std::vector<ecs::entity_set> children;
children.resize(count);
m_scheduler->queueJobs(count, [&]()
{
auto i = async::this_job::get_id();
if (entities[i].has_component<hierarchy>())
{
children[i] = entities[i].read_component<hierarchy>().children;
hasChildren[i] = children[i].size() > 0;
}
else
hasChildren[i] = false;
}).then(count, [&]()
{
auto i = async::this_job::get_id();
if (hasChildren[i])
diffs[i] = newValues[i] - oldValues[i];
}).wait();
for (int i = 0; i < count; i++)
{
OPTICK_EVENT("Update child");
if (!hasChildren[i])
continue;
m_scheduler->queueJobs(children[i].size(), [&]()
{
auto& child = children[i][async::this_job::get_id()];
child.write_component<position>(child.read_component<position>() + diffs[i]);
}).wait();
}
}
void legion::core::HierarchySystem::onRotationBulkModified(events::bulk_component_modification<rotation>* event)
{
OPTICK_EVENT();
const auto& entities = event->entities;
const auto& oldValues = event->oldValues;
const auto& newValues = event->newValues;
size_type count = entities.size();
ecs::component_container<rotation> diffs;
diffs.resize(count);
std::vector<byte> hasChildren;
hasChildren.resize(count);
std::vector<ecs::entity_set> children;
children.resize(count);
m_scheduler->queueJobs(count, [&]()
{
auto i = async::this_job::get_id();
if (entities[i].has_component<hierarchy>())
{
children[i] = entities[i].read_component<hierarchy>().children;
hasChildren[i] = children[i].size() > 0;
}
else
hasChildren[i] = false;
}).then(count, [&]()
{
auto i = async::this_job::get_id();
if (hasChildren[i])
diffs[i] = newValues[i] * math::inverse(oldValues[i]);
}).wait();
for (int i = 0; i < count; i++)
{
OPTICK_EVENT("Update child");
if (!hasChildren[i])
continue;
position pos = entities[i].read_component<position>();
m_scheduler->queueJobs(children[i].size(), [&]()
{
auto& child = children[i][async::this_job::get_id()];
child.write_component<position>(pos + (math::toMat3(diffs[i]) * (child.read_component<position>() - pos)));
child.write_component<rotation>(diffs[i] * child.read_component<rotation>());
}).wait();
}
}
void legion::core::HierarchySystem::onScaleBulkModified(events::bulk_component_modification<scale>* event)
{
OPTICK_EVENT();
const auto& entities = event->entities;
const auto& oldValues = event->oldValues;
const auto& newValues = event->newValues;
size_type count = entities.size();
ecs::component_container<scale> diffs;
diffs.resize(count);
std::vector<byte> hasChildren;
hasChildren.resize(count);
std::vector<ecs::entity_set> children;
children.resize(count);
m_scheduler->queueJobs(count, [&]()
{
auto i = async::this_job::get_id();
if (entities[i].has_component<hierarchy>())
{
children[i] = entities[i].read_component<hierarchy>().children;
hasChildren[i] = children[i].size() > 0;
}
else
hasChildren[i] = false;
}).then(count, [&]()
{
auto i = async::this_job::get_id();
if (hasChildren[i])
diffs[i] = newValues[i] / oldValues[i];
}).wait();
for (int i = 0; i < count; i++)
{
OPTICK_EVENT("Update child");
if (!hasChildren[i])
continue;
position pos = entities[i].read_component<position>();
m_scheduler->queueJobs(children[i].size(), [&]()
{
auto& child = children[i][async::this_job::get_id()];
child.write_component<position>(pos + (diffs[i] * (child.read_component<position>() - pos)));
child.write_component<scale>(child.read_component<scale>() * diffs[i]);
}).wait();
}
}
void legion::core::HierarchySystem::setup()
{
bindToEvent<events::component_modification<position>, &HierarchySystem::onPositionModified>();
bindToEvent<events::component_modification<rotation>, &HierarchySystem::onRotationModified>();
bindToEvent<events::component_modification<scale>, &HierarchySystem::onScaleModified>();
bindToEvent<events::bulk_component_modification<position>, &HierarchySystem::onPositionBulkModified>();
bindToEvent<events::bulk_component_modification<rotation>, &HierarchySystem::onRotationBulkModified>();
bindToEvent<events::bulk_component_modification<scale>, &HierarchySystem::onScaleBulkModified>();
}