Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
chunk_iterator_typed.inl
1#pragma once
2
3namespace gaia {
4 namespace ecs {
6 namespace detail {
7 template <typename T>
8 IterTermDesc ChunkIterTypedOps::term_desc(const ChunkIterImpl& self) {
9 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
10 IterTermDesc desc;
11 if constexpr (std::is_same_v<Arg, Entity>) {
12 desc.termId = EntityBad;
13 desc.isEntity = true;
14 } else {
15 desc.termId = world_query_arg_id<Arg>(*const_cast<World*>(self.world()));
16 desc.isEntity = false;
17 desc.usesSparseStorage = uses_ct_sparse_storage_v<Arg>;
18 desc.storageKnown = true;
19 }
20 return desc;
21 }
22
23 template <typename T>
24 auto ChunkIterTypedOps::view_any(const ChunkIterImpl& self) {
25#if GAIA_ASSERT_ENABLED
26 self.assert_term_access(ChunkIterTypedOps::template term_desc<T>(self).termId);
27#endif
28 using U = typename actual_type_t<T>::Type;
29 if constexpr (std::is_same_v<U, Entity> || mem::is_soa_layout_v<U>)
30 return self.m_pChunk->template view<T>(self.from(), self.to());
31 else if constexpr (uses_ct_sparse_storage_v<T>) {
32 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
33 auto* pWorld = const_cast<World*>(self.world());
34 return EntityTermViewGetSparse<U>{
35 self.m_pChunk->entity_view().data() + self.from(), pWorld,
36 world_typed_sparse_store_ptr<U>(*pWorld, desc.termId), desc.termId, self.size()};
37 } else {
38 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
39 const auto id = desc.usesSparseStorage ? desc.termId : EntityBad;
40
41 if (id != EntityBad)
42 return EntityTermViewGet<U>::entity(
43 self.m_pChunk->entity_view().data() + self.from(), const_cast<World*>(self.world()), id, self.size());
44
45 auto* pData = reinterpret_cast<const U*>(self.m_pChunk->template view<T>(self.from(), self.to()).data());
46 return EntityTermViewGet<U>::pointer(pData, self.size());
47 }
48 }
49
50 template <typename T>
51 auto ChunkIterTypedOps::view_any(ChunkIterImpl& self, uint32_t termIdx) {
52#if GAIA_ASSERT_ENABLED
53 self.assert_term_access(termIdx, ChunkIterTypedOps::template term_desc<T>(self).termId);
54#endif
55 using U = typename actual_type_t<T>::Type;
56
57 if constexpr (mem::is_soa_layout_v<U>) {
58 const auto compIdx = self.m_pCompIndices[termIdx];
59 if (compIdx == 0xFF) {
60 const auto* pEntities = self.m_pChunk->entity_view().data() + self.from();
61 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
62 GAIA_ASSERT(desc.termId != EntityBad);
63 return SoATermViewGet<U>{nullptr, 0, pEntities, const_cast<World*>(self.world()),
64 desc.termId, 0, self.size()};
65 }
66
67 GAIA_ASSERT(compIdx < self.m_pChunk->ids_view().size());
68 return SoATermViewGet<U>{
69 self.m_pChunk->comp_ptr(compIdx),
70 self.m_pChunk->capacity(),
71 nullptr,
72 const_cast<World*>(self.world()),
73 EntityBad,
74 self.from(),
75 self.size()};
76 } else if constexpr (uses_ct_sparse_storage_v<T>) {
77 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
78 auto* pWorld = const_cast<World*>(self.world());
79 return EntityTermViewGetSparse<U>{
80 self.m_pChunk->entity_view().data() + self.from(), pWorld,
81 world_typed_sparse_store_ptr<U>(*pWorld, desc.termId), desc.termId, self.size()};
82 } else {
83 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
84 const auto compIdx = self.m_pCompIndices[termIdx];
85 if (desc.usesSparseStorage)
86 return EntityTermViewGet<U>::entity(
87 self.m_pChunk->entity_view().data() + self.from(), const_cast<World*>(self.world()), desc.termId,
88 self.size());
89
90 if (compIdx == 0xFF) {
91 GAIA_ASSERT(desc.termId != EntityBad);
92 if (!self.m_inheritedData.empty()) {
93 const auto* pInheritedValue = reinterpret_cast<const U*>(self.m_inheritedData[termIdx]);
94 if (pInheritedValue != nullptr)
95 return EntityTermViewGet<U>::inherited(pInheritedValue, self.size());
96 }
97 if (world_term_uses_inherit_policy(*self.world(), desc.termId)) {
98 return EntityTermViewGet<U>::entity_chunk_stable(
99 self.m_pChunk->entity_view().data() + self.from(), self.m_pChunk, const_cast<World*>(self.world()),
100 desc.termId, self.from(), self.size());
101 }
102 return EntityTermViewGet<U>::entity(
103 self.m_pChunk->entity_view().data() + self.from(), const_cast<World*>(self.world()), desc.termId,
104 self.size());
105 }
106 GAIA_ASSERT(compIdx < self.m_pChunk->ids_view().size());
107
108 auto* pData = reinterpret_cast<const U*>(self.m_pChunk->comp_ptr_mut(compIdx, self.from()));
109 return EntityTermViewGet<U>::pointer(pData, self.size());
110 }
111 }
112
113 template <typename T>
114 auto ChunkIterTypedOps::view(const ChunkIterImpl& self) {
115#if GAIA_ASSERT_ENABLED
116 self.assert_term_access(ChunkIterTypedOps::template term_desc<T>(self).termId);
117#endif
118 using U = typename actual_type_t<T>::Type;
119 if constexpr (std::is_same_v<U, Entity>)
120 return self.m_pChunk->template view<T>(self.from(), self.to());
121 else if constexpr (mem::is_soa_layout_v<U>) {
122 const auto view = self.m_pChunk->template view<T>(self.from(), self.to());
123 return SoATermViewGetPointer<U>{(const uint8_t*)view.data(), (uint32_t)view.size(), self.from(), self.size()};
124 } else {
125 auto* pData = reinterpret_cast<const U*>(self.m_pChunk->template view<T>(self.from(), self.to()).data());
126 return EntityTermViewGetPointer<U>{pData, self.size()};
127 }
128 }
129
130 template <typename T>
131 auto ChunkIterTypedOps::view(const ChunkIterImpl& self, uint32_t termIdx) {
132#if GAIA_ASSERT_ENABLED
133 self.assert_term_access(termIdx, ChunkIterTypedOps::template term_desc<T>(self).termId);
134#endif
135 using U = typename actual_type_t<T>::Type;
136 const auto compIdx = self.m_pCompIndices[termIdx];
137 GAIA_ASSERT(compIdx != 0xFF);
138
139 if constexpr (mem::is_soa_layout_v<U>)
140 return SoATermViewGetPointer<U>{
141 self.m_pChunk->comp_ptr(compIdx), self.m_pChunk->capacity(), self.from(), self.size()};
142 else {
143 auto* pData = reinterpret_cast<const U*>(self.m_pChunk->comp_ptr(compIdx, self.from()));
144 return EntityTermViewGetPointer<U>{pData, self.size()};
145 }
146 }
147
148 template <typename T>
149 auto ChunkIterTypedOps::view_any_mut(ChunkIterImpl& self) {
150#if GAIA_ASSERT_ENABLED
151 self.assert_term_access(ChunkIterTypedOps::template term_desc<T>(self).termId);
152#endif
153 using U = typename actual_type_t<T>::Type;
154 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via view_mut is forbidden");
155 if constexpr (mem::is_soa_layout_v<U>) {
156 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
157 const bool tracked = self.touch_term_desc(desc);
158 GAIA_ASSERT(tracked);
159 (void)tracked;
160 if (self.m_writeIm)
161 return self.m_pChunk->template view_mut<T>(self.from(), self.to());
162 return self.m_pChunk->template sview_mut<T>(self.from(), self.to());
163 } else if constexpr (uses_ct_sparse_storage_v<T>) {
164 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
165 if (!self.touch_term(desc.termId))
166 return EntityTermViewSetSparse<U>{};
167 auto* pWorld = const_cast<World*>(self.world());
168 return EntityTermViewSetSparse<U>{
169 self.entity_snapshot(), pWorld, world_typed_sparse_store_ptr<U>(*pWorld, desc.termId), desc.termId,
170 self.size()};
171 } else {
172 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
173 const auto id = desc.usesSparseStorage ? desc.termId : EntityBad;
174
175 if (id != EntityBad) {
176 if (!self.touch_term(id))
177 return self.template entity_view_set_empty<U>(self.m_writeIm);
178 return self.template entity_view_set<U>(id, self.m_writeIm);
179 }
180
181 if (!self.touch_term_desc(desc))
182 return self.template entity_view_set_empty<U>(self.m_writeIm);
183 auto* pData =
184 reinterpret_cast<U*>((self.m_writeIm ? self.m_pChunk->template view_mut<T>(self.from(), self.to())
185 : self.m_pChunk->template sview_mut<T>(self.from(), self.to()))
186 .data());
187 return EntityTermViewSet<U>::pointer(pData, self.size());
188 }
189 }
190
191 template <typename T>
192 auto ChunkIterTypedOps::view_mut(ChunkIterImpl& self) {
193#if GAIA_ASSERT_ENABLED
194 self.assert_term_access(ChunkIterTypedOps::template term_desc<T>(self).termId);
195#endif
196 using U = typename actual_type_t<T>::Type;
197 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via view_mut is forbidden");
198 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
199 const bool tracked = self.touch_term_desc(desc);
200 if constexpr (mem::is_soa_layout_v<U>) {
201 if (!tracked)
202 return SoATermViewSetPointer<U>{};
203 auto view = self.m_writeIm ? self.m_pChunk->template view_mut<T>(self.from(), self.to())
204 : self.m_pChunk->template sview_mut<T>(self.from(), self.to());
205 return SoATermViewSetPointer<U>{(uint8_t*)view.data(), (uint32_t)view.size(), self.from(), self.size()};
206 } else {
207 if (!tracked)
208 return EntityTermViewSetPointer<U>{};
209 auto* pData =
210 reinterpret_cast<U*>((self.m_writeIm ? self.m_pChunk->template view_mut<T>(self.from(), self.to())
211 : self.m_pChunk->template sview_mut<T>(self.from(), self.to()))
212 .data());
213 return EntityTermViewSetPointer<U>{pData, self.size()};
214 }
215 }
216
217 template <typename T>
218 auto ChunkIterTypedOps::view_mut(ChunkIterImpl& self, uint32_t termIdx) {
219#if GAIA_ASSERT_ENABLED
220 self.assert_term_access(termIdx, ChunkIterTypedOps::template term_desc<T>(self).termId);
221#endif
222 using U = typename actual_type_t<T>::Type;
223 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via view_mut is forbidden");
224 const auto compIdx = self.m_pCompIndices[termIdx];
225 GAIA_ASSERT(compIdx != 0xFF);
226 self.touch_comp_idx(compIdx);
227
228 if constexpr (mem::is_soa_layout_v<U>) {
229 if (self.m_writeIm)
230 self.m_pChunk->update_world_version(compIdx);
231 return SoATermViewSetPointer<U>{
232 self.m_pChunk->comp_ptr_mut(compIdx), self.m_pChunk->capacity(), self.from(), self.size()};
233 } else {
234 if (self.m_writeIm)
235 self.m_pChunk->update_world_version(compIdx);
236 auto* pData = reinterpret_cast<U*>(self.m_pChunk->comp_ptr_mut(compIdx, self.from()));
237 return EntityTermViewSetPointer<U>{pData, self.size()};
238 }
239 }
240
241 template <typename T>
242 auto ChunkIterTypedOps::view_any_mut(ChunkIterImpl& self, uint32_t termIdx) {
243#if GAIA_ASSERT_ENABLED
244 self.assert_term_access(termIdx, ChunkIterTypedOps::template term_desc<T>(self).termId);
245#endif
246 using U = typename actual_type_t<T>::Type;
247
248 if constexpr (mem::is_soa_layout_v<U>) {
249 const auto compIdx = self.m_pCompIndices[termIdx];
250 if (compIdx == 0xFF) {
251 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
252 GAIA_ASSERT(desc.termId != EntityBad);
253 if (!self.touch_term(desc.termId))
254 return self.template entity_soa_view_set_empty<U>(self.m_writeIm);
255 return self.template entity_soa_view_set<U>(desc.termId, self.m_writeIm);
256 }
257
258 GAIA_ASSERT(compIdx < self.m_pChunk->comp_rec_view().size());
259 self.touch_comp_idx(compIdx);
260 if (self.m_writeIm)
261 self.m_pChunk->update_world_version(compIdx);
262 return SoATermViewSet<U>{
263 self.m_pChunk->comp_ptr_mut(compIdx),
264 self.m_pChunk->capacity(),
265 nullptr,
266 self.world(),
267 EntityBad,
268 self.from(),
269 self.size(),
270 self.m_writeIm};
271 } else if constexpr (uses_ct_sparse_storage_v<T>) {
272 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
273 if (!self.touch_term(desc.termId))
274 return EntityTermViewSetSparse<U>{};
275 auto* pWorld = const_cast<World*>(self.world());
276 return EntityTermViewSetSparse<U>{
277 self.entity_snapshot(), pWorld, world_typed_sparse_store_ptr<U>(*pWorld, desc.termId), desc.termId,
278 self.size()};
279 } else {
280 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
281 const auto compIdx = self.m_pCompIndices[termIdx];
282 if (desc.usesSparseStorage || compIdx == 0xFF) {
283 GAIA_ASSERT(desc.termId != EntityBad);
284 if (!self.touch_term(desc.termId))
285 return self.template entity_view_set_empty<U>(self.m_writeIm);
286 return self.template entity_view_set<U>(desc.termId, self.m_writeIm);
287 }
288 GAIA_ASSERT(compIdx < self.m_pChunk->comp_rec_view().size());
289
290 self.touch_comp_idx(compIdx);
291 if (self.m_writeIm)
292 self.m_pChunk->update_world_version(compIdx);
293
294 auto* pData = reinterpret_cast<U*>(self.m_pChunk->comp_ptr_mut(compIdx, self.from()));
295 return EntityTermViewSet<U>::pointer(pData, self.size());
296 }
297 }
298
299 template <typename T>
300 auto ChunkIterTypedOps::sview_any_mut(ChunkIterImpl& self) {
301#if GAIA_ASSERT_ENABLED
302 self.assert_term_access(ChunkIterTypedOps::template term_desc<T>(self).termId);
303#endif
304 using U = typename actual_type_t<T>::Type;
305 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via sview_mut is forbidden");
306 if constexpr (mem::is_soa_layout_v<U>)
307 return self.m_pChunk->template sview_mut<T>(self.from(), self.to());
308 else if constexpr (uses_ct_sparse_storage_v<T>) {
309 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
310 auto* pWorld = const_cast<World*>(self.world());
311 return EntityTermViewSetSparse<U>{
312 self.entity_snapshot(), pWorld, world_typed_sparse_store_ptr<U>(*pWorld, desc.termId), desc.termId,
313 self.size()};
314 } else {
315 const auto desc = ChunkIterTypedOps::template term_desc<T>(self);
316 const auto id = desc.usesSparseStorage ? desc.termId : EntityBad;
317
318 if (id != EntityBad)
319 return self.template entity_view_set<U>(id, false);
320
321 auto* pData = reinterpret_cast<U*>(self.m_pChunk->template sview_mut<T>(self.from(), self.to()).data());
322 return EntityTermViewSet<U>::pointer(pData, self.size());
323 }
324 }
325
326 template <typename T>
327 auto ChunkIterTypedOps::sview_mut(ChunkIterImpl& self) {
328#if GAIA_ASSERT_ENABLED
329 self.assert_term_access(ChunkIterTypedOps::template term_desc<T>(self).termId);
330#endif
331 using U = typename actual_type_t<T>::Type;
332 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via sview_mut is forbidden");
333 if constexpr (mem::is_soa_layout_v<U>) {
334 auto view = self.m_pChunk->template sview_mut<T>(self.from(), self.to());
335 return SoATermViewSetPointer<U>{(uint8_t*)view.data(), (uint32_t)view.size(), self.from(), self.size()};
336 } else {
337 auto* pData = reinterpret_cast<U*>(self.m_pChunk->template sview_mut<T>(self.from(), self.to()).data());
338 return EntityTermViewSetPointer<U>{pData, self.size()};
339 }
340 }
341
342 template <typename T>
343 auto ChunkIterTypedOps::sview_mut(ChunkIterImpl& self, uint32_t termIdx) {
344#if GAIA_ASSERT_ENABLED
345 self.assert_term_access(termIdx, ChunkIterTypedOps::template term_desc<T>(self).termId);
346#endif
347 using U = typename actual_type_t<T>::Type;
348 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via sview_mut is forbidden");
349 const auto compIdx = self.m_pCompIndices[termIdx];
350 GAIA_ASSERT(compIdx != 0xFF);
351
352 if constexpr (mem::is_soa_layout_v<U>)
353 return SoATermViewSetPointer<U>{
354 self.m_pChunk->comp_ptr_mut(compIdx), self.m_pChunk->capacity(), self.from(), self.size()};
355 else {
356 auto* pData = reinterpret_cast<U*>(self.m_pChunk->comp_ptr_mut(compIdx, self.from()));
357 return EntityTermViewSetPointer<U>{pData, self.size()};
358 }
359 }
360
361 template <typename T>
362 auto ChunkIterTypedOps::sview_any_mut(ChunkIterImpl& self, uint32_t termIdx) {
363#if GAIA_ASSERT_ENABLED
364 self.assert_term_access(termIdx, ChunkIterTypedOps::template term_desc<T>(self).termId);
365#endif
366 using U = typename actual_type_t<T>::Type;
367
368 if constexpr (mem::is_soa_layout_v<U>) {
369 const auto compIdx = self.m_pCompIndices[termIdx];
370 if (compIdx == 0xFF) {
371 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
372 GAIA_ASSERT(desc.termId != EntityBad);
373 return self.template entity_soa_view_set<U>(desc.termId, false);
374 }
375
376 GAIA_ASSERT(compIdx < self.m_pChunk->ids_view().size());
377 return SoATermViewSet<U>{
378 self.m_pChunk->comp_ptr_mut(compIdx),
379 self.m_pChunk->capacity(),
380 nullptr,
381 self.world(),
382 EntityBad,
383 self.from(),
384 self.size(),
385 false};
386 } else if constexpr (uses_ct_sparse_storage_v<T>) {
387 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
388 auto* pWorld = const_cast<World*>(self.world());
389 return EntityTermViewSetSparse<U>{
390 self.entity_snapshot(), pWorld, world_typed_sparse_store_ptr<U>(*pWorld, desc.termId), desc.termId,
391 self.size()};
392 } else {
393 const auto desc = self.resolved_term_desc(termIdx, ChunkIterTypedOps::template term_desc<T>(self));
394 const auto compIdx = self.m_pCompIndices[termIdx];
395 if (desc.usesSparseStorage || compIdx == 0xFF) {
396 GAIA_ASSERT(desc.termId != EntityBad);
397 return self.template entity_view_set<U>(desc.termId, false);
398 }
399 GAIA_ASSERT(compIdx < self.m_pChunk->ids_view().size());
400
401 auto* pData = reinterpret_cast<U*>(self.m_pChunk->comp_ptr_mut(compIdx, self.from()));
402 return EntityTermViewSet<U>::pointer(pData, self.size());
403 }
404 }
405
406 } // namespace detail
408
409 } // namespace ecs
410} // namespace gaia