Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
query_adapter_typed.inl
1#pragma once
2
3namespace gaia {
4 namespace ecs {
6 void world_notify_on_set_entity(World& world, Entity term, Entity entity);
7
8 template <typename T>
9 void* world_typed_sparse_store_ptr(World& world, Entity component);
10 template <typename T>
11 const T& world_typed_sparse_store_get(const void* pStore, Entity entity);
12 template <typename T>
13 T& world_typed_sparse_store_mut(void* pStore, Entity entity);
14 template <typename T>
15 bool world_typed_sparse_store_has(const void* pStore, Entity entity);
16
17 template <typename T, bool IsEntity = std::is_same_v<typename actual_type_t<T>::Type, Entity>>
18 struct typed_query_arg_uses_sparse_storage: std::false_type {};
19
20 template <typename T>
21 struct typed_query_arg_uses_sparse_storage<T, false>:
22 std::bool_constant<auto_storage_policy_v<typename actual_type_t<T>::Type> == DataStorageType::Sparse> {};
23
24 template <typename... T>
25 inline constexpr bool typed_query_args_use_sparse_storage_v =
26 (typed_query_arg_uses_sparse_storage<T>::value || ...);
27
28 template <typename T>
29 struct typed_query_arg_list_uses_sparse_storage;
30
31 template <typename... T>
32 struct typed_query_arg_list_uses_sparse_storage<core::func_type_list<T...>>:
33 std::bool_constant<typed_query_args_use_sparse_storage_v<T...>> {};
34
35 template <typename T>
36 inline constexpr bool typed_query_arg_list_uses_sparse_storage_v =
37 typed_query_arg_list_uses_sparse_storage<T>::value;
38
39 struct TypedQueryExecState {
40 uint32_t argCount = 0;
41 Entity argIds[MAX_ITEMS_IN_QUERY]{};
42 bool writeFlags[MAX_ITEMS_IN_QUERY]{};
43 void* sparseStores[MAX_ITEMS_IN_QUERY]{};
44 uint32_t firstWriteArg = MAX_ITEMS_IN_QUERY;
45 bool hasWriteArgs = false;
46 bool needsInheritedArgIds = false;
47 bool canUseDirectChunkEval = false;
48 bool canUseSparseChunkEval = false;
49 bool hasInheritedTerms = false;
50 };
51
52 struct TypedQueryArgMeta {
53 Entity termId = EntityBad;
54 bool isWrite = false;
55 bool isEntity = false;
56 bool isPair = false;
57 bool usesSparseStorage = false;
58 };
59
60 template <typename T>
61 GAIA_NODISCARD inline TypedQueryArgMeta typed_query_arg_meta(World& world) {
62 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
63 const bool isWrite =
64 std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>> && !std::is_same_v<Arg, Entity>;
65 if constexpr (std::is_same_v<Arg, Entity>)
66 return TypedQueryArgMeta{EntityBad, isWrite, true, false, false};
67 else {
68 using FT = typename component_type_t<Arg>::TypeFull;
69 if constexpr (is_pair<FT>::value)
70 return TypedQueryArgMeta{EntityBad, isWrite, false, true, false};
71 else {
72 const auto termId = world_query_arg_id<Arg>(world);
73 constexpr bool UsesSparseStorage =
74 auto_storage_policy_v<typename actual_type_t<Arg>::Type> == DataStorageType::Sparse;
75 return TypedQueryArgMeta{termId, isWrite, false, false, UsesSparseStorage};
76 }
77 }
78 }
79
80 template <typename... T>
81 inline uint32_t
82 init_typed_query_arg_metas(TypedQueryArgMeta* pMetas, World& world, [[maybe_unused]] core::func_type_list<T...>) {
83 if constexpr (sizeof...(T) > 0) {
84 const TypedQueryArgMeta descs[] = {typed_query_arg_meta<T>(world)...};
85 GAIA_FOR(sizeof...(T)) {
86 pMetas[i] = descs[i];
87 }
88 }
89 return (uint32_t)sizeof...(T);
90 }
91
92 template <typename... T, size_t... I>
93 inline void bind_typed_sparse_stores(
94 TypedQueryExecState& state, World& world, core::func_type_list<T...>, std::index_sequence<I...>) {
95 (([&]() {
96 using U = typename actual_type_t<T>::Type;
97 if constexpr (!std::is_same_v<U, Entity> && auto_storage_policy_v<U> == DataStorageType::Sparse)
98 state.sparseStores[I] = world_typed_sparse_store_ptr<U>(world, state.argIds[I]);
99 }()),
100 ...);
101 }
102
103 template <typename... T>
104 inline void bind_typed_sparse_stores(TypedQueryExecState& state, World& world, core::func_type_list<T...> types) {
105 bind_typed_sparse_stores(state, world, types, std::index_sequence_for<T...>{});
106 }
107
108#if GAIA_ASSERT_ENABLED
109 template <typename... T>
110 GAIA_NODISCARD inline bool
111 typed_query_args_match_query(const QueryInfo& queryInfo, [[maybe_unused]] core::func_type_list<T...>) {
112 if constexpr (sizeof...(T) > 0)
113 return queryInfo.template has_all<T...>();
114 else
115 return true;
116 }
117#endif
118
119 template <typename... T, typename Func, size_t... I>
120 inline void invoke_typed_query_args_by_id(
121 World& world, Entity entity, const Entity* pArgIds, Func& func, std::index_sequence<I...>) {
122 func(([&]() -> decltype(auto) {
123 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
124 if constexpr (std::is_same_v<Arg, Entity>)
125 return entity;
126 else if constexpr (std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>)
127 return world_query_entity_arg_by_id_raw<T>(world, entity, pArgIds[I]);
128 else
129 return world_query_entity_arg_by_id<T>(world, entity, pArgIds[I]);
130 }())...);
131 }
132
133 template <typename Func, typename... T>
134 inline void invoke_typed_query_args_by_id_erased(World& world, Entity entity, const Entity* pArgIds, void* pFunc) {
135 auto& func = *static_cast<Func*>(pFunc);
136 invoke_typed_query_args_by_id<T...>(world, entity, pArgIds, func, std::index_sequence_for<T...>{});
137 }
138
139 template <typename Func, typename... T>
140 GAIA_NODISCARD inline auto typed_invoke_inherited_ptr(core::func_type_list<T...>) {
141 return &invoke_typed_query_args_by_id_erased<Func, T...>;
142 }
143
144 inline void finish_typed_query_args_by_id(World& world, Entity entity, const TypedQueryExecState& state) {
145 if (state.firstWriteArg >= state.argCount)
146 return;
147
148 Entity seenTerms[ChunkHeader::MAX_COMPONENTS]{};
149 uint32_t seenCnt = 0;
150 const auto finish_term = [&](Entity term, bool sparseStoreBound) {
151 GAIA_FOR(seenCnt) {
152 if (seenTerms[i] == term)
153 return;
154 }
155
156 seenTerms[seenCnt++] = term;
157 if (sparseStoreBound)
158 world_notify_on_set_entity(world, term, entity);
159 else
160 world_finish_write(world, term, entity);
161 };
162
163 for (uint32_t i = state.firstWriteArg; i < state.argCount; ++i) {
164 if (state.writeFlags[i] && state.argIds[i] != EntityBad)
165 finish_term(state.argIds[i], state.sparseStores[i] != nullptr);
166 }
167 }
169 } // namespace ecs
170} // namespace gaia
static constexpr bool value
True when the type derives from the pair base.
Definition id.h:287