1 #ifndef EAGINE_ECS_MANIPULATOR_HPP
9 #define EAGINE_ECS_MANIPULATOR_HPP
11 #include "../assert.hpp"
12 #include "../optional_ref.hpp"
13 #include <type_traits>
16 namespace eagine::ecs {
18 template <
typename Component,
bool Const>
19 class basic_manipulator;
21 template <
typename Component>
22 class basic_manipulator<Component, false> {
24 Component* _ptr{
nullptr};
27 void _reset_cmp(Component& cmp) noexcept {
32 basic_manipulator() noexcept = default;
34 basic_manipulator(Component& cmp) noexcept
37 auto is_valid() const noexcept ->
bool {
38 return _ptr !=
nullptr;
41 auto read() const -> const Component& {
42 EAGINE_ASSERT(is_valid());
47 auto read(T Component::*member)
const
48 -> optional_reference_wrapper<const T> {
50 return {*_ptr.*member};
55 auto write() -> Component& {
56 EAGINE_ASSERT(is_valid());
60 auto operator->() -> Component* {
61 EAGINE_ASSERT(is_valid());
66 template <
typename Component>
67 class basic_manipulator<Component, true> {
69 const Component* _ptr{
nullptr};
72 void _reset_cmp(
const Component& cmp) noexcept {
77 basic_manipulator() noexcept = default;
79 basic_manipulator(const Component& cmp) noexcept
82 auto is_valid() const noexcept ->
bool {
83 return _ptr !=
nullptr;
86 auto read() const -> const Component& {
87 EAGINE_ASSERT(is_valid());
92 auto read(T Component::*member)
const
93 -> optional_reference_wrapper<const T> {
95 return {*_ptr.*member};
100 auto operator->() ->
const Component* {
101 EAGINE_ASSERT(is_valid());
106 template <
typename Component,
bool Const>
107 struct get_manipulator {
108 using type = basic_manipulator<Component, Const>;
111 template <
typename Component,
bool Const>
112 using get_manipulator_t =
typename get_manipulator<Component, Const>::type;
114 template <
typename Component>
116 :
public get_manipulator_t<
117 std::remove_const_t<Component>,
118 std::is_const_v<Component>> {
120 using _base = get_manipulator_t<
121 std::remove_const_t<Component>,
122 std::is_const_v<Component>>;
124 using _nonconstC = std::remove_const_t<Component>;
125 _nonconstC* _add_place{
nullptr};
128 const bool _can_rem{
false};
129 bool _removed{
false};
133 manipulator() =
default;
135 manipulator(
bool can_rem)
136 : _can_rem{can_rem} {}
138 manipulator(Component& cmp,
bool can_rem)
140 , _can_rem{can_rem} {}
142 manipulator(Component& cmp, _nonconstC& add,
bool can_rem)
145 , _can_rem(can_rem) {}
147 manipulator(std::nullptr_t, _nonconstC& add,
bool can_rem)
149 , _can_rem{can_rem} {}
151 auto can_add() const noexcept ->
bool {
152 return _add_place !=
nullptr;
155 void add(std::remove_const_t<Component>&& cmp) {
156 EAGINE_ASSERT(can_add());
157 EAGINE_ASSERT(_add_place);
158 *_add_place = std::move(cmp);
159 this->_reset_cmp(*_add_place);
163 auto can_remove() const noexcept ->
bool {
164 return _can_rem && this->is_valid();
172 template <
typename Component>
173 class concrete_manipulator :
public manipulator<Component> {
175 using manipulator<Component>::manipulator;
177 void reset(Component& cmp) noexcept {
178 this->_reset_cmp(cmp);
179 this->_added =
false;
180 this->_removed =
false;
183 auto add_requested() const noexcept ->
bool {
187 auto remove_requested() const noexcept ->
bool {
188 return this->_removed;
194 #endif // EAGINE_ECS_MANIPULATOR_HPP