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 bool was_active = is_active();
662 parent_ = new_parent;
667 set_transform_global(cached_transform_global);
684 root.
order = get_next_order();
692 set_active(was_active);
702void transform_component::attach_child(
const entt::handle& child,
transform_component& child_transform)
704 child_transform.sort_index_ = int32_t(children_.size());
705 children_.push_back(child);
710auto transform_component::remove_child(
const entt::handle& child, transform_component& child_transform) ->
bool
712 auto iter = std::remove_if(std::begin(children_),
714 [&child](
const auto& other)
716 return child == other;
718 if(iter == std::end(children_))
723 assert(std::distance(iter, std::end(children_)) == 1);
725 auto removed_idx = child_transform.sort_index_;
727 children_.erase(iter, std::end(children_));
730 for(
auto& c : children_)
732 auto& sort_idx =
c.get<transform_component>().sort_index_;
733 if(sort_idx > removed_idx)
738 child_transform.sort_index_ = {-1};
745 std::sort(children_.begin(),
747 [](
const auto& lhs,
const auto& rhs)
749 return lhs.template get<transform_component>().sort_index_ <
750 rhs.template get<transform_component>().sort_index_;
754void transform_component::apply_transform(
const math::transform& tr)
noexcept
756 auto parent = get_parent();
759 auto inv_parent_transform = inverse_parent_transform(parent);
760 set_transform_local(inv_parent_transform * tr);
764 set_transform_local(tr);
768auto transform_component::inverse_parent_transform(
const entt::handle& parent)
noexcept ->
math::transform
770 const auto& parent_transform = parent.get<transform_component>().get_transform_global();
776 return get_transform_global().inverse_transform_coord(
point);
781 return flags_.get_value(
this)[flags_types::active];
786 return flags_.get_global_value(
this,
false)[flags_types::active];
791 auto val = flags_.get_value(
this);
792 val[flags_types::active] = active;
793 flags_.set_value(
this, val);
798 return transform_.dirty;
803 transform_.set_dirty(
this, dirty);
808 return transform_dirty_[id];
813 transform_dirty_.set(
id, dirty);
823 children_ = children;
826void transform_component::on_dirty_transform(
bool dirty)
noexcept
830 transform_dirty_.set();
833 if(transform_.has_auto_resolve())
835 for(
const auto& child : get_children())
837 auto component = child.try_get<transform_component>();
840 component->transform_.set_dirty(component, dirty);
846auto transform_component::resolve_global_value_transform() const noexcept ->
math::transform
855 return parent_transform * local_transform;
861void transform_component::on_dirty_flags(
bool dirty)
noexcept
863 auto flags = flags_.get_global_value(
this,
false);
864 on_flags_changed(flags);
866 if(flags_.has_auto_resolve())
868 for(
const auto& child : get_children())
870 auto component = child.try_get<transform_component>();
873 component->flags_.set_dirty(component, dirty);
879void transform_component::on_flags_changed(flags_t flags)
881 if(flags[flags_types::active])
883 auto& comp =
get_owner().get_or_emplace<active_component>();
892auto transform_component::get_flags_global() const noexcept -> flags_t
894 return flags_.get_global_value(
this,
false);
897auto transform_component::resolve_global_value_flags() const noexcept -> flags_t
901 const auto& local_flags = flags_.get_value(
this);
904 const auto& parent_flags = parent.get<transform_component>().get_flags_global();
906 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 >
Hash specialization for batch_key to enable use in std::unordered_map.
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.