CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
Component.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "Forward.hpp"
11
12#include "EntityID.hpp"
13
16
20
24
25#include <bitset>
26#include <type_traits>
27
28namespace CeresEngine {
29
32 using ComponentID = unsigned int;
33
35 using ComponentMask = std::bitset<128>;
36
41
42 public:
44 virtual ~AbstractComponent() = default;
45
46 public:
50 };
51
69 private:
72
73 public:
76 static inline const ComponentID componentID = getComponentID();
77
80 static inline const ComponentMask mask = []() noexcept { // NOLINT(cert-err58-cpp)
82 m[componentID] = true;
83 return m;
84 }();
85
88
90 [[nodiscard]] const ComponentType& getComponentType() const noexcept final { return componentType; }
91
92 public: // Accessor
93 struct Accessor;
94 };
95
98 template<typename C> constexpr bool isComponent = std::is_base_of<AbstractComponent, C>::value;
99
102 template<typename... Cs> constexpr bool areComponents = (isComponent<Cs> && ...);
103
108 template<typename T, typename C> using ifComponent = typename std::enable_if<isComponent<C>, T>::type;
109
114 template<typename T, typename... Cs> using ifComponents = typename std::enable_if<areComponents<Cs...>, T>::type;
115
116 template<typename T>
118
121 template<CComponent C> inline constexpr void checkComponent() {
122 static_assert(isComponent<C>, "C must be a Component type!");
123 static_assert(std::is_final_v<C>, "Components must be final!");
124 }
125
175 template<typename TC> struct Component<TC>::Accessor {
176 public:
178
179 public:
181 explicit Accessor(const Entity& entity) : entity(entity) {}
182
183 protected:
184 using C = TC; // NOLINT
185
191 template<typename T> CE_FORCE_INLINE auto mutate(T C::*ptr);
192
200 template<typename MutatorFunc, typename T> requires(CInvocable<MutatorFunc, T&>) decltype(auto) mutate(MutatorFunc&& func, T C::*ptr);
201
203 template<typename T1, typename T2, typename... Ts>
205 Ts C::*... ptrs);
206
207 template<typename MutatorFunc, typename T1, typename T2, typename... Ts>
209
211 template<typename T> CE_FORCE_INLINE auto get(T C::*ptr);
212
214 template<typename T1, typename T2, typename... Ts>
216 Ts C::*... ptrs);
217
223 template<typename T> CE_FORCE_INLINE const T& read(const T C::*ptr) const;
224
226 template<typename T1, typename T2, typename... Ts>
227 CE_FORCE_INLINE Tuple<const T1&, const T2&, const Ts&...> read(const T1 C::*ptr1, const T2 C::*ptr2, const Ts C::*... ptrs) const;
228
230 template<typename T> CE_FORCE_INLINE const T& get(const T C::*ptr) const;
231
233 template<typename T1, typename T2, typename... Ts>
234 CE_FORCE_INLINE Tuple<const T1&, const T2&, const Ts&...> get(const T1 C::*ptr1, const T2 C::*ptr2, const Ts C::*... ptrs) const;
235 };
236
239 private:
242
245 static inline constexpr ComponentMask emptyComponentMask = 0;
246
247 public:
252 [[nodiscard]] const ComponentMask& get(const EntityIndex index) const noexcept {
253 if(mComponentMasks.size() < index + 1) {
254 return emptyComponentMask;
255 }
256 return mComponentMasks[index];
257 }
258
268 [[nodiscard]] bool has(const EntityIndex index, const ComponentMask& mask) const noexcept {
269 const ComponentMask& currentMask = get(index);
270 return (currentMask & mask) == mask;
271 }
272
278 const ComponentMask& set(const EntityIndex index, const ComponentMask& mask) noexcept {
279 if(mComponentMasks.size() < index + 1) {
280 if(mask == 0) {
281 // If the target mask is empty we don't need to resize.
282 return emptyComponentMask;
283 }
284
285 mComponentMasks.resize(index + 1);
286 }
287 mComponentMasks[index] = mask;
288 return mComponentMasks[index];
289 }
290
295 const ComponentMask& reset(const EntityIndex index) noexcept { return set(index, 0); }
296
305 const ComponentMask& add(const EntityIndex index, const ComponentMask& mask) noexcept {
306 if(mComponentMasks.size() < index + 1) {
307 mComponentMasks.resize(index + 1);
308 }
309 mComponentMasks[index] |= mask;
310 return mComponentMasks[index];
311 }
312
321 const ComponentMask& remove(const EntityIndex index, const ComponentMask& mask) noexcept {
322 if(mComponentMasks.size() < index + 1) {
323 return emptyComponentMask;
324 }
325 mComponentMasks[index] &= ~mask;
326 return mComponentMasks[index];
327 }
328
330 [[nodiscard]] std::size_t getSize() const noexcept { return mComponentMasks.size(); }
331 };
332
333 template<typename T> inline void buildComponentMask(ComponentMask& mask) { mask[T::componentID] = true; }
334
335 template<typename T, typename T1, typename... Ts> inline void buildComponentMask(ComponentMask& mask) {
337 buildComponentMask<T1, Ts...>(mask);
338 }
339
340 template<typename... Ts> inline ComponentMask buildComponentMask() {
341 ComponentMask mask = 0ul;
342 buildComponentMask<Ts...>(mask);
343 return mask;
344 }
345
346 template<CComponent... Cs> struct ComponentSet {
348 static_assert(areComponents<Cs...>, "All parameters in Cs must be components.");
349
353 template<CComponent C> static inline constexpr bool includes = (std::is_same_v<C, Cs> || ...);
354
357 static inline ComponentMask getComponentMask() noexcept { // NOLINT(cert-err58-cpp)
358 return (Cs::mask | ...);
359 }
360
361 // static inline const ComponentMask mask = getComponentMask();
362 //#else
363 // static inline const ComponentMask mask = (Cs::mask | ...);
364 //#endif
365
369 template<template<typename...> typename T> using Apply = T<Cs...>;
370 };
371
372 template<> struct ComponentSet<> {
376 template<CComponent C> static inline constexpr bool includes = false;
377
380 static inline ComponentMask getComponentMask() noexcept { // NOLINT(cert-err58-cpp)
381 return ComponentMask();
382 }
383 // static inline const ComponentMask mask = ComponentMask();
384
385 template<template<typename...> typename T> using Apply = T<>;
386 };
387
419
440
446
453
457 public:
461
463
464 protected:
467 ComponentMask mask;
468 mask[componentID] = true;
469 return mask;
470 }()) {}
471
472 public:
473 ComponentType(const ComponentType&) = delete;
477
478 protected: // ComponentID allocation
481
482 public: // Reflection
484 [[nodiscard]] virtual const Class* getClass() const noexcept = 0;
485
488
491
494
497
499 virtual void setAny(AbstractComponent& component, Box&& any) const noexcept = 0;
500
501 public: // Standard events
504
505 public:
509 // NOTE: This is safe as we only ever create a single instance for
510 // any given component type.
511 //
512 return &lhs == &rhs;
513 }
514
517 friend bool operator!=(const ComponentType& lhs, const ComponentType& rhs) noexcept { return !(lhs == rhs); }
518
519 public:
524 template<typename C> static const TComponentType<C>& get() noexcept;
525 };
526
530 private:
531 friend class ComponentType;
532
535 explicit TComponentType() : ComponentType(getComponentID()) {}
536
537 protected: // Component ID generation & retrieval
540 static const ComponentID id = nextComponentID++;
541 return id;
542 }
543
544 public: // Reflection
547
550
553
556
558 [[nodiscard]] Box getAny(AbstractComponent& component) const noexcept final { return std::ref(static_cast<C&>(component)); }
559
561 [[nodiscard]] Box getAny(const AbstractComponent& component) const noexcept final { return std::ref(static_cast<const C&>(component)); }
562
564 void setAny(AbstractComponent& component, const Box& value) const noexcept final {
565 if constexpr(std::is_copy_assignable_v<C>) {
566 static_cast<C&>(component) = value.template cref<C>();
567 }
568 // TODO: Throw if not assignable.
569 }
570
572 void setAny(AbstractComponent& component, Box&& value) const noexcept final {
573 if constexpr(std::is_copy_assignable_v<C>) {
574 static_cast<C&>(component) = std::move(value).template rref<C>();
575 }
576 // TODO: Throw if not assignable.
577 }
578
579 public: // Standard events
581 void emitComponentAdded(const Entity& entity) const final;
582
584 void emitComponentRemoved(const Entity& entity) const final;
585 };
586
587 template<typename C> inline const TComponentType<C>& ComponentType::get() noexcept {
588 static const TComponentType<C> instance;
589 return instance;
590 }
591
592 template<typename C> [[nodiscard]] ComponentID Component<C>::getComponentID() noexcept { return ComponentType::get<C>().componentID; }
593
594 template<typename C> const ComponentType& Component<C>::componentType = ComponentType::get<C>();
595
596#define CE_EXTERN_COMPONENT_BASE(T, EXTERN) \
597 EXTERN template struct ::CeresEngine::Component<T>; \
598 EXTERN template class ::CeresEngine::TComponentType<T>; \
599 EXTERN template class ::CeresEngine::ComponentStore<T>
600#define CE_EXTERN_COMPONENT(T) CE_EXTERN_COMPONENT_BASE(T, extern);
601#define CE_EXTERN_COMPONENT_IMPL(T) CE_EXTERN_COMPONENT_BASE(T, );
602} // namespace CeresEngine
603
604template<typename C> struct std::hash<CeresEngine::Component<C>> {
605 size_t operator()(const CeresEngine::Component<C>& component) const { return std::hash<C>{}(static_cast<const C&>(component)); }
606};
607
608template<> struct std::hash<CeresEngine::ComponentType> {
609 size_t operator()(const CeresEngine::ComponentType& type) const { return std::hash<const void*>{}(&type); }
610};
611
612template<typename C> struct std::hash<CeresEngine::TComponentType<C>> : std::hash<CeresEngine::ComponentType> {};
613
614#include "ComponentStore.hpp"
#define CE_REFLECTABLE_CLASS
Definition IReflectable.hpp:38
#define CE_FORCE_INLINE
Definition Macros.hpp:367
#define CE_SCRIPT_EXPORT(...)
The CE_SCRIPT_EXPORT macro marks a class or method as exportable and available in scripting environme...
Definition Macros.hpp:247
A value type that can hold any alongside it's type information.
Definition Box.hpp:40
Definition Class.hpp:46
Represents a reflected property from metadata defined by the class.
Definition Class.hpp:176
A object that manages a set of components masks.
Definition Component.hpp:238
static constexpr ComponentMask emptyComponentMask
A default empty component mask used when returning an empty mask by reference.
Definition Component.hpp:245
const ComponentMask & reset(const EntityIndex index) noexcept
Removes all bits in the component mask of the given index.
Definition Component.hpp:295
std::size_t getSize() const noexcept
Definition Component.hpp:330
bool has(const EntityIndex index, const ComponentMask &mask) const noexcept
Checks if the entity at the given index contains all components in the given mask.
Definition Component.hpp:268
Vector< ComponentMask > mComponentMasks
A vector that stores the component masks indexed by an integer index.
Definition Component.hpp:241
const ComponentMask & remove(const EntityIndex index, const ComponentMask &mask) noexcept
Removes a new set of components in the given mask from the given index.
Definition Component.hpp:321
const ComponentMask & get(const EntityIndex index) const noexcept
Gets the current component mask for the given index.
Definition Component.hpp:252
const ComponentMask & add(const EntityIndex index, const ComponentMask &mask) noexcept
Adds a new set of components in the given mask to the given index.
Definition Component.hpp:305
const ComponentMask & set(const EntityIndex index, const ComponentMask &mask) noexcept
Sets a mask for the given index.
Definition Component.hpp:278
A type that describes and provides type-erased operations on a component.
Definition Component.hpp:456
ComponentType & operator=(const ComponentType &)=delete
virtual const Class * getAccessorClass() const noexcept=0
Returns the component accessor meta class.
virtual void emitComponentRemoved(const Entity &entity) const =0
static const TComponentType< C > & get() noexcept
The type instance for a component of the C.
Definition Component.hpp:587
const ComponentMask componentMask
Definition Component.hpp:462
virtual void setAny(AbstractComponent &component, const Box &any) const noexcept=0
friend bool operator!=(const ComponentType &lhs, const ComponentType &rhs) noexcept
Compares two ComponentType instances for inequality.
Definition Component.hpp:517
ComponentType & operator=(ComponentType &&)=delete
ComponentType(const ComponentType &)=delete
ComponentType(const ComponentID componentID)
Definition Component.hpp:465
virtual Type getType() const noexcept=0
Returns the meta type of the component.
const ComponentID componentID
The component type ID.
Definition Component.hpp:460
static ComponentID nextComponentID
The next component ID to be statically allocated by the compiler.
Definition Component.hpp:480
virtual Type getAccessorType() const noexcept=0
Returns the component accessor meta type.
virtual const Class * getClass() const noexcept=0
Returns the meta class of the component.
ComponentType(ComponentType &&)=delete
virtual void emitComponentAdded(const Entity &entity) const =0
virtual Box getAny(AbstractComponent &component) const noexcept=0
The base entity class.
Definition Entity.hpp:41
An implementation of the ComponentType interface that implements type-erased operations for component...
Definition Component.hpp:529
void setAny(AbstractComponent &component, const Box &value) const noexcept final
Definition Component.hpp:564
void emitComponentAdded(const Entity &entity) const final
Box getAny(AbstractComponent &component) const noexcept final
Definition Component.hpp:558
static ComponentID getComponentID() noexcept
Definition Component.hpp:539
TComponentType()
Creates a new instance of a component type object for the given C component type.
Definition Component.hpp:535
Type getAccessorType() const noexcept final
Returns the component accessor meta type.
Definition Component.hpp:555
Type getType() const noexcept final
Returns the meta type of the component.
Definition Component.hpp:549
void setAny(AbstractComponent &component, Box &&value) const noexcept final
Definition Component.hpp:572
Box getAny(const AbstractComponent &component) const noexcept final
Definition Component.hpp:561
void emitComponentRemoved(const Entity &entity) const final
const Class * getClass() const noexcept final
Returns the meta class of the component.
Definition Component.hpp:546
const Class * getAccessorClass() const noexcept final
Returns the component accessor meta class.
Definition Component.hpp:552
Tuple is a fixed-size collection of heterogeneous values.
Definition Tuple.hpp:15
Represents a reflected C++ type. Can be used to get metadata from a C++ type.
Definition Type.hpp:32
const Class * getClass() const noexcept
Gets the Class instance associated with the type.
Definition Component.hpp:117
Definition Concepts.hpp:43
Definition Application.hpp:19
constexpr bool isComponent
A trait that checks if the type C is a component.
Definition Component.hpp:98
typename std::enable_if< areComponents< Cs... >, T >::type ifComponents
If the types Cs are all components (as defined by areComponents<Cs>), this type is aliased to T.
Definition Component.hpp:114
typename std::enable_if< isComponent< C >, T >::type ifComponent
If the type C is a component (as defined by isComponent<C>), this type is aliased to T.
Definition Component.hpp:108
ComponentMask buildComponentMask()
Definition Component.hpp:340
std::vector< T, ScopedAllocatorAdaptor< StdAllocator< T, RawAllocator > > > Vector
Vector is a sequence container that encapsulates dynamic size arrays.
Definition Vector.hpp:17
constexpr void checkComponent()
A trait that checks if the type C is a valid component type.
Definition Component.hpp:121
constexpr bool areComponents
A trait that checks if the types Cs are all components.
Definition Component.hpp:102
std::bitset< 128 > ComponentMask
A bitset that represents a components mask (i.e. a set of components)
Definition Component.hpp:35
sfl::small_vector< T, N, ScopedAllocatorAdaptor< StdAllocator< T, RawAllocator > > > SmallVector
SmallVector is a sequence container similar to Vector.
Definition SmallVector.hpp:31
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
unsigned int ComponentID
A numeric type that represents a component.
Definition Component.hpp:32
UInt32 EntityIndex
Definition EntityID.hpp:22
A abstract class that provides a trait that allows checking for component implementations.
Definition Component.hpp:39
virtual ~AbstractComponent()=default
Defaulted virtual destructor.
virtual const ComponentType & getComponentType() const noexcept=0
Gets the component type.
An abstract type that represents a generic component listener.
Definition Component.hpp:390
virtual ~AbstractComponentListener()=default
Destroys the AbstractComponentListener instance.
virtual ComponentMask mask() const noexcept=0
The component criteria a entity must match for consideration of a callback.
virtual void componentsAdded(const Entity &entity) noexcept=0
A notification dispatched by the SystemManager to a system.
virtual void componentsRemoved(const Entity &entity) noexcept=0
A notification dispatched by the SystemManager to a system.
virtual void entityDirtied(const Entity &entity, const EntityChangeSet &changeSet) noexcept
A notification dispatched by the SystemManager to a system.
Definition Component.hpp:417
An accessor class that implements high-level access to an entity that has the given component.
Definition Component.hpp:175
Tuple< const T1 &, const T2 &, const Ts &... > get(const T1 C::*ptr1, const T2 C::*ptr2, const Ts C::*... ptrs) const
Accesses an element from an existing Component.
const Entity & entity
Definition Component.hpp:177
TC C
Definition Component.hpp:184
auto get(T C::*ptr)
Accesses an element from an existing Component.
Tuple< ComponentFieldMutator< T1, C >, ComponentFieldMutator< T2, C >, ComponentFieldMutator< Ts, C >... > get(T1 C::*ptr1, T2 C::*ptr2, Ts C::*... ptrs)
Accesses an element from an existing Component.
const T & get(const T C::*ptr) const
Accesses an element from an existing Component.
Accessor(const Entity &entity)
Definition Component.hpp:181
Tuple< ComponentFieldMutator< T1, C >, ComponentFieldMutator< T2, C >, ComponentFieldMutator< Ts, C >... > mutate(MutatorFunc &&func, T1 C::*ptr1, T2 C::*ptr2, Ts C::*... ptr)
auto mutate(T C::*ptr)
Accesses an element from an existing Component.
const T & read(const T C::*ptr) const
Accesses an element from an existing Component.
decltype(auto) mutate(MutatorFunc &&func, T C::*ptr)
Accesses an element from an existing Component.
Tuple< const T1 &, const T2 &, const Ts &... > read(const T1 C::*ptr1, const T2 C::*ptr2, const Ts C::*... ptrs) const
TODO Write docs.
Tuple< ComponentFieldMutator< T1, C >, ComponentFieldMutator< T2, C >, ComponentFieldMutator< Ts, C >... > mutate(T1 C::*ptr1, T2 C::*ptr2, Ts C::*... ptrs)
TODO Write docs.
A structure that encodes a change to a single component field.
Definition Component.hpp:442
const ClassProperty * property
The component field whose value has been changed.
Definition Component.hpp:444
A structure that encodes a set of changes done to a component.
Definition Component.hpp:448
SmallVector< ComponentChange, 10 > changes
A set of changes done to a component.
Definition Component.hpp:451
Definition Forward.hpp:28
Components serve as the base for data storage for an entity.
Definition Component.hpp:68
const ComponentType & getComponentType() const noexcept final
Gets the component type.
Definition Component.hpp:90
static ComponentID getComponentID() noexcept
Definition Component.hpp:592
static const ComponentType & componentType
Gets the component type.
Definition Component.hpp:87
The ComponentListener is a EntityManager listener type that gets notified whenever an entity matching...
Definition Component.hpp:436
ComponentMask mask() const noexcept final
The component criteria a entity must match for consideration of a callback.
Definition Component.hpp:438
static ComponentMask getComponentMask() noexcept
A trait that contains the minimum component mask for that includes all components in the set.
Definition Component.hpp:380
T<> Apply
Definition Component.hpp:385
Definition Component.hpp:346
static ComponentMask getComponentMask() noexcept
A trait that contains the minimum component mask for that includes all components in the set.
Definition Component.hpp:357
static constexpr bool includes
Checks if all Cs are valid component types.
Definition Component.hpp:353
T< Cs... > Apply
Applies all components Cs into the template type T as T<Cs...>.
Definition Component.hpp:369
Definition Entity.hpp:452