Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
component.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <concepts>
6#include <cstddef>
7#include <cstdint>
8#include <string_view>
9#include <type_traits>
10
11namespace helios::ecs {
12
13/// @brief Type index for components.
15
16/// @brief Type id for components.
18
19/// @brief Storage type for components.
20enum class ComponentStorageType : uint8_t {
21 kArchetype, ///< Component is stored in an archetype.
22 kSparseSet, ///< Component is stored in a sparse set.
23};
24
25/**
26 * @brief Concept to check if a type can be used as a component.
27 * @details A component must be destructible, move or copy constructible, be an
28 * object, and not polymorphic.
29 */
30template <typename T>
32 std::destructible<T> &&
33 (std::move_constructible<T> || std::copy_constructible<T>) &&
34 !std::is_polymorphic_v<std::remove_cvref_t<T>> &&
35 std::is_object_v<std::remove_cvref_t<T>>;
36
37/**
38 * @brief Concept to check if the type is considered a tag component.
39 * @details A tag component is a component that is empty and can be used for
40 * tagging entities.
41 */
42template <typename T>
44 ComponentTrait<T> && std::is_empty_v<std::remove_cvref_t<T>>;
45
46/**
47 * @brief Concept for components that provide a name.
48 * @details A component with name trait must satisfy `ComponentTrait` and
49 * provide:
50 * - `static constexpr std::string_view kName` variable
51 */
52template <typename T>
54 { std::remove_cvref_t<T>::kName } -> std::convertible_to<std::string_view>;
55};
56
57/**
58 * @brief Concept for components that provide a storage type.
59 * @details A component with name trait must satisfy `ComponentTrait` and
60 * provide:
61 * - `static constexpr ComponentStorageType kStorageType` variable
62 */
63template <typename T>
65 {
66 std::remove_cvref_t<T>::kStorageType
67 } -> std::convertible_to<ComponentStorageType>;
68};
69
70/**
71 * @brief Component name for debugging and serialization.
72 * @tparam T Component type
73 * @return Component name
74 */
75template <ComponentTrait T>
76[[nodiscard]] constexpr std::string_view ComponentNameOf() noexcept {
77 if constexpr (ComponentWithNameTrait<T>) {
78 return T::kName;
79 } else {
81 }
82}
83
84/**
85 * @brief Component name for debugging and serialization.
86 * @tparam T Component type
87 * @param instance Component instance
88 * @return Component name
89 */
90template <ComponentTrait T>
91[[nodiscard]] constexpr std::string_view ComponentNameOf(
92 const T& /*instance*/) noexcept {
94}
95
96/**
97 * @brief Component storage type.
98 * @details If component does not provide a storage type, it defaults to:
99 * - `ComponentStorageType::kSparseSet` for tag components
100 * - `ComponentStorageType::kArchetype` for non-tag components
101 * @tparam T Component type
102 * @return Component storage type
103 */
104template <ComponentTrait T>
105[[nodiscard]] consteval ComponentStorageType ComponentStorageTypeOf() noexcept {
106 if constexpr (ComponentWithStorageTypeTrait<T>) {
107 return T::kStorageType;
108 } else {
109 if constexpr (TagComponentTrait<T>) {
111 } else {
113 }
114 }
115}
116
117/**
118 * @brief Component storage type.
119 * @details If component does not provide a storage type, it defaults to
120 * `ComponentStorageType::kArchetype`.
121 * @tparam T Component type
122 * @param instance Component instance
123 * @return Component storage type
124 */
125template <ComponentTrait T>
127 const T& /*instance*/) noexcept {
129}
130
131/**
132 * @brief Concept for components that are stored in an archetype.
133 * @details An archetype component must satisfy `ComponentTrait`
134 * and have a storage type of `ComponentStorageType::kArchetype`.
135 */
136template <typename T>
140
141/**
142 * @brief Concept for components that are stored in a sparse set.
143 * @details A sparse set component must satisfy `ComponentTrait`
144 * and have a storage type of `ComponentStorageType::kSparseSet`.
145 */
146template <typename T>
150
151/**
152 * @brief Component traits for optimization decisions.
153 * @tparam T Component type
154 */
155template <ComponentTrait T>
157 static constexpr size_t kSize = sizeof(T);
158 static constexpr size_t kAlignment = alignof(T);
161 static constexpr bool kIsTag = TagComponentTrait<T>;
162};
163
164/// @brief Component type info for runtime operations.
166public:
167 constexpr ComponentTypeInfo(const ComponentTypeInfo&) noexcept = default;
168 constexpr ComponentTypeInfo(ComponentTypeInfo&&) noexcept = default;
169 constexpr ~ComponentTypeInfo() noexcept = default;
170
171 constexpr ComponentTypeInfo& operator=(const ComponentTypeInfo&) noexcept =
172 default;
173 constexpr ComponentTypeInfo& operator=(ComponentTypeInfo&&) noexcept =
174 default;
175
176 /**
177 * @brief Create a `ComponentTypeInfo` from a component type.
178 * @tparam T Component type
179 * @return `ComponentTypeInfo` for the given component type
180 */
181 template <ComponentTrait T>
182 [[nodiscard]] static constexpr ComponentTypeInfo From() noexcept {
183 constexpr ComponentTraits<T> traits;
184 return {ComponentTypeIndex::From<T>(), traits.kSize, traits.kAlignment,
185 traits.kStorageType, traits.kIsTag};
186 }
187
188 constexpr bool operator==(const ComponentTypeInfo& other) const noexcept {
189 return type_index_ == other.type_index_;
190 }
191 constexpr bool operator!=(const ComponentTypeInfo& other) const noexcept {
192 return !(*this == other);
193 }
194
195 constexpr bool operator<(const ComponentTypeInfo& other) const noexcept {
196 return type_index_ < other.type_index_;
197 }
198
199 /**
200 * @brief Get the component type index.
201 * @return Component type index
202 */
203 [[nodiscard]] constexpr ComponentTypeIndex TypeIndex() const noexcept {
204 return type_index_;
205 }
206
207 /**
208 * @brief Get the size of the component type.
209 * @return Size of the component type
210 */
211 [[nodiscard]] constexpr size_t Size() const noexcept { return size_; }
212
213 /**
214 * @brief Get the alignment of the component type.
215 * @return Alignment of the component type
216 */
217 [[nodiscard]] constexpr size_t Alignment() const noexcept {
218 return alignment_;
219 }
220
221 /**
222 * @brief Get the storage type of the component type.
223 * @return Storage type of the component type
224 */
225 [[nodiscard]] constexpr ComponentStorageType StorageType() const noexcept {
226 return storage_type_;
227 }
228
229 /**
230 * @brief Check if the component type is a tag (empty).
231 * @return True if the component type is a tag, false otherwise
232 */
233 [[nodiscard]] constexpr bool IsTag() const noexcept { return is_tag_; }
234
235private:
236 constexpr ComponentTypeInfo(ComponentTypeIndex type_index, size_t size,
237 size_t alignment,
238 ComponentStorageType storage_type,
239 bool is_tag) noexcept
240 : type_index_(type_index),
241 size_(size),
242 alignment_(alignment),
243 storage_type_(storage_type),
244 is_tag_(is_tag) {}
245
246 ComponentTypeIndex type_index_;
247 size_t size_ = 0;
248 size_t alignment_ = 0;
250 bool is_tag_ = false;
251};
252
253} // namespace helios::ecs
254
255namespace std {
256
257template <>
258struct hash<helios::ecs::ComponentTypeInfo> {
259 consteval size_t operator()(
260 const helios::ecs::ComponentTypeInfo& info) const noexcept {
261 return info.TypeIndex().Hash();
262 }
263};
264
265} // namespace std
Component type info for runtime operations.
constexpr size_t Alignment() const noexcept
Get the alignment of the component type.
constexpr bool operator!=(const ComponentTypeInfo &other) const noexcept
constexpr ComponentTypeInfo(const ComponentTypeInfo &) noexcept=default
constexpr ComponentTypeInfo(ComponentTypeInfo &&) noexcept=default
constexpr bool operator<(const ComponentTypeInfo &other) const noexcept
constexpr bool operator==(const ComponentTypeInfo &other) const noexcept
constexpr bool IsTag() const noexcept
Check if the component type is a tag (empty).
constexpr ComponentStorageType StorageType() const noexcept
Get the storage type of the component type.
constexpr size_t Size() const noexcept
Get the size of the component type.
static constexpr ComponentTypeInfo From() noexcept
Create a ComponentTypeInfo from a component type.
constexpr ComponentTypeIndex TypeIndex() const noexcept
Get the component type index.
static constexpr TypeIndex From() noexcept
Constructs a TypeIndex from a type T.
Concept for components that are stored in an archetype.
Concept to check if a type can be used as a component.
Definition component.hpp:31
Concept for components that provide a name.
Definition component.hpp:53
Concept for components that provide a storage type.
Definition component.hpp:64
Concept for components that are stored in a sparse set.
Concept to check if the type is considered a tag component.
Definition component.hpp:43
ComponentStorageType
Storage type for components.
Definition component.hpp:20
@ kArchetype
Component is stored in an archetype.
Definition component.hpp:21
@ kSparseSet
Component is stored in a sparse set.
Definition component.hpp:22
consteval ComponentStorageType ComponentStorageTypeOf() noexcept
Component storage type.
utils::TypeId ComponentTypeId
Type id for components.
Definition component.hpp:17
constexpr std::string_view ComponentNameOf() noexcept
Component name for debugging and serialization.
Definition component.hpp:76
utils::TypeIndex ComponentTypeIndex
Type index for components.
Definition component.hpp:14
constexpr std::string_view QualifiedTypeNameOf() noexcept
Retrieves the fully qualified type name of T.
STL namespace.
Component traits for optimization decisions.
static constexpr bool kIsTag
static constexpr size_t kSize
static constexpr size_t kAlignment
static constexpr ComponentStorageType kStorageType
consteval size_t operator()(const helios::ecs::ComponentTypeInfo &info) const noexcept