Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
component_desc.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5#include <cstring>
6#include <tuple>
7#include <type_traits>
8
9#include "gaia/core/span.h"
10#include "gaia/core/utility.h"
11#include "gaia/ecs/component.h"
12#include "gaia/mem/data_layout_policy.h"
13#include "gaia/mem/mem_utils.h"
14#include "gaia/meta/reflection.h"
15#include "gaia/meta/type_info.h"
16#include "gaia/ser/ser_rt.h"
17
18namespace gaia {
19 namespace ecs {
20 namespace detail {
21 using ComponentDescId = uint32_t;
22
23 template <typename T>
24 struct ComponentDesc final {
25 using CT = component_type_t<T>;
26 using U = typename component_type_t<T>::Type;
27 using DescU = typename CT::TypeFull;
28
29 static ComponentDescId id() {
30 return meta::type_info::id<DescU>();
31 }
32
33 static constexpr ComponentLookupHash hash_lookup() {
34 return {meta::type_info::hash<DescU>()};
35 }
36
37 static constexpr auto name() {
38 return meta::type_info::name<DescU>();
39 }
40
41 static constexpr uint32_t size() {
42 if constexpr (std::is_empty_v<U>)
43 return 0;
44 else
45 return (uint32_t)sizeof(U);
46 }
47
48 static constexpr uint32_t alig() {
49 constexpr auto alig = mem::auto_view_policy<U>::Alignment;
50 static_assert(alig < Component::MaxAlignment, "Maximum supported alignment for a component is MaxAlignment");
51 return alig;
52 }
53
54 static uint32_t soa(std::span<uint8_t, meta::StructToTupleMaxTypes> soaSizes) {
55 if constexpr (mem::is_soa_layout_v<U>) {
56 uint32_t i = 0;
57 using TTuple = decltype(meta::struct_to_tuple(std::declval<U>()));
58 // is_soa_layout_v is always false for empty types so we know there is at least one element in the tuple
59 constexpr auto TTupleSize = std::tuple_size_v<TTuple>;
60 static_assert(TTupleSize > 0);
61 static_assert(TTupleSize <= meta::StructToTupleMaxTypes);
62 core::each_tuple<TTuple>([&](auto&& item) {
63 static_assert(sizeof(item) <= 255, "Each member of a SoA component can be at most 255 B long!");
64 soaSizes[i] = (uint8_t)sizeof(item);
65 ++i;
66 });
67 GAIA_ASSERT(i <= meta::StructToTupleMaxTypes);
68 return i;
69 } else {
70 return 0U;
71 }
72 }
73
74 static constexpr auto func_ctor() {
75 if constexpr (!mem::is_soa_layout_v<U> && !std::is_trivially_constructible_v<U>) {
76 return [](void* ptr, uint32_t cnt) {
77 core::call_ctor_n((U*)ptr, cnt);
78 };
79 } else {
80 return nullptr;
81 }
82 }
83
84 static constexpr auto func_dtor() {
85 if constexpr (!mem::is_soa_layout_v<U> && !std::is_trivially_destructible_v<U>) {
86 return [](void* ptr, uint32_t cnt) {
87 core::call_dtor_n((U*)ptr, cnt);
88 };
89 } else {
90 return nullptr;
91 }
92 }
93
94 static constexpr auto func_copy_ctor() {
95 return [](void* GAIA_RESTRICT dst, const void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
96 uint32_t sizeDst, uint32_t sizeSrc) {
97 mem::copy_ctor_element<U>((uint8_t*)dst, (const uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
98 };
99 }
100
101 static constexpr auto func_move_ctor() {
102 return [](void* GAIA_RESTRICT dst, void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
103 uint32_t sizeDst, uint32_t sizeSrc) {
104 mem::move_ctor_element<U>((uint8_t*)dst, (uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
105 };
106 }
107
108 static constexpr auto func_copy() {
109 return [](void* GAIA_RESTRICT dst, const void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
110 uint32_t sizeDst, uint32_t sizeSrc) {
111 mem::copy_element<U>((uint8_t*)dst, (const uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
112 };
113 }
114
115 static constexpr auto func_move() {
116 return [](void* GAIA_RESTRICT dst, void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
117 uint32_t sizeDst, uint32_t sizeSrc) {
118 mem::move_element<U>((uint8_t*)dst, (uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
119 };
120 }
121
122 static constexpr auto func_swap() {
123 return [](void* GAIA_RESTRICT left, void* GAIA_RESTRICT right, uint32_t idxLeft, uint32_t idxRight,
124 uint32_t sizeLeft, uint32_t sizeRight) {
125 mem::swap_elements<U>((uint8_t*)left, (uint8_t*)right, idxLeft, idxRight, sizeLeft, sizeRight);
126 };
127 }
128
129 static constexpr auto func_cmp() {
130 if constexpr (mem::is_soa_layout_v<U>) {
131 return []([[maybe_unused]] const void* left, [[maybe_unused]] const void* right) {
132 GAIA_ASSERT(false && "func_cmp for SoA not implemented yet");
133 return false;
134 };
135 } else {
136 constexpr bool hasGlobalCmp = core::has_ffunc_equals<U>::value;
137 constexpr bool hasMemberCmp = core::has_func_equals<U>::value;
138 if constexpr (hasGlobalCmp || hasMemberCmp) {
139 return [](const void* left, const void* right) {
140 const auto* l = (const U*)left;
141 const auto* r = (const U*)right;
142 return *l == *r;
143 };
144 } else {
145 // fallback comparison function
146 return [](const void* left, const void* right) {
147 const auto* l = (const U*)left;
148 const auto* r = (const U*)right;
149 return memcmp(l, r, sizeof(U)) == 0;
150 };
151 }
152 }
153 }
154
155 static constexpr auto func_save() {
156 return [](ser::ISerializer* pSer, const void* pSrc, uint32_t from, uint32_t to, uint32_t cap) {
157 const auto* pComponent = (const U*)pSrc;
158
159#if GAIA_ASSERT_ENABLED
160 // Check if save and load match. Testing with one item is enough.
161 pSer->check(*pComponent);
162#endif
163
164 if constexpr (mem::is_soa_layout_v<U>) {
165 auto view = mem::auto_view_policy_get<U>{std::span{(const uint8_t*)pSrc, cap}};
166 GAIA_FOR2(from, to) {
167 auto val = view[i];
168 pSer->save(val);
169 }
170 } else {
171 pComponent += from;
172 GAIA_FOR2(from, to) {
173 pSer->save(*pComponent);
174 ++pComponent;
175 }
176 }
177 };
178 }
179
180 static constexpr auto func_load() {
181 return [](ser::ISerializer* pSer, void* pDst, uint32_t from, uint32_t to, uint32_t cap) {
182 if constexpr (mem::is_soa_layout_v<U>) {
183 auto view = mem::auto_view_policy_set<U>{std::span{(uint8_t*)pDst, cap}};
184 GAIA_FOR2(from, to) {
185 U val;
186 pSer->load(val);
187 view[i] = val;
188 }
189 } else {
190 auto* pComponent = (U*)pDst + from;
191 GAIA_FOR2(from, to) {
192 pSer->load(*pComponent);
193 ++pComponent;
194 }
195 }
196 };
197 }
198 };
199 } // namespace detail
200 } // namespace ecs
201} // namespace gaia
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition utility.h:527
Definition utility.h:522
Definition component_desc.h:24
Definition data_layout_policy.h:90
Definition data_layout_policy.h:92
Definition data_layout_policy.h:87
Definition ser_rt.h:13