Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
component.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5#include <type_traits>
6
7#include "gaia/core/hashing_policy.h"
8#include "gaia/core/utility.h"
9#include "gaia/ecs/id.h"
10#include "gaia/mem/data_layout_policy.h"
11#include "gaia/meta/type_info.h"
12
13namespace gaia {
14 namespace ecs {
15 //----------------------------------------------------------------------
16 // Component-related types
17 //----------------------------------------------------------------------
18
19 using ComponentVersion = uint32_t;
20 using ChunkDataVersionOffset = uint8_t;
21 using CompOffsetMappingIndex = uint8_t;
22 using ChunkDataOffset = uint16_t;
23 using ComponentLookupHash = core::direct_hash_key<uint64_t>;
24 using EntitySpan = std::span<const Entity>;
25 using EntitySpanMut = std::span<Entity>;
26 using ComponentSpan = std::span<const Component>;
27 using ChunkDataOffsetSpan = std::span<const ChunkDataOffset>;
28 using SortComponentCond = core::is_smaller<Entity>;
29
33 GAIA_NODISCARD constexpr bool component_has_inline_data(Component component) noexcept {
34 return component.size() != 0U && (component.storage_type() != DataStorageType::Sparse || component.soa() != 0U);
35 }
36
40 GAIA_NODISCARD constexpr bool component_has_out_of_line_data(Component component) noexcept {
41 return component.size() != 0U && component.storage_type() == DataStorageType::Sparse && component.soa() == 0U;
42 }
43
44 //----------------------------------------------------------------------
45 // Component verification
46 //----------------------------------------------------------------------
47
48 namespace detail {
49 template <typename T>
50 struct is_component_size_valid: std::bool_constant<sizeof(T) < Component::MaxComponentSizeInBytes> {};
51
52 template <typename T>
53 struct is_component_type_valid:
54 std::bool_constant<
55 // SoA types need to be trivial. No restrictions otherwise.
56 (!mem::is_soa_layout_v<T> || std::is_trivially_copyable_v<T>)> {};
57
58 } // namespace detail
59
60 //----------------------------------------------------------------------
61 // Component verification
62 //----------------------------------------------------------------------
63
64 template <typename T>
65 constexpr void verify_comp() {
66 using U = typename actual_type_t<T>::TypeOriginal;
67
68 // Make sure we only use this for "raw" types
69 static_assert(
70 core::is_raw_v<U>,
71 "Components have to be \"raw\" types - no arrays, no const, reference, pointer or volatile");
72 static_assert(detail::is_component_type_valid<U>::value, "SoA components must be trivially copyable");
73 }
74
75 //----------------------------------------------------------------------
76 // Component lookup hash
77 //----------------------------------------------------------------------
78
79 template <typename Container>
80 GAIA_NODISCARD constexpr ComponentLookupHash calc_lookup_hash(Container arr) noexcept {
81 constexpr auto arrSize = arr.size();
82 if constexpr (arrSize == 0) {
83 return {0};
84 } else {
85 ComponentLookupHash::Type hash = arr[0];
86 core::each<arrSize - 1>([&hash, &arr](auto i) {
87 hash = core::hash_combine(hash, arr[i + 1]);
88 });
89 return {hash};
90 }
91 }
92
93 template <typename = void, typename...>
94 constexpr ComponentLookupHash calc_lookup_hash() noexcept;
95
96 template <typename T, typename... Rest>
97 GAIA_NODISCARD constexpr ComponentLookupHash calc_lookup_hash() noexcept {
98 if constexpr (sizeof...(Rest) == 0)
99 return {meta::type_info::hash<T>()};
100 else
101 return {core::hash_combine(meta::type_info::hash<T>(), meta::type_info::hash<Rest>()...)};
102 }
103
104 template <>
105 GAIA_NODISCARD constexpr ComponentLookupHash calc_lookup_hash() noexcept {
106 return {0};
107 }
108
112 GAIA_NODISCARD inline ComponentLookupHash calc_lookup_hash(EntitySpan comps) noexcept {
113 const auto compsSize = comps.size();
114 if (compsSize == 0)
115 return {0};
116
117 auto hash = core::calculate_hash64(comps[0].value());
118 GAIA_FOR2(1, compsSize) {
119 hash = core::hash_combine(hash, core::calculate_hash64(comps[i].value()));
120 }
121 return {hash};
122 }
123
129 template <uint32_t MAX_COMPONENTS>
130 GAIA_NODISCARD inline uint32_t comp_idx(const Entity* pComps, Entity entity) {
131 // We let the compiler know the upper iteration bound at compile-time.
132 // This way it can optimize better (e.g. loop unrolling, vectorization).
133 GAIA_FOR(MAX_COMPONENTS) {
134 if (pComps[i] == entity)
135 return i;
136 }
137
138 GAIA_ASSERT(false);
139 return BadIndex;
140 }
141
146 GAIA_NODISCARD inline uint32_t comp_idx(std::span<const Entity> comps, Entity entity) {
147 // We let the compiler know the upper iteration bound at compile-time.
148 // This way it can optimize better (e.g. loop unrolling, vectorization).
149 const auto cnt = (uint32_t)comps.size();
150 GAIA_FOR(cnt) {
151 if (comps[i] == entity)
152 return i;
153 }
154
155 GAIA_ASSERT(false);
156 return BadIndex;
157 }
158 } // namespace ecs
159} // namespace gaia
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9