31#if defined(__GNUC__) || defined(_WIN32)
33inline const char* type_name() {
34 static const size_t len = ECS_FUNC_TYPE_LEN(
const char*, type_name, ECS_FUNC_NAME);
35 static char result[len + 1] = {};
36 static const size_t front_len = ECS_FUNC_NAME_FRONT(
const char*, type_name);
37 static const char* cppTypeName = ecs_cpp_get_type_name(result, ECS_FUNC_NAME, len, front_len);
41#error "implicit component registration not supported"
47inline const char* symbol_name() {
48 static const size_t len = ECS_FUNC_TYPE_LEN(
const char*, symbol_name, ECS_FUNC_NAME);
49 static char result[len + 1] = {};
50 static const char* cppSymbolName = ecs_cpp_get_symbol_name(result, type_name<T>(), len);
54template <>
inline const char* symbol_name<uint8_t>() {
57template <>
inline const char* symbol_name<uint16_t>() {
60template <>
inline const char* symbol_name<uint32_t>() {
63template <>
inline const char* symbol_name<uint64_t>() {
66template <>
inline const char* symbol_name<int8_t>() {
69template <>
inline const char* symbol_name<int16_t>() {
72template <>
inline const char* symbol_name<int32_t>() {
75template <>
inline const char* symbol_name<int64_t>() {
78template <>
inline const char* symbol_name<float>() {
81template <>
inline const char* symbol_name<double>() {
89template<
typename T, enable_if_t<
90 std::is_trivial<T>::value ==
true
96template<
typename T, enable_if_t<
97 std::is_trivial<T>::value ==
false
99void register_lifecycle_actions(
104 cl.
ctor = ctor<T>(cl.flags);
105 cl.dtor = dtor<T>(cl.flags);
107 cl.copy = copy<T>(cl.flags);
108 cl.copy_ctor = copy_ctor<T>(cl.flags);
109 cl.move = move<T>(cl.flags);
110 cl.move_ctor = move_ctor<T>(cl.flags);
112 cl.ctor_move_dtor = ctor_move_dtor<T>(cl.flags);
113 cl.move_dtor = move_dtor<T>(cl.flags);
117 if (cl.flags & (ECS_TYPE_HOOK_MOVE_ILLEGAL|ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL))
125 static_assert(is_pointer<T>::value ==
false,
126 "pointer types are not allowed for components");
130 bool allow_tag =
true)
132 s_index = flecs_component_ids_index_get();
133 s_allow_tag = allow_tag;
135 s_alignment =
alignof(T);
136 if (is_empty<T>::value && allow_tag) {
142 static void init_builtin(
145 bool allow_tag =
true)
148 flecs_component_ids_set(
world, s_index,
id);
152 static entity_t register_id(world_t *
world,
153 const char *name =
nullptr,
bool allow_tag =
true, flecs::id_t
id = 0,
154 bool is_component =
false,
bool implicit_name =
true,
const char *n =
nullptr,
155 flecs::entity_t
module = 0)
162 ecs_assert(s_index != 0, ECS_INTERNAL_ERROR, NULL);
165 flecs::entity_t c = flecs_component_ids_get(
world, s_index);
179 bool existing =
false;
180 c = ecs_cpp_component_find(
181 world,
id, n, symbol_name<T>(), size(), alignment(),
182 implicit_name, &existing);
184 const char *
symbol =
nullptr;
189 symbol = symbol_name<T>();
192 c = ecs_cpp_component_register(
world, c, c,
name, type_name<T>(),
193 symbol, size(), alignment(), is_component, &existing);
201 if (size() && !existing) {
202 register_lifecycle_actions<T>(
world, c);
206 flecs_component_ids_set(
world, s_index, c);
211 #if FLECS_CPP_ENUM_REFLECTION_SUPPORT
224 static entity_t id(world_t *world)
226#ifdef FLECS_CPP_NO_AUTO_REGISTRATION
227 ecs_assert(registered(world), ECS_INVALID_OPERATION,
228 "component '%s' must be registered before use",
231 flecs::entity_t c = flecs_component_ids_get(world, s_index);
234 "component '%s' was deleted, reregister before using",
237 flecs::entity_t c = flecs_component_ids_get_alive(
world, s_index);
239 c = register_id(
world);
246 static size_t size() {
247 ecs_assert(s_index != 0, ECS_INTERNAL_ERROR, NULL);
252 static size_t alignment() {
253 ecs_assert(s_index != 0, ECS_INTERNAL_ERROR, NULL);
258 static bool registered(flecs::world_t *world) {
259 ecs_assert(world !=
nullptr, ECS_INVALID_PARAMETER, NULL);
265 if (!flecs_component_ids_get(world, s_index)) {
274 static void reset() {
281 static int32_t s_index;
282 static size_t s_size;
283 static size_t s_alignment;
284 static bool s_allow_tag;
288template <
typename T> int32_t type_impl<T>::s_index;
289template <
typename T>
size_t type_impl<T>::s_size;
290template <
typename T>
size_t type_impl<T>::s_alignment;
291template <
typename T>
bool type_impl<T>::s_allow_tag(
true );
306 static id_t id(world_t *
world =
nullptr) {
321 using entity::entity;
327# include "mixins/metrics/untyped_component.inl"
348 flecs::world_t *
world,
349 const char *
name =
nullptr,
350 bool allow_tag =
true,
353 const char *n =
name;
354 bool implicit_name =
false;
356 n = _::type_name<T>();
363 implicit_name =
true;
372 if (
module && implicit_name) {
375 const char *
start = strchr(n,
'<'), *last_elem = NULL;
377 const char *ptr =
start;
378 while (ptr[0] && (ptr[0] !=
':') && (ptr > n)) {
387 name = last_elem + 1;
397 template <
typename Func>
400 flecs::type_hooks_t h = get_hooks();
402 "on_add hook is already set");
403 BindingCtx *ctx = get_binding_ctx(h);
404 h.
on_add = Delegate::run_add;
405 ctx->on_add = FLECS_NEW(Delegate)(FLECS_FWD(func));
406 ctx->free_on_add = _::free_obj<Delegate>;
412 template <
typename Func>
415 typename std::decay<Func>::type, T>;
416 flecs::type_hooks_t h = get_hooks();
418 "on_remove hook is already set");
419 BindingCtx *ctx = get_binding_ctx(h);
421 ctx->on_remove = FLECS_NEW(Delegate)(FLECS_FWD(func));
422 ctx->free_on_remove = _::free_obj<Delegate>;
428 template <
typename Func>
431 typename std::decay<Func>::type, T>;
432 flecs::type_hooks_t h = get_hooks();
434 "on_set hook is already set");
435 BindingCtx *ctx = get_binding_ctx(h);
436 h.
on_set = Delegate::run_set;
437 ctx->on_set = FLECS_NEW(Delegate)(FLECS_FWD(func));
438 ctx->free_on_set = _::free_obj<Delegate>;
444# include "mixins/meta/component.inl"
450 BindingCtx* get_binding_ctx(flecs::type_hooks_t& h){
451 BindingCtx *result =
static_cast<BindingCtx*
>(h.
binding_ctx);
453 result = FLECS_NEW(BindingCtx);
460 flecs::type_hooks_t get_hooks() {
ecs_entity_t ecs_set_with(ecs_world_t *world, ecs_id_t id)
Set current with id.
void ecs_add_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t id)
Add a (component) id to an entity.
#define ecs_assert(condition, error_code,...)
Assert.
void ecs_set_hooks_id(ecs_world_t *world, ecs_entity_t id, const ecs_type_hooks_t *hooks)
Register hooks for component.
const ecs_type_hooks_t * ecs_get_hooks_id(const ecs_world_t *world, ecs_entity_t id)
Get hooks for component.
ecs_id_t ecs_entity_t
An entity identifier.
struct ecs_world_t ecs_world_t
A world is the container for all ECS data and supporting features.
transcribe_cv_t< remove_reference_t< P >, typename raw_type_t< P >::second > pair_second_t
Get pair::second from pair while preserving cv qualifiers.
transcribe_cv_t< remove_reference_t< P >, typename raw_type_t< P >::first > pair_first_t
Get pair::first from pair while preserving cv qualifiers.
bool ecs_is_alive(const ecs_world_t *world, ecs_entity_t e)
Test whether an entity is alive.
ecs_entity_t ecs_get_scope(const ecs_world_t *world)
Get the current scope.
const char * ecs_get_symbol(const ecs_world_t *world, ecs_entity_t entity)
Get the symbol of an entity.
ecs_entity_t ecs_set_scope(ecs_world_t *world, ecs_entity_t scope)
Set the current scope.
ecs_iter_action_t on_remove
Callback that is invoked when an instance of the component is removed.
void * binding_ctx
Language binding context.
ecs_iter_action_t on_set
Callback that is invoked when an instance of the component is set.
ecs_iter_action_t on_add
Callback that is invoked when an instance of a component is added.
ecs_ctx_free_t binding_ctx_free
Callback to free binding_ctx.
component< T > & on_remove(Func &&func)
Register on_remove hook.
component(flecs::world_t *world, const char *name=nullptr, bool allow_tag=true, flecs::id_t id=0)
Register a component.
component< T > & on_add(Func &&func)
Register on_add hook.
component< T > & on_set(Func &&func)
Register on_set hook.
flecs::string_view name() const
Return the entity name.
flecs::string_view symbol() const
Return the entity symbol.
flecs::entity module(const char *name=nullptr) const
Define a module.