12auto is_ancestor_of(entt::handle potential_parent, entt::handle child) ->
bool
23 auto& tc = child.get<transform_component>();
24 entt::handle current = tc.get_parent();
27 if(current == potential_parent)
29 current = current.get<transform_component>().get_parent();
34bool order_changed =
false;
36auto get_next_order() -> uint64_t
38 static uint64_t order{};
50 order_changed =
false;
73 component.set_owner(
entity);
87 parent_transform->remove_child(component.get_owner(), component);
91 for(
auto& child : component.children_)
102 return is_ancestor_of(parent_to_test, child);
107 std::unordered_set<entt::entity> entity_set;
110 entity_set.insert(*ent);
113 std::vector<entt::handle> top_level;
114 top_level.reserve(list.size());
118 bool has_selected_ancestor =
false;
131 if(entity_set.find(parent) != entity_set.end())
134 has_selected_ancestor =
true;
140 if(!has_selected_ancestor)
142 top_level.push_back(*ent);
151 std::unordered_set<entt::entity> entity_set;
154 entity_set.insert(ent);
157 std::vector<entt::handle> top_level;
158 top_level.reserve(list.size());
162 bool has_selected_ancestor =
false;
175 if(entity_set.find(parent) != entity_set.end())
178 has_selected_ancestor =
true;
184 if(!has_selected_ancestor)
186 top_level.push_back(ent);
193void transform_component::set_owner(entt::handle owner)
200 root.
order = get_next_order();
203 transform_dirty_.set();
207 flags_.set_dirty(
this,
false);
208 flags_.set_value(
this, flags);
216 return transform_.get_value(
this);
221 transform_.set_value(
this, trans);
226 if(transform_.has_auto_resolve())
232 transform_.get_global_value(
this,
true);
234 for(
const auto& child : children_)
244 return transform_.get_global_value(
this,
false);
249 return set_transform_global_epsilon(tr, math::epsilon<float>());
254 if(get_transform_global().compare(tr, epsilon) == 0)
274 const auto& this_pos = get_position_global();
275 if(math::all(math::epsilonEqual(this_pos, position, math::epsilon<float>())))
279 auto m = get_transform_global();
280 m.set_position(position);
287 math::vec3 new_pos = get_position_global() + amount;
288 set_position_global(new_pos);
303 transform_.value(
this).set_position(position);
308 transform_.value(
this).translate_local(amount);
317 const math::quat& rotation,
318 float epsilon)
noexcept ->
bool
320 const auto& this_pos = get_position_global();
321 const auto& this_rotation = get_rotation_global();
322 bool same_position = math::all(math::epsilonEqual(this_pos, position, epsilon));
326 bool same_rotation = math::all(math::epsilonEqual(this_rotation, rotation, epsilon));
334 auto m = get_transform_global();
335 m.set_rotation(rotation);
336 m.set_position(position);
354 const auto& this_rotation = get_rotation_global();
355 if(math::all(math::epsilonEqual(this_rotation, rotation, math::epsilon<float>())))
360 auto m = get_transform_global();
361 m.set_rotation(rotation);
368 auto m = get_transform_global();
371 set_transform_global(m);
386 transform_.value(
this).set_rotation(rotation);
391 auto m = get_transform_local();
394 set_transform_local(m);
414 auto m = get_transform_global();
415 m.rotate(math::radians(rotation));
417 set_transform_global(m);
432 auto m = get_transform_local();
433 m.rotate_local(math::radians(rotation));
435 set_transform_local(m);
440 auto m = get_transform_global();
441 m.rotate_axis(math::radians(degrees), axis);
443 set_transform_global(m);
449 auto quaternion = math::angleAxis(math::radians(degrees), axis);
450 auto vector2 = vector -
point;
451 vector2 = quaternion * vector2;
452 vector =
point + vector2;
460 auto euler = math::eulerAngles(rotation);
468 look_at(
point, math::vec3{0.0f, 1.0f, 0.0f});
473 auto eye = get_position_global();
477 set_rotation_global(m.get_rotation());
491 transform_.value(
this).scale(
scale);
541 auto m = get_transform_global();
559 const auto& this_scale = get_scale_global();
560 if(math::all(math::epsilonEqual(this_scale,
scale, math::epsilon<float>())))
565 auto m = get_transform_global();
573 transform_.value(
this).set_scale(
scale);
578 const auto& this_skew = get_skew_global();
579 if(math::all(math::epsilonEqual(this_skew, skew, math::epsilon<float>())))
584 auto m = get_transform_global();
592 transform_.value(
this).set_skew(skew);
597 const auto& this_perspective = get_perspective_global();
598 if(math::all(math::epsilonEqual(this_perspective, perspective, math::epsilon<float>())))
603 auto m = get_transform_global();
604 m.set_perspective(perspective);
611 transform_.value(
this).set_perspective(perspective);
633 auto old_parent = parent_;
635 if(new_parent == get_owner())
642 if(old_parent == new_parent)
648 if(is_ancestor_of(get_owner(), new_parent))
658 cached_transform_global = get_transform_global();
661 parent_ = new_parent;
666 set_transform_global(cached_transform_global);
683 root.
order = get_next_order();
699void transform_component::attach_child(
const entt::handle& child,
transform_component& child_transform)
701 child_transform.sort_index_ = int32_t(children_.size());
702 children_.push_back(child);
707auto transform_component::remove_child(
const entt::handle& child, transform_component& child_transform) ->
bool
709 auto iter = std::remove_if(std::begin(children_),
711 [&child](
const auto& other)
713 return child == other;
715 if(iter == std::end(children_))
720 assert(std::distance(iter, std::end(children_)) == 1);
722 auto removed_idx = child_transform.sort_index_;
724 children_.erase(iter, std::end(children_));
727 for(
auto& c : children_)
729 auto& sort_idx =
c.get<transform_component>().sort_index_;
730 if(sort_idx > removed_idx)
735 child_transform.sort_index_ = {-1};
742 std::sort(children_.begin(),
744 [](
const auto& lhs,
const auto& rhs)
746 return lhs.template get<transform_component>().sort_index_ <
747 rhs.template get<transform_component>().sort_index_;
751void transform_component::apply_transform(
const math::transform& tr)
noexcept
753 auto parent = get_parent();
756 auto inv_parent_transform = inverse_parent_transform(parent);
757 set_transform_local(inv_parent_transform * tr);
761 set_transform_local(tr);
765auto transform_component::inverse_parent_transform(
const entt::handle& parent)
noexcept ->
math::transform
767 const auto& parent_transform = parent.get<transform_component>().get_transform_global();
773 return get_transform_global().inverse_transform_coord(
point);
778 return flags_.get_value(
this)[flags_types::active];
783 return flags_.get_global_value(
this,
false)[flags_types::active];
788 auto val = flags_.get_value(
this);
789 val[flags_types::active] = active;
790 flags_.set_value(
this, val);
795 return transform_.dirty;
800 transform_.set_dirty(
this, dirty);
805 return transform_dirty_[id];
810 transform_dirty_.set(
id, dirty);
820 children_ = children;
823void transform_component::on_dirty_transform(
bool dirty)
noexcept
827 transform_dirty_.set();
830 if(transform_.has_auto_resolve())
832 for(
const auto& child : get_children())
834 auto component = child.try_get<transform_component>();
837 component->transform_.set_dirty(component, dirty);
843auto transform_component::resolve_global_value_transform() const noexcept ->
math::transform
852 return parent_transform * local_transform;
858void transform_component::on_dirty_flags(
bool dirty)
noexcept
860 auto flags = flags_.get_global_value(
this,
false);
861 on_flags_changed(flags);
863 if(flags_.has_auto_resolve())
865 for(
const auto& child : get_children())
867 auto component = child.try_get<transform_component>();
870 component->flags_.set_dirty(component, dirty);
876void transform_component::on_flags_changed(flags_t flags)
878 if(flags[flags_types::active])
880 auto& comp =
get_owner().get_or_emplace<active_component>();
889auto transform_component::get_flags_global() const noexcept -> flags_t
891 return flags_.get_global_value(
this,
false);
894auto transform_component::resolve_global_value_flags() const noexcept -> flags_t
898 const auto& local_flags = flags_.get_value(
this);
901 const auto& parent_flags = parent.get<transform_component>().get_flags_global();
903 return parent_flags & local_flags;
auto get_owner() const noexcept -> entt::const_handle
Gets the owner of the component.
void set_owner(entt::handle owner)
Sets the owner of the component.
#define APPLOG_ERROR(...)
auto inverse(transform_t< T, Q > const &t) noexcept -> transform_t< T, Q >
auto is_roots_order_changed() -> bool
void reset_roots_order_changed()
Root component structure for the ACE framework, serves as the base component.
static void on_update_component(entt::registry &r, entt::entity e)
Called when the component is updated.
static void on_create_component(entt::registry &r, entt::entity e)
Called when the component is created.
static void on_destroy_component(entt::registry &r, entt::entity e)
Called when the component is destroyed.