Cogs.Core
Component.h
1#pragma once
2
3#include "../Reflection/Name.h"
4
5#include <cstdint>
6
8namespace Cogs
9{
10 namespace Reflection
11 {
12 class Type;
13 }
14
16 using ComponentIndex = uint32_t;
17
20
22 namespace ComponentModel
23 {
26 {
30 enum EComponentFlags : uint32_t
31 {
33 None = 0x00,
35 Active = 0x01,
36
38 Changed = 0x02,
39
42
51
54
56 FieldChange = 0x100,
57
60 };
61 };
62
67 {
69 ComponentHandle() = default;
70
72 ComponentHandle(const ComponentHandle & other) = default;
73
76
78 constexpr ComponentHandle(class ComponentPoolBase* pool, ComponentIndex index, Reflection::TypeId typeId, uint16_t generation)
79 : pool(pool), index(index), typeId(typeId), generation(generation)
80 {
81 }
82
83
85 COGSFOUNDATION_API class Component * resolve() const;
86
89 template<typename ComponentType>
90 inline ComponentType * resolveComponent() const
91 {
92 return static_cast<ComponentType *>(resolve());
93 }
94
116 explicit operator bool() const { return resolve() != nullptr; }
117
120 {
121 return ComponentHandle{ nullptr, 0, 0, 0 };
122 }
123
125 class ComponentPoolBase * pool = nullptr;
126 ComponentIndex index = 0;
128 uint16_t generation = 0;
130 };
131
133 [[nodiscard]] constexpr bool operator==(const ComponentHandle & a, const ComponentHandle & b)
134 {
135 return a.pool == b.pool && a.index == b.index && a.typeId == b.typeId;
136 }
137
143 {
144 public:
145 Component() = default;
146
148 COGSFOUNDATION_API static void registerType();
149
151 class Entity * getContainer() const { return container; }
152
154 void setContainer(class Entity * container) { this->container = container; }
155
158 template<typename ComponentType>
159 ComponentType * getComponent() const
160 {
161 static Reflection::TypeId id(getComponentTypeId(::getName<ComponentType>()));
162
163 return static_cast<ComponentType *>(getComponent(id));
164 }
165
168 COGSFOUNDATION_API Component * getComponent(const Reflection::Name & name) const;
169
172 COGSFOUNDATION_API Component * getComponent(const Reflection::TypeId & id) const;
173
176 template<typename ComponentType>
178 {
179 static Reflection::TypeId id(getComponentTypeId(::getName<ComponentType>()));
180
181 return getComponentHandle(id);
182 }
183
186 COGSFOUNDATION_API ComponentHandle getComponentHandle(const Reflection::Name & name) const;
187
190 COGSFOUNDATION_API ComponentHandle getComponentHandle(const Reflection::TypeId & id) const;
191
194
196 bool isActive() const { return isSet(ComponentFlags::Active); }
197
203
210
219 {
220 const uint32_t fieldBit = leftShift(ComponentFlags::FieldChange, fieldId);
221 setFlag((fieldBit ? fieldBit : ComponentFlags::OverflowFieldChange) |
224 }
225
236 template<typename ClassType, typename FieldType>
237 void setFieldChanged(FieldType ClassType::* field)
238 {
239 return this->setFieldChanged(getFieldId(field));
240 }
241
251 {
252 const uint32_t fieldBit = leftShift(ComponentFlags::FieldChange, fieldId);
253 setFlag((fieldBit ? fieldBit : ComponentFlags::OverflowFieldChange) |
255 }
256
259 bool hasChanged() const { return isSet(ComponentFlags::Changed); }
260
263
272 bool hasFieldChanged(const Reflection::FieldId fieldId) const
273 {
274 const uint32_t fieldBit = leftShift(ComponentFlags::FieldChange, fieldId);
275 return fieldBit ? isSet(fieldBit) : isSet(ComponentFlags::OverflowFieldChange);
276 }
277
289 template<typename ClassType, typename FieldType>
290 bool hasFieldChanged(FieldType ClassType::* field) const
291 {
292 return hasFieldChanged(getFieldId(field));
293 }
294
297 {
299 }
300
310 {
314 }
315 }
316
327 template<typename ClassType, typename FieldType>
328 Reflection::FieldId getFieldId(FieldType ClassType::* field) const
329 {
330 return getFieldIdFromOffset(memberOffset(field));
331 }
332
335
343 {
344 const uint32_t fieldBit = leftShift(ComponentFlags::FieldChange, fieldId);
345 // If Field is Overflow flags the fieldBit will be zero -> not resetting any flags.
346 unsetFlag(fieldBit);
347 }
348
358 template<typename ClassType, typename FieldType>
359 void resetFieldChanged(FieldType ClassType::* field)
360 {
361 return resetFieldChanged(getFieldId(field));
362 }
363
365 constexpr void setFlags(const uint32_t flags) { this->flags = flags; }
366
368 constexpr void setFlag(const uint32_t flag) { this->flags |= flag; }
369
371 constexpr void unsetFlag(const uint32_t flag) { this->flags &= ~flag; }
372
374 [[nodiscard]] constexpr bool isSet(const uint32_t flag) const { return (flags & flag) == flag; }
375
377 constexpr void setTypeId(const Reflection::TypeId typeId) { this->typeId = typeId; }
378
380 [[nodiscard]] constexpr Reflection::TypeId getTypeId() const { return typeId; }
381
383 [[nodiscard]] COGSFOUNDATION_API const Reflection::Type & getType() const;
384
386 [[nodiscard]] COGSFOUNDATION_API static Reflection::TypeId getComponentTypeId(const StringView & name);
387
389 constexpr void setIndex(const ComponentIndex index) { this->index = index; }
390
392 [[nodiscard]] constexpr ComponentIndex getIndex() const { return index; }
393
395 constexpr void setGeneration(uint16_t generation) {
396 this->generation = generation;
397 }
398
400 [[nodiscard]] constexpr uint16_t getGeneration() const {
401 return generation;
402 }
403
405 [[nodiscard]] size_t hash(size_t hashValue = Cogs::hash()) const {
406 hashValue = Cogs::hash(reinterpret_cast<intptr_t>(container), hashValue);
407 hashValue = Cogs::hash(index, hashValue);
408 hashValue = Cogs::hash(flags, hashValue);
409 hashValue = Cogs::hash(typeId, hashValue);
410 hashValue = Cogs::hash(generation, hashValue);
411
412 return hashValue;
413 }
414
415 private:
416 // Must avoid shifting too long. C++ undefined behavior (GCC Unix problem)
417 [[nodiscard]] static constexpr uint32_t leftShift(const uint32_t value, const uint32_t fieldId)
418 {
419 return fieldId >= 32 ? 0u : (value << fieldId);
420 }
421
423 [[nodiscard]] COGSFOUNDATION_API Reflection::FieldId getFieldIdFromOffset(size_t offset) const;
424
426 class Entity * container = nullptr;
427 ComponentIndex index = 0;
430 uint16_t generation = 0;
432 };
433 }
434}
435
436template<> inline Cogs::StringView getName<Cogs::ComponentModel::Component>() { return "Component"; }
Untyped Component pool base.
Definition: ComponentPool.h:37
Base class for Component instances.
Definition: Component.h:143
static COGSFOUNDATION_API void registerType()
Register the Component type in the global type database.
Definition: Component.cpp:17
void setChanged()
Sets the component to the ComponentFlags::Changed state with carry.
Definition: Component.h:202
constexpr uint16_t getGeneration() const
Gets the component generation.
Definition: Component.h:400
Reflection::FieldId getFieldId(FieldType ClassType::*field) const
Gets field ID of the given field.
Definition: Component.h:328
constexpr void setIndex(const ComponentIndex index)
Set the components pool index. For internal use only.
Definition: Component.h:389
void setActive()
Sets the component to the ComponentFlags::Active state.
Definition: Component.h:193
constexpr void unsetFlag(const uint32_t flag)
Unset the given flag. Does not remove the status of other than the given flags.
Definition: Component.h:371
void setFieldChanged(const Reflection::FieldId fieldId)
Sets the component to the ComponentFlags::Changed state without carry.
Definition: Component.h:218
void setFieldChangedTransient(const Reflection::FieldId fieldId)
Sets the component to the ComponentFlags::Changed state without carry.
Definition: Component.h:250
constexpr ComponentIndex getIndex() const
Get the components pool index. For internal use only.
Definition: Component.h:392
ComponentType * getComponent() const
Definition: Component.h:159
bool isActive() const
Gets if the component is currently set to the ComponentFlags::Active state.
Definition: Component.h:196
static COGSFOUNDATION_API Reflection::TypeId getComponentTypeId(const StringView &name)
Get the type id of the component type with the given name.
Definition: Component.cpp:32
bool hasAnyfieldChanged() const
Gets if any fields have been changed.
Definition: Component.h:262
constexpr void setFlags(const uint32_t flags)
Override all flags of the Component, setting the given flags.
Definition: Component.h:365
void setChangedTransient()
Sets the component to the ComponentFlags::Changed state without carry.
Definition: Component.h:209
constexpr bool isSet(const uint32_t flag) const
Checks if the given flag is set. Requires exact bit match if test of several bits.
Definition: Component.h:374
void resetFieldsChanged()
Resets the state of all changed field flags.
Definition: Component.h:334
COGSFOUNDATION_API Reflection::FieldId getFieldIdFromOffset(size_t offset) const
Returns Field ID for the field with the given offset. Returns NoField if not a registered field.
Definition: Component.cpp:22
class Entity * getContainer() const
Get the container currently owning this component instance.
Definition: Component.h:151
constexpr void setTypeId(const Reflection::TypeId typeId)
Set the Reflection::TypeId of the component.
Definition: Component.h:377
void resetFieldChanged(const Reflection::FieldId fieldId)
Resets the changed state of the given fieldId.
Definition: Component.h:342
void resetFieldChanged(FieldType ClassType::*field)
Resets the changed state of the given field.
Definition: Component.h:359
ComponentHandle getComponentHandle() const
Definition: Component.h:177
constexpr Reflection::TypeId getTypeId() const
Get the Reflection::TypeId of the component.
Definition: Component.h:380
constexpr void setGeneration(uint16_t generation)
Sets the component generation.
Definition: Component.h:395
constexpr void setFlag(const uint32_t flag)
Set the given flags. Does not override the currently set flags.
Definition: Component.h:368
void setContainer(class Entity *container)
Set the container owning this component instance.
Definition: Component.h:154
bool hasFieldChanged(FieldType ClassType::*field) const
Gets if the given field has changed.
Definition: Component.h:290
void setFieldChanged(FieldType ClassType::*field)
Sets a flag indicating that the given field has changed.
Definition: Component.h:237
size_t hash(size_t hashValue=Cogs::hash()) const
Calculates a hash of this component's members.
Definition: Component.h:405
bool hasFieldChanged(const Reflection::FieldId fieldId) const
Gets if the field with the given id on this component instance has changed.
Definition: Component.h:272
void resetCarryChanged()
Reset the CarryChanged flag. Called at start of redraw. See ComponentFlags::CarryChanged.
Definition: Component.h:296
COGSFOUNDATION_API const Reflection::Type & getType() const
Get the full Reflection::Type of the component.
Definition: Component.cpp:27
void resetChanged()
Resets the changed state of the component, respecting any carry state set.
Definition: Component.h:309
Container for components, providing composition of dynamic entities.
Definition: Entity.h:18
Represents a discrete type definition, describing a native type class.
Definition: Type.h:89
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr bool operator==(const ComponentHandle &a, const ComponentHandle &b)
Overloaded equality operator.
Definition: Component.h:133
uint16_t TypeId
Built in type used to uniquely identify a single type instance.
Definition: Name.h:48
uint16_t FieldId
Type used to index fields.
Definition: Name.h:54
constexpr TypeId NoType
Definition of no type.
Definition: Name.h:51
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
uint32_t ComponentIndex
Type used to track component indexes in pools.
Definition: Component.h:16
ComponentIndex SizeType
Type used to track the size of pools.
Definition: Component.h:19
size_t memberOffset(FieldType ClassType::*ptr)
Find the offset of a pointer to member in a class or struct.
Contains component flags.
Definition: Component.h:26
EComponentFlags
Component flags describing the state of a component instance.
Definition: Component.h:31
@ Changed
The components data has changed.
Definition: Component.h:38
@ AllFieldChanged
Mark all fields changed. Sets FieldChange + all bits above + OverflowFieldChange.
Definition: Component.h:59
@ None
The component has not been initialized.
Definition: Component.h:33
@ DisableTracking
No change tracking should be performed on the component.
Definition: Component.h:41
@ FieldChange
Flags above reserved for field change storage. Field0=FieldChange, Field 1 = FieldChange<<1.
Definition: Component.h:56
@ Active
The component has been initialized and is currently allocated.
Definition: Component.h:35
@ OverflowFieldChange
Field change bit for fields outside range of individual change tracking bit. Field 24++.
Definition: Component.h:53
Handle to a Component instance.
Definition: Component.h:67
COGSFOUNDATION_API class Component * resolve() const
Resolve the handle, returning a pointer to the held Component instance.
Definition: Component.cpp:65
ComponentHandle(const ComponentHandle &other)=default
Defaulted copy constructor.
ComponentHandle & operator=(const ComponentHandle &rhs)=default
Defaulted assign operator.
ComponentHandle()=default
Defaulted constructor.
static ComponentHandle Empty()
Returns an empty, invalid handle. Will evaluate to false if tested against using operator bool().
Definition: Component.h:119
constexpr ComponentHandle(class ComponentPoolBase *pool, ComponentIndex index, Reflection::TypeId typeId, uint16_t generation)
Explicit full initialization.
Definition: Component.h:78
ComponentType * resolveComponent() const
Definition: Component.h:90
Represents an unique name.
Definition: Name.h:70