Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend reflection framework with Id primitive #1078

Merged
merged 2 commits into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 212 additions & 25 deletions flecs.c

Large diffs are not rendered by default.

66 changes: 62 additions & 4 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2307,6 +2307,10 @@ void ecs_os_set_api_defaults(void);
#define ecs_os_memcpy_n(ptr1, ptr2, T, count) ecs_os_memcpy(ptr1, ptr2, ECS_SIZEOF(T) * count)
#define ecs_os_memcmp_t(ptr1, ptr2, T) ecs_os_memcmp(ptr1, ptr2, ECS_SIZEOF(T))

#define ecs_os_memmove_t(ptr1, ptr2, T) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T))
#define ecs_os_memmove_n(ptr1, ptr2, T, count) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T) * count)
#define ecs_os_memmove_t(ptr1, ptr2, T) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T))

#define ecs_os_strcmp(str1, str2) strcmp(str1, str2)
#define ecs_os_memset_t(ptr, value, T) ecs_os_memset(ptr, value, ECS_SIZEOF(T))
#define ecs_os_memset_n(ptr, value, T, count) ecs_os_memset(ptr, value, ECS_SIZEOF(T) * count)
Expand Down Expand Up @@ -13384,6 +13388,7 @@ FLECS_API extern const ecs_entity_t ecs_id(ecs_f32_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_f64_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_string_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_entity_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_id_t);

/** Type kinds supported by meta addon */
typedef enum ecs_type_kind_t {
Expand Down Expand Up @@ -13423,7 +13428,8 @@ typedef enum ecs_primitive_kind_t {
EcsIPtr,
EcsString,
EcsEntity,
EcsPrimitiveKindLast = EcsEntity
EcsId,
EcsPrimitiveKindLast = EcsId
} ecs_primitive_kind_t;

/** Component added to primitive types */
Expand Down Expand Up @@ -13642,6 +13648,12 @@ typedef struct EcsOpaque {
ecs_world_t *world,
ecs_entity_t entity);

/** Assign (component) id value */
void (*assign_id)(
void *dst,
ecs_world_t *world,
ecs_id_t id);

/** Assign null value */
void (*assign_null)(
void *dst);
Expand Down Expand Up @@ -13732,7 +13744,8 @@ typedef enum ecs_meta_type_op_kind_t {
EcsOpIPtr,
EcsOpString,
EcsOpEntity,
EcsMetaTypeOpKindLast = EcsOpEntity
EcsOpId,
EcsMetaTypeOpKindLast = EcsOpId
} ecs_meta_type_op_kind_t;

typedef struct ecs_meta_type_op_t {
Expand Down Expand Up @@ -13908,6 +13921,18 @@ int ecs_meta_set_entity(
ecs_meta_cursor_t *cursor,
ecs_entity_t value);

/** Set field with (component) id value */
FLECS_API
int ecs_meta_set_id(
ecs_meta_cursor_t *cursor,
ecs_id_t value);

/** Set field with (component) id value */
FLECS_API
int ecs_meta_set_component(
ecs_meta_cursor_t *cursor,
ecs_id_t value);

/** Set field with null value */
FLECS_API
int ecs_meta_set_null(
Expand Down Expand Up @@ -13960,6 +13985,11 @@ FLECS_API
ecs_entity_t ecs_meta_get_entity(
const ecs_meta_cursor_t *cursor);

/** Get field value as (component) id.
* This operation can convert from an entity. */
ecs_id_t ecs_meta_get_id(
const ecs_meta_cursor_t *cursor);

/** Convert pointer of primitive kind to float. */
FLECS_API
double ecs_meta_ptr_to_float(
Expand Down Expand Up @@ -17705,6 +17735,11 @@ struct cursor {
return ecs_meta_set_entity(&m_cursor, value);
}

/** Set (component) id value */
int set_id(flecs::id_t value) {
return ecs_meta_set_id(&m_cursor, value);
}

/** Set null value */
int set_null() {
return ecs_meta_set_null(&m_cursor);
Expand Down Expand Up @@ -17861,6 +17896,16 @@ struct opaque {
return *this;
}

/** Assign (component) id value */
opaque& assign_id(
void (*func)(T *dst, ecs_world_t *world, ecs_id_t id))
{
this->desc.type.assign_id =
reinterpret_cast<decltype(
this->desc.type.assign_id)>(func);
return *this;
}

/** Assign null value */
opaque& assign_null(void (*func)(T *dst)) {
this->desc.type.assign_null =
Expand Down Expand Up @@ -24330,6 +24375,16 @@ struct each_delegate : public delegate {
self->invoke(iter);
}

// Create instance of delegate
static each_delegate* make(const Func& func) {
return FLECS_NEW(each_delegate)(func);
}

// Function that can be used as callback to free delegate
static void free(void *obj) {
_::free_obj<each_delegate>(static_cast<each_delegate*>(obj));
}

// Static function to call for component on_add hook
static void run_add(ecs_iter_t *iter) {
component_binding_ctx *ctx = reinterpret_cast<component_binding_ctx*>(
Expand Down Expand Up @@ -25000,6 +25055,10 @@ struct entity_with_delegate<Func, if_t< is_callable<Func>::value > >

} // namespace _

// Experimental: allows using the each delegate for use cases outside of flecs
template <typename Func, typename ... Args>
using delegate = _::each_delegate<typename std::decay<Func>::type, Args...>;

} // namespace flecs

/**
Expand Down Expand Up @@ -26020,8 +26079,7 @@ struct component : untyped_component {
/** Register on_add hook. */
template <typename Func>
component<T>& on_add(Func&& func) {
using Delegate = typename _::each_delegate<
typename std::decay<Func>::type, T>;
using Delegate = typename _::each_delegate<typename std::decay<Func>::type, T>;
flecs::type_hooks_t h = get_hooks();
ecs_assert(h.on_add == nullptr, ECS_INVALID_OPERATION,
"on_add hook is already set");
Expand Down
3 changes: 1 addition & 2 deletions include/flecs/addons/cpp/component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,7 @@ struct component : untyped_component {
/** Register on_add hook. */
template <typename Func>
component<T>& on_add(Func&& func) {
using Delegate = typename _::each_delegate<
typename std::decay<Func>::type, T>;
using Delegate = typename _::each_delegate<typename std::decay<Func>::type, T>;
flecs::type_hooks_t h = get_hooks();
ecs_assert(h.on_add == nullptr, ECS_INVALID_OPERATION,
"on_add hook is already set");
Expand Down
14 changes: 14 additions & 0 deletions include/flecs/addons/cpp/delegate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,16 @@ struct each_delegate : public delegate {
self->invoke(iter);
}

// Create instance of delegate
static each_delegate* make(const Func& func) {
return FLECS_NEW(each_delegate)(func);
}

// Function that can be used as callback to free delegate
static void free(void *obj) {
_::free_obj<each_delegate>(static_cast<each_delegate*>(obj));
}

// Static function to call for component on_add hook
static void run_add(ecs_iter_t *iter) {
component_binding_ctx *ctx = reinterpret_cast<component_binding_ctx*>(
Expand Down Expand Up @@ -883,4 +893,8 @@ struct entity_with_delegate<Func, if_t< is_callable<Func>::value > >

} // namespace _

// Experimental: allows using the each delegate for use cases outside of flecs
template <typename Func, typename ... Args>
using delegate = _::each_delegate<typename std::decay<Func>::type, Args...>;

} // namespace flecs
5 changes: 5 additions & 0 deletions include/flecs/addons/cpp/mixins/meta/cursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ struct cursor {
return ecs_meta_set_entity(&m_cursor, value);
}

/** Set (component) id value */
int set_id(flecs::id_t value) {
return ecs_meta_set_id(&m_cursor, value);
}

/** Set null value */
int set_null() {
return ecs_meta_set_null(&m_cursor);
Expand Down
10 changes: 10 additions & 0 deletions include/flecs/addons/cpp/mixins/meta/opaque.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ struct opaque {
return *this;
}

/** Assign (component) id value */
opaque& assign_id(
void (*func)(T *dst, ecs_world_t *world, ecs_id_t id))
{
this->desc.type.assign_id =
reinterpret_cast<decltype(
this->desc.type.assign_id)>(func);
return *this;
}

/** Assign null value */
opaque& assign_null(void (*func)(T *dst)) {
this->desc.type.assign_null =
Expand Down
30 changes: 28 additions & 2 deletions include/flecs/addons/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ FLECS_API extern const ecs_entity_t ecs_id(ecs_f32_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_f64_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_string_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_entity_t);
FLECS_API extern const ecs_entity_t ecs_id(ecs_id_t);

/** Type kinds supported by meta addon */
typedef enum ecs_type_kind_t {
Expand Down Expand Up @@ -175,7 +176,8 @@ typedef enum ecs_primitive_kind_t {
EcsIPtr,
EcsString,
EcsEntity,
EcsPrimitiveKindLast = EcsEntity
EcsId,
EcsPrimitiveKindLast = EcsId
} ecs_primitive_kind_t;

/** Component added to primitive types */
Expand Down Expand Up @@ -394,6 +396,12 @@ typedef struct EcsOpaque {
ecs_world_t *world,
ecs_entity_t entity);

/** Assign (component) id value */
void (*assign_id)(
void *dst,
ecs_world_t *world,
ecs_id_t id);

/** Assign null value */
void (*assign_null)(
void *dst);
Expand Down Expand Up @@ -484,7 +492,8 @@ typedef enum ecs_meta_type_op_kind_t {
EcsOpIPtr,
EcsOpString,
EcsOpEntity,
EcsMetaTypeOpKindLast = EcsOpEntity
EcsOpId,
EcsMetaTypeOpKindLast = EcsOpId
} ecs_meta_type_op_kind_t;

typedef struct ecs_meta_type_op_t {
Expand Down Expand Up @@ -660,6 +669,18 @@ int ecs_meta_set_entity(
ecs_meta_cursor_t *cursor,
ecs_entity_t value);

/** Set field with (component) id value */
FLECS_API
int ecs_meta_set_id(
ecs_meta_cursor_t *cursor,
ecs_id_t value);

/** Set field with (component) id value */
FLECS_API
int ecs_meta_set_component(
ecs_meta_cursor_t *cursor,
ecs_id_t value);

/** Set field with null value */
FLECS_API
int ecs_meta_set_null(
Expand Down Expand Up @@ -712,6 +733,11 @@ FLECS_API
ecs_entity_t ecs_meta_get_entity(
const ecs_meta_cursor_t *cursor);

/** Get field value as (component) id.
* This operation can convert from an entity. */
ecs_id_t ecs_meta_get_id(
const ecs_meta_cursor_t *cursor);

/** Convert pointer of primitive kind to float. */
FLECS_API
double ecs_meta_ptr_to_float(
Expand Down
4 changes: 4 additions & 0 deletions include/flecs/os_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,10 @@ void ecs_os_set_api_defaults(void);
#define ecs_os_memcpy_n(ptr1, ptr2, T, count) ecs_os_memcpy(ptr1, ptr2, ECS_SIZEOF(T) * count)
#define ecs_os_memcmp_t(ptr1, ptr2, T) ecs_os_memcmp(ptr1, ptr2, ECS_SIZEOF(T))

#define ecs_os_memmove_t(ptr1, ptr2, T) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T))
#define ecs_os_memmove_n(ptr1, ptr2, T, count) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T) * count)
#define ecs_os_memmove_t(ptr1, ptr2, T) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T))

#define ecs_os_strcmp(str1, str2) strcmp(str1, str2)
#define ecs_os_memset_t(ptr, value, T) ecs_os_memset(ptr, value, ECS_SIZEOF(T))
#define ecs_os_memset_n(ptr, value, T, count) ecs_os_memset(ptr, value, ECS_SIZEOF(T) * count)
Expand Down
1 change: 1 addition & 0 deletions src/addons/alerts.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ ecs_entity_t flecs_alert_out_of_range_kind(
case EcsIPtr:
case EcsString:
case EcsEntity:
case EcsId:
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/addons/expr/deserialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ ecs_entity_t flecs_largest_type(
case EcsIPtr: return ecs_id(ecs_i64_t);
case EcsString: return ecs_id(ecs_string_t);
case EcsEntity: return ecs_id(ecs_entity_t);
case EcsId: return ecs_id(ecs_id_t);
default: ecs_throw(ECS_INTERNAL_ERROR, NULL);
}
error:
Expand Down
11 changes: 11 additions & 0 deletions src/addons/expr/serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ int flecs_expr_ser_primitive(
}
break;
}
case EcsId: {
ecs_id_t id = *(const ecs_id_t*)base;
if (!id) {
ecs_strbuf_appendch(str, '0');
} else {
ecs_id_str_buf(world, id, str);
}
break;
}
default:
ecs_err("invalid primitive kind");
return -1;
Expand Down Expand Up @@ -370,6 +379,7 @@ int flecs_expr_ser_type_op(
case EcsOpUPtr:
case EcsOpIPtr:
case EcsOpEntity:
case EcsOpId:
case EcsOpString:
case EcsOpOpaque:
if (flecs_expr_ser_primitive(world, flecs_expr_op_to_primitive_kind(op->kind),
Expand Down Expand Up @@ -454,6 +464,7 @@ int flecs_expr_ser_type_ops(
case EcsOpUPtr:
case EcsOpIPtr:
case EcsOpEntity:
case EcsOpId:
case EcsOpString:
case EcsOpOpaque:
if (flecs_expr_ser_type_op(world, op, base, str, is_expr)) {
Expand Down
10 changes: 10 additions & 0 deletions src/addons/json/serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,15 @@ int json_ser_type_op(
}
break;
}
case EcsOpId: {
ecs_id_t id = *(const ecs_id_t*)vptr;
if (!id) {
ecs_strbuf_appendch(str, '0');
} else {
flecs_json_id(str, world, id);
}
break;
}

case EcsOpU64:
case EcsOpI64:
Expand Down Expand Up @@ -466,6 +475,7 @@ int json_ser_type_ops(
case EcsOpUPtr:
case EcsOpIPtr:
case EcsOpEntity:
case EcsOpId:
case EcsOpString:
case EcsOpOpaque:
if (json_ser_type_op(world, op, base, str)) {
Expand Down
5 changes: 5 additions & 0 deletions src/addons/json/serialize_type_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ int json_typeinfo_ser_primitive(
case EcsEntity:
flecs_json_string(str, "entity");
break;
case EcsId:
flecs_json_string(str, "id");
break;
default:
return -1;
}
Expand Down Expand Up @@ -248,6 +251,7 @@ int json_typeinfo_ser_type_op(
case EcsOpUPtr:
case EcsOpIPtr:
case EcsOpEntity:
case EcsOpId:
case EcsOpString:
if (json_typeinfo_ser_primitive(
flecs_json_op_to_primitive_kind(op->kind), str))
Expand Down Expand Up @@ -360,6 +364,7 @@ int json_typeinfo_ser_type_ops(
case EcsOpUPtr:
case EcsOpIPtr:
case EcsOpEntity:
case EcsOpId:
case EcsOpString:
case EcsOpOpaque:
if (json_typeinfo_ser_type_op(world, op, str, stack[sp - 1])) {
Expand Down
Loading