28#if defined(__GNUC__) || defined(_WIN32)
30inline const char* type_name() {
31 static const size_t len = ECS_FUNC_TYPE_LEN(
const char*, type_name, ECS_FUNC_NAME);
32 static char result[len + 1] = {};
33 static const size_t front_len = ECS_FUNC_NAME_FRONT(
const char*, type_name);
34 static const char* cppTypeName = ecs_cpp_get_type_name(result, ECS_FUNC_NAME, len, front_len);
38#error "implicit component registration not supported"
44inline const char* symbol_name() {
45 static const size_t len = ECS_FUNC_TYPE_LEN(
const char*, symbol_name, ECS_FUNC_NAME);
46 static char result[len + 1] = {};
47 static const char* cppSymbolName = ecs_cpp_get_symbol_name(result, type_name<T>(), len);
51template <>
inline const char* symbol_name<uint8_t>() {
54template <>
inline const char* symbol_name<uint16_t>() {
57template <>
inline const char* symbol_name<uint32_t>() {
60template <>
inline const char* symbol_name<uint64_t>() {
63template <>
inline const char* symbol_name<int8_t>() {
66template <>
inline const char* symbol_name<int16_t>() {
69template <>
inline const char* symbol_name<int32_t>() {
72template <>
inline const char* symbol_name<int64_t>() {
75template <>
inline const char* symbol_name<float>() {
78template <>
inline const char* symbol_name<double>() {
86template<
typename T, enable_if_t<
87 std::is_trivial<T>::value ==
true
93template<
typename T, enable_if_t<
94 std::is_trivial<T>::value ==
false
96void register_lifecycle_actions(
112 cl.
flags &= ECS_TYPE_HOOKS_ILLEGAL;
115 if (cl.
flags & (ECS_TYPE_HOOK_MOVE_ILLEGAL|ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL))
123 static_assert(is_pointer<T>::value ==
false,
124 "pointer types are not allowed for components");
128 bool allow_tag =
true)
130 s_index = flecs_component_ids_index_get();
131 s_allow_tag = allow_tag;
133 s_alignment =
alignof(T);
134 if (is_empty<T>::value && allow_tag) {
140 static void init_builtin(
141 flecs::world_t *world,
143 bool allow_tag =
true)
146 flecs_component_ids_set(
world, s_index,
id);
150 static entity_t register_id(
152 const char *name =
nullptr,
153 bool allow_tag =
true,
154 bool is_component =
true,
155 bool explicit_registration =
false,
163 ecs_assert(s_index != 0, ECS_INTERNAL_ERROR, NULL);
166 bool registered =
false, existing =
false;
168 flecs::entity_t c = ecs_cpp_component_register(
169 world,
id, s_index,
name, type_name<T>(),
170 symbol_name<T>(), size(), alignment(),
171 is_component, explicit_registration, ®istered, &existing);
179 if (size() && !existing) {
180 register_lifecycle_actions<T>(
world, c);
186 #if FLECS_CPP_ENUM_REFLECTION_SUPPORT
187 _::init_enum<T>(
world, c);
197 static entity_t
id(world_t *
world)
199#ifdef FLECS_CPP_NO_AUTO_REGISTRATION
201 "component '%s' must be registered before use",
204 flecs::entity_t c = flecs_component_ids_get(
world, s_index);
207 "component '%s' was deleted, reregister before using",
210 flecs::entity_t c = flecs_component_ids_get_alive(
world, s_index);
212 c = register_id(
world);
219 static size_t size() {
220 ecs_assert(s_index != 0, ECS_INTERNAL_ERROR, NULL);
225 static size_t alignment() {
226 ecs_assert(s_index != 0, ECS_INTERNAL_ERROR, NULL);
231 static bool registered(flecs::world_t *world) {
232 ecs_assert(world !=
nullptr, ECS_INVALID_PARAMETER, NULL);
238 if (!flecs_component_ids_get(
world, s_index)) {
247 static void reset() {
254 static int32_t s_index;
255 static size_t s_size;
256 static size_t s_alignment;
257 static bool s_allow_tag;
261template <
typename T> int32_t type_impl<T>::s_index;
262template <
typename T>
size_t type_impl<T>::s_size;
263template <
typename T>
size_t type_impl<T>::s_alignment;
264template <
typename T>
bool type_impl<T>::s_allow_tag(
true );
279 static id_t id(world_t *
world =
nullptr) {
293struct untyped_component : entity {
294 using entity::entity;
296 untyped_component() :
entity() { }
297 explicit untyped_component(flecs::world_t *
world, flecs::entity_t
id) :
entity(
world,
id) { }
298 explicit untyped_component(flecs::entity_t
id) :
entity(
id) { }
300 explicit untyped_component(flecs::world_t *
world,
const char *
name)
312 explicit untyped_component(world_t *
world,
const char *
name,
const char *sep,
const char *root_sep)
326flecs::type_hooks_t get_hooks()
const {
335void set_hooks(flecs::type_hooks_t &h) {
336 h.
flags &= ECS_TYPE_HOOKS_ILLEGAL;
342untyped_component& on_compare(
345 ecs_assert(compare_callback, ECS_INVALID_PARAMETER, NULL);
346 flecs::type_hooks_t h = get_hooks();
347 h.
cmp = compare_callback;
348 h.
flags &= ~ECS_TYPE_HOOK_CMP_ILLEGAL;
349 if(h.
flags & ECS_TYPE_HOOK_EQUALS_ILLEGAL) {
350 h.
flags &= ~ECS_TYPE_HOOK_EQUALS_ILLEGAL;
357untyped_component& on_equals(
360 ecs_assert(equals_callback, ECS_INVALID_PARAMETER, NULL);
361 flecs::type_hooks_t h = get_hooks();
362 h.
equals = equals_callback;
363 h.
flags &= ~ECS_TYPE_HOOK_EQUALS_ILLEGAL;
372# include "mixins/metrics/untyped_component.inl"
393 flecs::world_t *
world,
394 const char *
name =
nullptr,
395 bool allow_tag =
true,
403 template <
typename Func>
406 flecs::type_hooks_t h = get_hooks();
408 "on_add hook is already set");
409 BindingCtx *ctx = get_binding_ctx(h);
410 h.
on_add = Delegate::run_add;
411 ctx->on_add = FLECS_NEW(Delegate)(FLECS_FWD(func));
412 ctx->free_on_add = _::free_obj<Delegate>;
418 template <
typename Func>
421 typename std::decay<Func>::type, T>;
422 flecs::type_hooks_t h = get_hooks();
424 "on_remove hook is already set");
425 BindingCtx *ctx = get_binding_ctx(h);
427 ctx->on_remove = FLECS_NEW(Delegate)(FLECS_FWD(func));
428 ctx->free_on_remove = _::free_obj<Delegate>;
434 template <
typename Func>
437 typename std::decay<Func>::type, T>;
438 flecs::type_hooks_t h = get_hooks();
440 "on_set hook is already set");
441 BindingCtx *ctx = get_binding_ctx(h);
442 h.
on_set = Delegate::run_set;
443 ctx->on_set = FLECS_NEW(Delegate)(FLECS_FWD(func));
444 ctx->free_on_set = _::free_obj<Delegate>;
450 using untyped_component::on_compare;
453 ecs_assert(handler != NULL, ECS_INVALID_OPERATION,
454 "Type does not have operator> or operator< const or is inaccessible");
462 on_compare(
reinterpret_cast<ecs_cmp_t>(callback));
467 using untyped_component::on_equals;
470 ecs_assert(handler != NULL, ECS_INVALID_OPERATION,
471 "Type does not have operator== const or is inaccessible");
484# include "mixins/meta/component.inl"
490 BindingCtx* get_binding_ctx(flecs::type_hooks_t& h){
491 BindingCtx *result =
static_cast<BindingCtx*
>(h.
binding_ctx);
493 result = FLECS_NEW(BindingCtx);
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.
ecs_entity_t ecs_entity_init(ecs_world_t *world, const ecs_entity_desc_t *desc)
Find or create an entity.
int(* ecs_cmp_t)(const void *a_ptr, const void *b_ptr, const ecs_type_info_t *type_info)
Compare hook to compare component instances.
bool(* ecs_equals_t)(const void *a_ptr, const void *b_ptr, const ecs_type_info_t *type_info)
Equals operator hook.
bool ecs_is_alive(const ecs_world_t *world, ecs_entity_t e)
Test whether an entity is alive.
Used with ecs_entity_init().
const char * sep
Optional custom separator for hierarchical names.
const char * root_sep
Optional, used for identifiers relative to root.
const char * name
Name of the entity.
bool use_low_id
When set to true, a low id (typically reserved for components) will be used to create the entity,...
ecs_copy_t copy_ctor
Ctor + copy.
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_move_t move_dtor
Move + dtor.
ecs_flags32_t flags
Hook flags.
ecs_cmp_t cmp
Compare hook.
ecs_copy_t copy
copy assignment
ecs_iter_action_t on_set
Callback that is invoked when an instance of the component is set.
ecs_move_t move
move assignment
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.
ecs_move_t move_ctor
Ctor + move.
ecs_equals_t equals
Equals hook.
ecs_move_t ctor_move_dtor
Ctor + move + dtor (or move_ctor + dtor).
Type that contains component information (passed to ctors/dtors/...)
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.
bool(*)(const T *a, const T *b, const ecs_type_info_t *ti) equals_hook
Type safe variant of equals op function.
component< T > & on_add(Func &&func)
Register on_add hook.
component< T > & on_set(Func &&func)
Register on_set hook.
int(*)(const T *a, const T *b, const ecs_type_info_t *ti) cmp_hook
Type safe variant of compare op function.
flecs::string_view name() const
Return the entity name.
Class that wraps around a flecs::id_t.
flecs::entity entity() const
Return id as entity (only allowed when id is valid entity)