2#include "gaia/config/config.h"
7#include "gaia/ecs/component_cache.h"
8#include "gaia/ecs/component_cache_item.h"
9#include "gaia/ecs/id.h"
10#include "gaia/util/str.h"
15 void world_finish_write(World& world, Entity term, Entity entity);
19 enum ComponentRawViewFlags : uint32_t {
21 ComponentRawViewFlag_None = 0,
23 ComponentRawViewFlag_Valid = 1U << 0
36 const void*
data =
nullptr;
40 uint32_t
flags = ComponentRawViewFlag_None;
43 GAIA_NODISCARD
bool valid() const noexcept {
44 return (
flags & ComponentRawViewFlag_Valid) != 0;
47 static_assert(
sizeof(ComponentRawView) == 16,
"ComponentRawView must stay compact");
64 uint32_t
flags = ComponentRawViewFlag_None;
67 GAIA_NODISCARD
bool valid() const noexcept {
68 return (
flags & ComponentRawViewFlag_Valid) != 0;
71 static_assert(
sizeof(ComponentRawMutView) == 16,
"ComponentRawMutView must stay compact");
74 enum class ComponentWriteResult : uint8_t { Ok, Invalid, ReadOnly, OutOfRange };
99 cursor.m_components = &components;
100 cursor.m_stack[0].type = component;
101 cursor.m_stack[0].data = view.
data;
102 cursor.m_stack[0].size = view.
size;
103 cursor.m_valid =
true;
120 cursor.m_world = &world;
121 cursor.m_components = &components;
122 cursor.m_entity = entity;
123 cursor.m_rootType = component;
124 cursor.m_stack[0].type = component;
125 cursor.m_stack[0].data = view.
data;
126 cursor.m_stack[0].mutData = view.
data;
127 cursor.m_stack[0].size = view.
size;
128 cursor.m_stack[0].writable =
true;
129 cursor.m_valid =
true;
134 GAIA_NODISCARD
bool valid() const noexcept {
139 GAIA_NODISCARD uint32_t
depth() const noexcept {
145 return m_valid ? m_stack[m_depth].type : EntityBad;
149 GAIA_NODISCARD uint32_t
size() const noexcept {
150 return m_valid ? m_stack[m_depth].size : 0;
154 GAIA_NODISCARD
const void*
ptr() const noexcept {
155 return m_valid ? m_stack[m_depth].data :
nullptr;
159 GAIA_NODISCARD
void*
mut_ptr() const noexcept {
160 return m_valid ? m_stack[m_depth].mutData :
nullptr;
165 const auto* pItem = current_item();
166 return pItem !=
nullptr ? pItem->field_count() : 0;
173 const auto* pItem = current_item();
174 if (pItem ==
nullptr || index >= pItem->field_count())
176 return descend(pItem->fields[index]);
183 const auto* pItem = current_item();
184 if (pItem ==
nullptr)
188 if (!pItem->field(name, &pField) || pField ==
nullptr)
190 return descend(*pField);
196 if (!m_valid || m_depth == 0)
205 GAIA_NODISCARD
bool get_f32(
float* value)
const noexcept {
206 if (value ==
nullptr || !m_valid ||
size() !=
sizeof(
float) ||
ptr() ==
nullptr)
208 memcpy(value,
ptr(),
sizeof(
float));
221 ComponentWriteResult
write_bytes(
const void* data, uint32_t byteCount)
noexcept {
223 return ComponentWriteResult::Invalid;
224 if (!m_stack[m_depth].writable || m_world ==
nullptr || m_entity == EntityBad || m_rootType == EntityBad)
225 return ComponentWriteResult::ReadOnly;
226 if (byteCount !=
size())
227 return ComponentWriteResult::OutOfRange;
229 return ComponentWriteResult::Ok;
230 if (data ==
nullptr ||
mut_ptr() ==
nullptr)
231 return ComponentWriteResult::Invalid;
233 memcpy(
mut_ptr(), data, byteCount);
234 world_finish_write(*m_world, m_rootType, m_entity);
235 return ComponentWriteResult::Ok;
241 const void* data =
nullptr;
242 void* mutData =
nullptr;
244 bool writable =
false;
247 World* m_world =
nullptr;
248 const ComponentCache* m_components =
nullptr;
249 Entity m_entity = EntityBad;
250 Entity m_rootType = EntityBad;
252 uint32_t m_depth = 0;
253 bool m_valid =
false;
255 GAIA_NODISCARD
const ComponentCacheItem* current_item() const noexcept {
256 if (!m_valid || m_components ==
nullptr)
258 return m_components->find(m_stack[m_depth].
type);
261 bool descend(
const RuntimeField&
field)
noexcept {
262 if (!m_valid || m_components ==
nullptr || m_depth + 1 >=
MaxDepth)
265 const auto* pType = m_components->find(
field.type);
266 if (pType ==
nullptr)
269 const auto elemSize = pType->comp.size();
270 const auto elemCount = ComponentCacheItem::field_element_count(
field);
271 const auto fieldSize64 = (uint64_t)elemSize * (uint64_t)elemCount;
272 const auto end = (uint64_t)
field.offset + fieldSize64;
273 if (fieldSize64 > UINT32_MAX || end > m_stack[m_depth].
size)
277 next.type =
field.type;
278 next.size = (uint32_t)fieldSize64;
279 next.writable = m_stack[m_depth].writable;
280 if (m_stack[m_depth].data !=
nullptr)
281 next.data = (
const uint8_t*)m_stack[m_depth].data +
field.offset;
282 if (m_stack[m_depth].mutData !=
nullptr)
283 next.mutData = (uint8_t*)m_stack[m_depth].mutData +
field.offset;
285 m_stack[++m_depth] = next;
Cache for compile-time defined components.
Definition component_cache.h:24
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Stack-only cursor over raw component bytes and runtime field metadata.
Definition component_cursor.h:81
bool field(uint32_t index)
Descends into the reflected field at index.
Definition component_cursor.h:172
GAIA_NODISCARD void * mut_ptr() const noexcept
Definition component_cursor.h:159
static GAIA_NODISCARD ComponentCursor from_raw(const ComponentCache &components, Entity component, ComponentRawView view)
Creates a read-only cursor from a raw component view.
Definition component_cursor.h:94
GAIA_NODISCARD uint32_t field_count() const
Definition component_cursor.h:164
ComponentCursor()=default
Creates an invalid cursor.
bool parent() noexcept
Moves back to the parent cursor scope.
Definition component_cursor.h:195
GAIA_NODISCARD uint32_t size() const noexcept
Definition component_cursor.h:149
GAIA_NODISCARD uint32_t depth() const noexcept
Definition component_cursor.h:139
GAIA_NODISCARD bool valid() const noexcept
Definition component_cursor.h:134
GAIA_NODISCARD bool get_f32(float *value) const noexcept
Reads the current cursor bytes as a scalar f32 convenience value.
Definition component_cursor.h:205
GAIA_NODISCARD Entity type() const noexcept
Definition component_cursor.h:144
GAIA_NODISCARD const void * ptr() const noexcept
Definition component_cursor.h:154
ComponentWriteResult write_bytes(const void *data, uint32_t byteCount) noexcept
Writes exact bytes to the current cursor position.
Definition component_cursor.h:221
static constexpr uint32_t MaxDepth
Maximum nested field depth tracked by the cursor.
Definition component_cursor.h:83
static GAIA_NODISCARD ComponentCursor from_raw(World &world, const ComponentCache &components, Entity entity, Entity component, ComponentRawMutView view)
Creates a mutable cursor from a raw component view.
Definition component_cursor.h:114
bool field(util::str_view name)
Descends into the reflected field named name.
Definition component_cursor.h:182
Non-owning mutable view over raw component bytes on an entity.
Definition component_cursor.h:58
void * data
Raw component payload bytes. Null for tags and invalid views.
Definition component_cursor.h:60
uint32_t flags
Bitmask of ComponentRawViewFlags values.
Definition component_cursor.h:64
uint32_t size
Payload size in bytes.
Definition component_cursor.h:62
GAIA_NODISCARD bool valid() const noexcept
Definition component_cursor.h:67
Non-owning read-only view over raw component bytes on an entity.
Definition component_cursor.h:34
uint32_t size
Payload size in bytes.
Definition component_cursor.h:38
uint32_t flags
Bitmask of ComponentRawViewFlags values.
Definition component_cursor.h:40
GAIA_NODISCARD bool valid() const noexcept
Definition component_cursor.h:43
const void * data
Raw component payload bytes. Null for tags and invalid views.
Definition component_cursor.h:36
Stored runtime field metadata.
Definition component_desc.h:65
Lightweight non-owning string view over a character sequence.
Definition str.h:13