Flecs v4.1
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
component_id.hpp
1#pragma once
2
3namespace flecs {
4namespace _ {
5
6template <typename T = void, bool Sparse = false, typename Owner = void, typename Construct = T>
8 using type = T;
9 using construct_type = Construct;
10 static constexpr bool sparse = Sparse;
13
14 flecs::entity_t owner(world_t *world) const {
15 if constexpr (std::is_void_v<Owner>) {
16 (void)world;
17 return entity;
18 } else {
20 }
21 }
22};
23
24template <typename T>
25flecs::entity_t entity_id(world_t *world, T value) {
26 if constexpr (is_enum_v<T>) {
27 auto entity = flecs::enum_type<T>(world).entity(value);
28 ecs_assert(entity, ECS_INVALID_PARAMETER, "enum constant was not found");
29 return entity;
30 } else {
31 (void)world;
32 return value;
33 }
34}
35
36template <typename T>
37auto resolve_id(world_t *world, arg_list<T>) {
38 using A = actual_type_t<T>;
39 auto id = _::type<T>::id(world);
40 if constexpr (is_pair_v<T>) {
41 return component_id<A, false, pair_first_t<T>>{id, 0};
42 } else {
43 return component_id<A, true>{id, id};
44 }
45}
46
47template <typename First, typename Second>
48auto resolve_id(world_t *world, arg_list<First, Second>) {
50 return component_id<actual_type_t<T>, false, First, First>{
51 _::type<T>::id(world), 0};
52}
53
54template <typename First, typename Second>
55auto resolve_id(world_t *world, arg_list<First>, Second second) {
56 auto first = _::type<First>::id(world);
57 return component_id<First>{ecs_pair(first, entity_id(world, second)), first};
58}
59
60template <typename T>
61auto resolve_id(world_t *world, arg_list<>, T value) {
62 if constexpr (is_enum_v<T>) {
63 return resolve_id(world, arg_list<T>{}, value);
64 } else {
65 (void)world;
66 return component_id<>{value, value};
67 }
68}
69
70inline auto resolve_id(world_t*, arg_list<>, flecs::entity_t first, flecs::entity_t second) {
71 return component_id<>{ecs_pair(first, second), first};
72}
73
74template <typename... T, typename... Args>
75auto make_id(world_t *world, Args... args) {
76 return resolve_id(world, arg_list<T...>{}, args...);
77}
78
79template <typename T = void, typename Second = void>
80struct value_type : actual_type<conditional_t<std::is_void_v<Second>, T, flecs::pair<T, Second>>> {};
81
82template <typename... T>
83using value_type_t = typename value_type<T...>::type;
84
85template <typename... T, typename A>
86auto value_id(world_t *world, const A&) {
87 if constexpr (sizeof...(T)) {
88 return make_id<T...>(world);
89 } else {
90 return make_id<A>(world);
91 }
92}
93
94template <typename Second>
95auto second_id(world_t *world, flecs::entity_t first) {
96 auto second = _::type<Second>::id(world);
97 auto id = ecs_pair(first, second);
98 ecs_assert(ecs_get_type_info(world, id) &&
99 ecs_get_type_info(world, id)->component == second, ECS_INVALID_PARAMETER,
100 "type of pair is not Second");
101 return component_id<Second>{id, first};
102}
103
104template <typename First, typename Second>
105auto second_id(world_t *world) {
106 static_assert(is_empty_v<First>, "first element of pair must be a tag");
107 return make_id<First, Second>(world);
108}
109
110template <typename Id>
111void add_component(world_t *world, flecs::entity_t entity, Id id) {
112 flecs_static_assert(std::is_void_v<typename Id::construct_type> ||
113 is_flecs_constructible<typename Id::construct_type>::value,
114 "cannot default construct component: use emplace<T>()");
115 ecs_add_id(world, entity, id.id);
116}
117
118template <typename Id>
119bool has_component(world_t *world, flecs::entity_t entity, Id id) {
120 if (ecs_has_id(world, entity, id.id)) {
121 return true;
122 }
123 if constexpr (Id::sparse && is_enum_v<typename Id::type>) {
124 return ecs_has_pair(world, entity, id.id, flecs::Wildcard);
125 }
126 return false;
127}
128
129template <bool Mutable, bool Required, bool Ensure = false, typename Id>
130decltype(auto) get_component(world_t *world, flecs::entity_t entity, Id id) {
131 using T = typename Id::type;
132 using A = conditional_t<Mutable, T, const T>;
133 auto get = [&]() {
134 if constexpr (Ensure) {
135 if constexpr (std::is_void_v<T>) {
136 auto ti = ecs_get_type_info(world, id.id);
137 ecs_assert(ti && ti->size, ECS_INVALID_PARAMETER, "component has no data");
138 return ecs_ensure_id(world, entity, id.id, static_cast<size_t>(ti->size));
139 } else {
140 return ecs_ensure_id(world, entity, id.id, sizeof(T));
141 }
142 } else if constexpr (Id::sparse && !std::is_void_v<T> &&
143 is_get_sparse_component<T>::value)
144 {
145 return ecs_get_sparse_id(world, entity, id.id, sizeof(T));
146 } else if constexpr (Mutable) {
147 return ecs_get_mut_id(world, entity, id.id);
148 } else {
149 return ecs_get_id(world, entity, id.id);
150 }
151 };
152 if constexpr (!std::is_void_v<T>) {
153 ecs_assert(_::type<T>::size() != 0, ECS_INVALID_PARAMETER,
154 "operation invalid for empty type");
155 }
156 A *ptr = static_cast<A*>(get());
157 if constexpr (Required) {
158 ecs_assert(ptr != nullptr, ECS_INVALID_OPERATION,
159 "entity does not have component (use try_get or try_get_mut)");
160 }
161 if constexpr (Required && !std::is_void_v<T>) {
162 return *ptr;
163 } else {
164 return ptr;
165 }
166}
167
168}
169}
void ecs_add_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Add a (component) ID to an entity.
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:473
#define ECS_INVALID_OPERATION
Invalid operation error code.
Definition log.h:669
#define ECS_INVALID_PARAMETER
Invalid parameter error code.
Definition log.h:671
const ecs_type_info_t * ecs_get_type_info(const ecs_world_t *world, ecs_id_t component)
Get the type info for a component.
ecs_id_t id_t
ID type.
Definition c_types.hpp:20
ecs_entity_t entity_t
Entity type.
Definition c_types.hpp:21
ecs_world_t world_t
World type.
Definition c_types.hpp:18
bool ecs_has_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Test if an entity has a component.
#define ecs_has_pair(world, entity, first, second)
Test if an entity has a pair.
Definition flecs_c.h:527
const void * ecs_get_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Get an immutable pointer to a component.
void * ecs_get_mut_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Get a mutable pointer to a component.
void * ecs_ensure_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component, size_t size)
Ensure an entity has a component and return a pointer.
void * ecs_get_sparse_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component, size_t size)
Get a pointer to a sparse component.
Get the actual type from a regular type or pair.
Definition pair.hpp:120
Entity.
Definition entity.hpp:30
entity()
Default constructor.
Definition entity.hpp:32
Class that wraps around a flecs::id_t.
Definition decl.hpp:27
Type that represents a pair.
Definition pair.hpp:36
Trait that marks a component as Sparse at compile time.
Definition utils.hpp:187
The world.
Definition world.hpp:129