spritesheet viewer + update flecs

efd/v1
Dominik Madarász 2023-02-02 12:26:01 +01:00
parent 89fea143d3
commit 6e6243e9df
8 changed files with 1364 additions and 520 deletions

View File

@ -0,0 +1,14 @@
void spritesheet_viewer(struct nk_context *ctx, struct nk_image spritesheet, Vector2 frameSize, int framesPerRow) {
const int maxFrames = (int)((spritesheet.w*spritesheet.h) / (frameSize.x*frameSize.y));
nk_layout_row_static(ctx, 32, 32, (int)(nk_window_get_size(ctx).x / frameSize.x) -1);
for(int frame = 0; frame < maxFrames; frame++) {
float ox = (frame % framesPerRow) * frameSize.x;
float oy = (int)(frame / framesPerRow) * frameSize.y;
spritesheet.region[0] = (nk_ushort)ox;
spritesheet.region[1] = (nk_ushort)oy;
spritesheet.region[2] = (nk_ushort)frameSize.x;
spritesheet.region[3] = (nk_ushort)frameSize.y;
nk_image(ctx, spritesheet);
nk_labelf(ctx, NK_TEXT_ALIGN_LEFT, "%d", frame);
}
}

View File

@ -0,0 +1,80 @@
void PhysOnCreateBody(ecs_iter_t *it) {
PhysicsBody *pb = ecs_field(it, PhysicsBody, 1);
Position *p = ecs_field(it, Position, 2);
for (int i = 0; i < it->count; i++) {
if (pb[i].body_ptr > 0) continue;
const frMaterial mat = {
.density = pb[i].density,
.staticFriction = pb[i].static_friction,
.dynamicFriction = pb[i].dynamic_friction,
};
frShape *shape = 0;
if (pb[i].kind == PHYS_CIRCLE) {
shape = frCreateCircle(mat, pb[i].circle.r);
} else {
shape = frCreateRectangle(mat, pb[i].rect.w, pb[i].rect.h);
}
frBodyFlags flags = 0x0;
if (pb[i].inf_inertia) flags |= FR_FLAG_INFINITE_INERTIA;
if (pb[i].inf_mass) flags |= FR_FLAG_INFINITE_MASS;
frBody *body = frCreateBodyFromShape(FR_BODY_DYNAMIC, flags, frVec2PixelsToMeters((Vector2){p[i].x, p[i].y}), shape);
frAddToWorld(phys_world, body);
pb[i].body_ptr = (uintptr_t)body;
}
}
void PhysOnRemoveBody(ecs_iter_t *it) {
PhysicsBody *pb = ecs_field(it, PhysicsBody, 1);
for (int i = 0; i < it->count; i++) {
frBody *body = (frBody*)pb[i].body_ptr;
frRemoveFromWorld(phys_world, body);
frShape *shape = frGetBodyShape(body);
frReleaseBody(body);
frReleaseShape(shape);
}
}
void PhysSetVelocity(ecs_iter_t *it) {
PhysicsBody *pb = ecs_field(it, PhysicsBody, 1);
Velocity *v = ecs_field(it, Velocity, 2);
for (int i = 0; i < it->count; i++) {
frBody *body = (frBody*)pb[i].body_ptr;
frSetBodyVelocity(body, frVec2PixelsToMeters((Vector2) { v[i].x , v[i].y }));
}
}
void PhysUpdatePosition(ecs_iter_t *it) {
PhysicsBody *pb = ecs_field(it, PhysicsBody, 1);
Position *p = ecs_field(it, Position, 2);
Velocity *v = ecs_field(it, Velocity, 3);
for (int i = 0; i < it->count; i++) {
frBody *body = (frBody*)pb[i].body_ptr;
Vector2 pos = frVec2MetersToPixels(frGetBodyPosition(body));
entity_set_position(it->entities[i], pos.x, pos.y);
Vector2 vel = frVec2MetersToPixels(frGetBodyVelocity(body));
v[i].x = vel.x;
v[i].y = vel.y;
}
}
void PhysResetPosition(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
for (int i = 0; i < it->count; i++) {
const PhysicsBody *pb = ecs_get(it->world, it->entities[i], PhysicsBody);
if (!pb) continue;
frBody *body = (frBody*)pb->body_ptr;
frSetBodyPosition(body, frVec2PixelsToMeters((Vector2){p[i].x, p[i].y}));
}
}
void PhysSimulateWorld(ecs_iter_t *it) {
frSimulateWorld(phys_world, 1.0f/60.0f);
}

View File

@ -252,3 +252,48 @@ void DrawRectangleLinesEco(float posX, float posY, float width, float height, Co
rlVertex2f(posX + 1, posY + 1); rlVertex2f(posX + 1, posY + 1);
rlEnd(); rlEnd();
} }
//------------------------------------------------------------------------
// SPRITESHEET
//------------------------------------------------------------------------
extern float platform_frametime();
typedef struct {
Texture2D texture;
Vector2 frameSize;
int framesPerRow;
Vector2 origin;
} SpriteSheet;
typedef struct {
SpriteSheet *spritesheet;
int start;
int numFrames;
float tickDelay; // in seconds
int frame; // output
// transient data
float nextTickTime;
} SpriteAnimation;
static inline
void DrawSpriteEco(SpriteSheet* sprite, int frame, float x, float y, float ang, float scale, Color c) {
float ox = (frame % sprite->framesPerRow) * sprite->frameSize.x;
float oy = (int)(frame / sprite->framesPerRow) * sprite->frameSize.y;
DrawTexturePro(sprite->texture, (Rectangle){ox, oy, sprite->frameSize.x,sprite->frameSize.y},
(Rectangle){x, y, sprite->frameSize.x * scale, sprite->frameSize.y * scale},
(Vector2){sprite->origin.x * scale, sprite->origin.y * scale}, ang, c);
}
static inline
int TickSpriteAnimation(SpriteAnimation *anim) {
if (anim->nextTickTime < platform_frametime()) {
anim->nextTickTime = platform_frametime() + anim->tickDelay;
anim->frame = anim->start + (anim->frame + 1) % anim->numFrames;
}
return anim->frame;
}

View File

@ -27,6 +27,7 @@ ZPL_DIAGNOSTIC_POP
#include "gui/ui_skin.c" #include "gui/ui_skin.c"
#include "gui/tooltip.c" #include "gui/tooltip.c"
#include "gui/notifications.c" #include "gui/notifications.c"
#include "gui/spritesheet_viewer.c"
#include "renderer.c" #include "renderer.c"
@ -91,48 +92,6 @@ void platform_input() {
} }
} }
void debug_draw_spritesheet() {
if (nk_begin(game_ui, "Spritesheet debug", nk_rect(660, 100, 240, 800),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|NK_WINDOW_TITLE))
{
nk_layout_row_dynamic(game_ui, 0, 2);
static int spritesheet_frame_id = 0;
if(nk_button_label(game_ui, "Prev")){
spritesheet_frame_id-=100;
}
if(nk_button_label(game_ui, "Next")){
spritesheet_frame_id+=100;
}
static bool loaded = false;
static struct nk_image nuclear_image;
static int max_frames = 0;
if (!loaded) {
nuclear_image = TextureToNuklear(main_sprite_sheet.texture);
max_frames = nuclear_image.w*nuclear_image.h / (32*32);
loaded = true;
}
nk_layout_row_static(game_ui, 32, 32, (int)(nk_window_get_size(game_ui).x / 32.f) -1);
for(int i = 0; i < 100; i++) {
int frame = spritesheet_frame_id + i;
frame %= max_frames;
float ox = (frame % main_sprite_sheet.framesWide) * main_sprite_sheet.frameSize.x;
float oy = (int)(frame / main_sprite_sheet.framesWide) * main_sprite_sheet.frameSize.y;
nuclear_image.region[0] = (nk_short)ox;
nuclear_image.region[1] = (nk_short)oy;
nuclear_image.region[2] = 32;
nuclear_image.region[3] = 32;
nk_image(game_ui, nuclear_image);
nk_labelf(game_ui, NK_TEXT_ALIGN_LEFT, "%d", frame);
}
nk_end(game_ui);
}
}
void platform_render() { void platform_render() {
platform_resize_window(); platform_resize_window();
@ -162,7 +121,14 @@ void platform_render() {
renderer_debug_draw(); renderer_debug_draw();
debug_draw(); debug_draw();
debug_draw_spritesheet();
if (nk_begin(game_ui, "Spritesheet Viewer", nk_rect(460, 100, 800, 600),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|NK_WINDOW_TITLE))
{
spritesheet_viewer(game_ui, main_sprite_sheet_nk, main_sprite_sheet.frameSize, main_sprite_sheet.framesPerRow);
nk_end(game_ui);
}
notification_draw(); notification_draw();
game_draw_ui(); game_draw_ui();
} }

View File

@ -1,9 +1,8 @@
#include "spritesheet.c"
static Camera2D render_camera; static Camera2D render_camera;
static float zoom_overlay_tran = 0.0f; static float zoom_overlay_tran = 0.0f;
static SpriteSheet main_sprite_sheet = { 0 }; static SpriteSheet main_sprite_sheet = { 0 };
static struct nk_image main_sprite_sheet_nk = { 0 };
#define CAM_OVERLAY_ZOOM_LEVEL 0.15f #define CAM_OVERLAY_ZOOM_LEVEL 0.15f
#define ALPHA(x) ColorAlpha(x, data->tran_time) #define ALPHA(x) ColorAlpha(x, data->tran_time)
@ -95,7 +94,7 @@ void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entr
DrawNametag("Player", key, data, x, y-16); DrawNametag("Player", key, data, x, y-16);
//DrawTextureRec(GetSpriteTexture2D(assets_find(ASSET_PLAYER)), ASSET_SRC_RECT(), (Vector2){data->x-(WORLD_BLOCK_SIZE/2), data->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time)); //DrawTextureRec(GetSpriteTexture2D(assets_find(ASSET_PLAYER)), ASSET_SRC_RECT(), (Vector2){data->x-(WORLD_BLOCK_SIZE/2), data->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
//DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time)); //DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
sprite_draw(&main_sprite_sheet, 129, x, y, 0.0f, 2.0f, WHITE); DrawSpriteEco(&main_sprite_sheet, 129, x, y, 0.0f, 2.0f, WHITE);
//if (data->has_items && !data->inside_vehicle) { //if (data->has_items && !data->inside_vehicle) {
// float ix = data->x; // float ix = data->x;
@ -167,8 +166,10 @@ void renderer_init(void) {
// NOTE(DavoSK): Init others spritesheets here // NOTE(DavoSK): Init others spritesheets here
main_sprite_sheet.texture = LoadTexture("art/gen/spritesheet.png"); main_sprite_sheet.texture = LoadTexture("art/gen/spritesheet.png");
main_sprite_sheet.frameSize = (Vector2){ 32, 32 }; main_sprite_sheet.frameSize = (Vector2){ 32, 32 };
main_sprite_sheet.framesWide = 64; main_sprite_sheet.framesPerRow = 64;
main_sprite_sheet.origin = (Vector2){ 16, 16 }; main_sprite_sheet.origin = (Vector2){ 16, 16 };
main_sprite_sheet_nk = TextureToNuklear(main_sprite_sheet.texture);
} }
void renderer_shutdown(void) { void renderer_shutdown(void) {

View File

@ -1,18 +0,0 @@
typedef struct {
Texture2D texture;
Vector2 frameSize;
int framesWide;
Vector2 origin;
} SpriteSheet;
// enum {
// SPRITE_PLAYER =
// };
void sprite_draw(SpriteSheet* sprite, int frame, float x, float y, float ang, float scale, Color c) {
float ox = (frame % sprite->framesWide) * sprite->frameSize.x;
float oy = (int)(frame / sprite->framesWide) * sprite->frameSize.y;
DrawTexturePro(sprite->texture, (Rectangle){ox, oy, sprite->frameSize.x,sprite->frameSize.y},
(Rectangle){x, y, sprite->frameSize.x * scale, sprite->frameSize.y * scale},
(Vector2){sprite->origin.x * scale, sprite->origin.y * scale}, ang, c);
}

File diff suppressed because it is too large Load Diff

View File

@ -2576,8 +2576,6 @@ void ecs_os_set_api_defaults(void);
#define ecs_os_strdup(str) ecs_os_api.strdup_(str) #define ecs_os_strdup(str) ecs_os_api.strdup_(str)
#endif #endif
#define ecs_os_strset(dst, src) ecs_os_free(*dst); *dst = ecs_os_strdup(src)
#ifdef __cplusplus #ifdef __cplusplus
#define ecs_os_strlen(str) static_cast<ecs_size_t>(strlen(str)) #define ecs_os_strlen(str) static_cast<ecs_size_t>(strlen(str))
#define ecs_os_strncmp(str1, str2, num) strncmp(str1, str2, static_cast<size_t>(num)) #define ecs_os_strncmp(str1, str2, num) strncmp(str1, str2, static_cast<size_t>(num))
@ -2686,6 +2684,9 @@ void ecs_os_fatal(const char *file, int32_t line, const char *msg);
FLECS_API FLECS_API
const char* ecs_os_strerror(int err); const char* ecs_os_strerror(int err);
FLECS_API
void ecs_os_strset(char **str, const char *value);
#ifdef FLECS_ACCURATE_COUNTERS #ifdef FLECS_ACCURATE_COUNTERS
#define ecs_os_inc(v) (ecs_os_ainc(v)) #define ecs_os_inc(v) (ecs_os_ainc(v))
#define ecs_os_linc(v) (ecs_os_lainc(v)) #define ecs_os_linc(v) (ecs_os_lainc(v))
@ -3168,6 +3169,7 @@ struct ecs_observer_t {
ecs_observable_t *observable; /**< Observable for observer */ ecs_observable_t *observable; /**< Observable for observer */
int32_t *last_event_id; /**< Last handled event id */ int32_t *last_event_id; /**< Last handled event id */
int32_t last_event_id_storage;
ecs_id_t register_id; /**< Id observer is registered with (single term observers only) */ ecs_id_t register_id; /**< Id observer is registered with (single term observers only) */
int32_t term_index; /**< Index of the term in parent observer (single term observers only) */ int32_t term_index; /**< Index of the term in parent observer (single term observers only) */
@ -4380,10 +4382,10 @@ FLECS_API extern const ecs_entity_t EcsMonitor;
FLECS_API extern const ecs_entity_t EcsOnDelete; FLECS_API extern const ecs_entity_t EcsOnDelete;
/** Event. Triggers when a table is created. */ /** Event. Triggers when a table is created. */
// FLECS_API extern const ecs_entity_t EcsOnCreateTable; FLECS_API extern const ecs_entity_t EcsOnTableCreate;
/** Event. Triggers when a table is deleted. */ /** Event. Triggers when a table is deleted. */
// FLECS_API extern const ecs_entity_t EcsOnDeleteTable; FLECS_API extern const ecs_entity_t EcsOnTableDelete;
/** Event. Triggers when a table becomes empty (doesn't emit on creation). */ /** Event. Triggers when a table becomes empty (doesn't emit on creation). */
FLECS_API extern const ecs_entity_t EcsOnTableEmpty; FLECS_API extern const ecs_entity_t EcsOnTableEmpty;
@ -4440,7 +4442,7 @@ FLECS_API extern const ecs_entity_t EcsPhase;
/** The first user-defined component starts from this id. Ids up to this number /** The first user-defined component starts from this id. Ids up to this number
* are reserved for builtin components */ * are reserved for builtin components */
#define EcsFirstUserComponentId (32) #define EcsFirstUserComponentId (8)
/** The first user-defined entity starts from this id. Ids up to this number /** The first user-defined entity starts from this id. Ids up to this number
* are reserved for builtin components */ * are reserved for builtin components */
@ -5506,12 +5508,13 @@ void ecs_ref_update(
ecs_ref_t *ref); ecs_ref_t *ref);
/** Get a mutable pointer to a component. /** Get a mutable pointer to a component.
* This operation is similar to ecs_get_id but it returns a mutable * This operation returns a mutable pointer to a component. If the component did
* pointer. If this operation is invoked from inside a system, the entity will * not yet exist, it will be added.
* be staged and a pointer to the staged component will be returned.
* *
* If the entity did not yet have the component, the component will be added by * If get_mut is called when the world is in deferred/readonly mode, the
* this operation. In this case the is_added out parameter will be set to true. * function will:
* - return a pointer to a temp storage if the component does not yet exist, or
* - return a pointer to the existing component if it exists
* *
* @param world The world. * @param world The world.
* @param entity The entity. * @param entity The entity.
@ -8439,6 +8442,17 @@ int ecs_value_move_ctor(
#define ecs_entity(world, ...)\ #define ecs_entity(world, ...)\
ecs_entity_init(world, &(ecs_entity_desc_t) __VA_ARGS__ ) ecs_entity_init(world, &(ecs_entity_desc_t) __VA_ARGS__ )
/** Shorthand for creating a component with ecs_component_init.
*
* Example:
* ecs_component(world, {
* .type.size = 4,
* .type.alignment = 4
* });
*/
#define ecs_component(world, ...)\
ecs_component_init(world, &(ecs_component_desc_t) __VA_ARGS__ )
/** Shorthand for creating a filter with ecs_filter_init. /** Shorthand for creating a filter with ecs_filter_init.
* *
* Example: * Example:
@ -8996,6 +9010,11 @@ int ecs_value_move_ctor(
#endif // FLECS_C_ #endif // FLECS_C_
#ifdef __cplusplus
}
#endif
/** /**
* @file addons.h * @file addons.h
* @brief Include enabled addons. * @brief Include enabled addons.
@ -11698,6 +11717,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_colors; /**< Serialize doc color for entities */ bool serialize_colors; /**< Serialize doc color for entities */
bool measure_eval_duration; /**< Serialize evaluation duration */ bool measure_eval_duration; /**< Serialize evaluation duration */
bool serialize_type_info; /**< Serialize type information */ bool serialize_type_info; /**< Serialize type information */
bool serialize_table; /**< Serialize entire table vs. matched components */
} ecs_iter_to_json_desc_t; } ecs_iter_to_json_desc_t;
#define ECS_ITER_TO_JSON_INIT (ecs_iter_to_json_desc_t){\ #define ECS_ITER_TO_JSON_INIT (ecs_iter_to_json_desc_t){\
@ -11714,7 +11734,8 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_variable_ids = false, \ .serialize_variable_ids = false, \
.serialize_colors = false, \ .serialize_colors = false, \
.measure_eval_duration = false, \ .measure_eval_duration = false, \
.serialize_type_info = false \ .serialize_type_info = false, \
.serialize_table = false \
} }
/** Serialize iterator into JSON string. /** Serialize iterator into JSON string.
@ -11746,6 +11767,37 @@ int ecs_iter_to_json_buf(
ecs_strbuf_t *buf_out, ecs_strbuf_t *buf_out,
const ecs_iter_to_json_desc_t *desc); const ecs_iter_to_json_desc_t *desc);
/** Serialize world into JSON string.
* This operation iterates the contents of the world to JSON. The operation is
* equivalent to the following code:
*
* ecs_filter_t *f = ecs_filter(world, {
* .terms = {{ .id = EcsAny }}
* });
*
* ecs_iter_t it = ecs_filter_init(world, &f);
* ecs_iter_to_json_desc_t desc = { .serialize_table = true };
* ecs_iter_to_json(world, iter, &desc);
*
* @param world The world to serialize.
* @return A JSON string with the serialized iterator data, or NULL if failed.
*/
FLECS_API
char* ecs_world_to_json(
ecs_world_t *world);
/** Serialize world into JSON string buffer.
* Same as ecs_world_to_json, but serializes to an ecs_strbuf_t instance.
*
* @param world The world to serialize.
* @param buf_out The strbuf to append the string to.
* @return Zero if success, non-zero if failed.
*/
FLECS_API
int ecs_world_to_json_buf(
ecs_world_t *world,
ecs_strbuf_t *buf_out);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -12229,6 +12281,7 @@ FLECS_API extern const ecs_entity_t ecs_id(EcsMember);
FLECS_API extern const ecs_entity_t ecs_id(EcsStruct); FLECS_API extern const ecs_entity_t ecs_id(EcsStruct);
FLECS_API extern const ecs_entity_t ecs_id(EcsArray); FLECS_API extern const ecs_entity_t ecs_id(EcsArray);
FLECS_API extern const ecs_entity_t ecs_id(EcsVector); FLECS_API extern const ecs_entity_t ecs_id(EcsVector);
FLECS_API extern const ecs_entity_t ecs_id(EcsOpaque);
FLECS_API extern const ecs_entity_t ecs_id(EcsUnit); FLECS_API extern const ecs_entity_t ecs_id(EcsUnit);
FLECS_API extern const ecs_entity_t ecs_id(EcsUnitPrefix); FLECS_API extern const ecs_entity_t ecs_id(EcsUnitPrefix);
FLECS_API extern const ecs_entity_t EcsConstant; FLECS_API extern const ecs_entity_t EcsConstant;
@ -12261,6 +12314,7 @@ typedef enum ecs_type_kind_t {
EcsStructType, EcsStructType,
EcsArrayType, EcsArrayType,
EcsVectorType, EcsVectorType,
EcsOpaqueType,
EcsTypeKindLast = EcsVectorType EcsTypeKindLast = EcsVectorType
} ecs_type_kind_t; } ecs_type_kind_t;
@ -12371,6 +12425,72 @@ typedef struct EcsVector {
} EcsVector; } EcsVector;
/* Opaque type support */
#if !defined(__cplusplus) || !defined(FLECS_CPP)
/** Serializer interface */
typedef struct ecs_meta_serializer_t {
/* Serialize value */
int (*value)(
const struct ecs_meta_serializer_t *ser, /**< Serializer */
ecs_entity_t type, /**< Type of the value to serialize */
const void *value); /**< Pointer to the value to serialize */
/* Serialize member */
int (*member)(
const struct ecs_meta_serializer_t *ser, /**< Serializer */
const char *member); /**< Member name */
const ecs_world_t *world;
void *ctx;
} ecs_meta_serializer_t;
#elif defined(__cplusplus)
} /* extern "C" { */
/** Serializer interface (same layout as C, but with convenience methods) */
typedef struct ecs_meta_serializer_t {
/* Serialize value */
int (*value_)(
const struct ecs_meta_serializer_t *ser,
ecs_entity_t type,
const void *value);
/* Serialize member */
int (*member_)(
const struct ecs_meta_serializer_t *ser,
const char *name);
/* Serialize value */
int value(ecs_entity_t type, const void *value) const;
/* Serialize value */
template <typename T>
int value(const T& value) const;
/* Serialize member */
int member(const char *name) const;
const ecs_world_t *world;
void *ctx;
} ecs_meta_serializer_t;
extern "C" {
#endif
/** Callback invoked serializing an opaque type. */
typedef int (*ecs_meta_serialize_t)(
const ecs_meta_serializer_t *ser,
const void *src); /**< Pointer to value to serialize */
typedef struct EcsOpaque {
ecs_entity_t as_type; /**< Type that describes the serialized output */
ecs_meta_serialize_t serialize; /**< Serialize action */
} EcsOpaque;
/* Units */ /* Units */
/* Helper type to describe translation between two units. Note that this /* Helper type to describe translation between two units. Note that this
@ -12404,6 +12524,7 @@ typedef struct EcsUnitPrefix {
typedef enum ecs_meta_type_op_kind_t { typedef enum ecs_meta_type_op_kind_t {
EcsOpArray, EcsOpArray,
EcsOpVector, EcsOpVector,
EcsOpOpaque,
EcsOpPush, EcsOpPush,
EcsOpPop, EcsOpPop,
@ -12655,8 +12776,7 @@ ecs_entity_t ecs_meta_get_entity(
/** Used with ecs_primitive_init. */ /** Used with ecs_primitive_init. */
typedef struct ecs_primitive_desc_t { typedef struct ecs_primitive_desc_t {
/* Existing entity to associate with primitive (optional) */ ecs_entity_t entity; /**< Existing entity to use for type (optional) */
ecs_entity_t entity;
ecs_primitive_kind_t kind; ecs_primitive_kind_t kind;
} ecs_primitive_desc_t; } ecs_primitive_desc_t;
@ -12668,8 +12788,7 @@ ecs_entity_t ecs_primitive_init(
/** Used with ecs_enum_init. */ /** Used with ecs_enum_init. */
typedef struct ecs_enum_desc_t { typedef struct ecs_enum_desc_t {
/* Existing entity to associate with enum (optional) */ ecs_entity_t entity; /**< Existing entity to use for type (optional) */
ecs_entity_t entity;
ecs_enum_constant_t constants[ECS_MEMBER_DESC_CACHE_SIZE]; ecs_enum_constant_t constants[ECS_MEMBER_DESC_CACHE_SIZE];
} ecs_enum_desc_t; } ecs_enum_desc_t;
@ -12682,8 +12801,7 @@ ecs_entity_t ecs_enum_init(
/** Used with ecs_bitmask_init. */ /** Used with ecs_bitmask_init. */
typedef struct ecs_bitmask_desc_t { typedef struct ecs_bitmask_desc_t {
/* Existing entity to associate with bitmask (optional) */ ecs_entity_t entity; /**< Existing entity to use for type (optional) */
ecs_entity_t entity;
ecs_bitmask_constant_t constants[ECS_MEMBER_DESC_CACHE_SIZE]; ecs_bitmask_constant_t constants[ECS_MEMBER_DESC_CACHE_SIZE];
} ecs_bitmask_desc_t; } ecs_bitmask_desc_t;
@ -12696,8 +12814,7 @@ ecs_entity_t ecs_bitmask_init(
/** Used with ecs_array_init. */ /** Used with ecs_array_init. */
typedef struct ecs_array_desc_t { typedef struct ecs_array_desc_t {
/* Existing entity to associate with array (optional) */ ecs_entity_t entity; /**< Existing entity to use for type (optional) */
ecs_entity_t entity;
ecs_entity_t type; ecs_entity_t type;
int32_t count; int32_t count;
} ecs_array_desc_t; } ecs_array_desc_t;
@ -12711,8 +12828,7 @@ ecs_entity_t ecs_array_init(
/** Used with ecs_vector_init. */ /** Used with ecs_vector_init. */
typedef struct ecs_vector_desc_t { typedef struct ecs_vector_desc_t {
/* Existing entity to associate with vector (optional) */ ecs_entity_t entity; /**< Existing entity to use for type (optional) */
ecs_entity_t entity;
ecs_entity_t type; ecs_entity_t type;
} ecs_vector_desc_t; } ecs_vector_desc_t;
@ -12725,8 +12841,7 @@ ecs_entity_t ecs_vector_init(
/** Used with ecs_struct_init. */ /** Used with ecs_struct_init. */
typedef struct ecs_struct_desc_t { typedef struct ecs_struct_desc_t {
/* Existing entity to associate with struct (optional) */ ecs_entity_t entity; /**< Existing entity to use for type (optional) */
ecs_entity_t entity;
ecs_member_t members[ECS_MEMBER_DESC_CACHE_SIZE]; ecs_member_t members[ECS_MEMBER_DESC_CACHE_SIZE];
} ecs_struct_desc_t; } ecs_struct_desc_t;
@ -12736,6 +12851,36 @@ ecs_entity_t ecs_struct_init(
ecs_world_t *world, ecs_world_t *world,
const ecs_struct_desc_t *desc); const ecs_struct_desc_t *desc);
/** Used with ecs_opaque_init. */
typedef struct ecs_opaque_desc_t {
ecs_entity_t entity;
ecs_entity_t as_type; /**< Type that describes the serialized output */
ecs_meta_serialize_t serialize; /**< Serialize action */
} ecs_opaque_desc_t;
/** Create a new opaque type.
* Opaque types are types of which the layout doesn't match what can be modelled
* with the primitives of the meta framework, but which have a structure
* that can be described with meta primitives. Typical examples are STL types
* such as std::string or std::vector, types with a nontrivial layout, and types
* that only expose getter/setter methods.
*
* An opaque type is a combination of a serialization function, and a handle to
* a meta type which describes the structure of the serialized output. For
* example, an opaque type for std::string would have a serializer function that
* accesses .c_str(), and with type ecs_string_t.
*
* The serializer callback accepts a serializer object and a pointer to the
* value of the opaque type to be serialized. The serializer has two methods:
*
* - value, which serializes a value (such as .c_str())
* - member, which specifies a member to be serialized (in the case of a struct)
*/
FLECS_API
ecs_entity_t ecs_opaque_init(
ecs_world_t *world,
const ecs_opaque_desc_t *desc);
/** Used with ecs_unit_init. */ /** Used with ecs_unit_init. */
typedef struct ecs_unit_desc_t { typedef struct ecs_unit_desc_t {
/** Existing entity to associate with unit (optional) */ /** Existing entity to associate with unit (optional) */
@ -12812,6 +12957,9 @@ ecs_entity_t ecs_quantity_init(
#define ecs_vector(world, ...)\ #define ecs_vector(world, ...)\
ecs_vector_init(world, &(ecs_vector_desc_t) __VA_ARGS__ ) ecs_vector_init(world, &(ecs_vector_desc_t) __VA_ARGS__ )
#define ecs_opaque(world, ...)\
ecs_opaque_init(world, &(ecs_opaque_desc_t) __VA_ARGS__ )
#define ecs_struct(world, ...)\ #define ecs_struct(world, ...)\
ecs_struct_init(world, &(ecs_struct_desc_t) __VA_ARGS__ ) ecs_struct_init(world, &(ecs_struct_desc_t) __VA_ARGS__ )
@ -14364,8 +14512,6 @@ int32_t ecs_cpp_reset_count_inc(void);
#ifdef __cplusplus #ifdef __cplusplus
}
/** /**
* @file addons/cpp/flecs.hpp * @file addons/cpp/flecs.hpp
* @brief Flecs C++11 API. * @brief Flecs C++11 API.
@ -14493,6 +14639,8 @@ static const flecs::entity_t OnAdd = EcsOnAdd;
static const flecs::entity_t OnRemove = EcsOnRemove; static const flecs::entity_t OnRemove = EcsOnRemove;
static const flecs::entity_t OnSet = EcsOnSet; static const flecs::entity_t OnSet = EcsOnSet;
static const flecs::entity_t UnSet = EcsUnSet; static const flecs::entity_t UnSet = EcsUnSet;
static const flecs::entity_t OnTableCreate = EcsOnTableCreate;
static const flecs::entity_t OnTableDelete = EcsOnTableDelete;
/* Builtin term flags */ /* Builtin term flags */
static const uint32_t Self = EcsSelf; static const uint32_t Self = EcsSelf;
@ -16064,6 +16212,7 @@ namespace flecs {
* @{ * @{
*/ */
/* Primitive type aliases */
using bool_t = ecs_bool_t; using bool_t = ecs_bool_t;
using char_t = ecs_char_t; using char_t = ecs_char_t;
using u8_t = ecs_u8_t; using u8_t = ecs_u8_t;
@ -16079,12 +16228,12 @@ using iptr_t = ecs_iptr_t;
using f32_t = ecs_f32_t; using f32_t = ecs_f32_t;
using f64_t = ecs_f64_t; using f64_t = ecs_f64_t;
using type_kind_t = ecs_type_kind_t; /* Embedded type aliases */
using primitive_kind_t = ecs_primitive_kind_t;
using member_t = ecs_member_t; using member_t = ecs_member_t;
using enum_constant_t = ecs_enum_constant_t; using enum_constant_t = ecs_enum_constant_t;
using bitmask_constant_t = ecs_bitmask_constant_t; using bitmask_constant_t = ecs_bitmask_constant_t;
/* Components */
using MetaType = EcsMetaType; using MetaType = EcsMetaType;
using MetaTypeSerialized = EcsMetaTypeSerialized; using MetaTypeSerialized = EcsMetaTypeSerialized;
using Primitive = EcsPrimitive; using Primitive = EcsPrimitive;
@ -16101,6 +16250,7 @@ struct bitmask {
uint32_t value; uint32_t value;
}; };
/* Handles to builtin reflection types */
static const flecs::entity_t Bool = ecs_id(ecs_bool_t); static const flecs::entity_t Bool = ecs_id(ecs_bool_t);
static const flecs::entity_t Char = ecs_id(ecs_char_t); static const flecs::entity_t Char = ecs_id(ecs_char_t);
static const flecs::entity_t Byte = ecs_id(ecs_byte_t); static const flecs::entity_t Byte = ecs_id(ecs_byte_t);
@ -16118,12 +16268,53 @@ static const flecs::entity_t F32 = ecs_id(ecs_f32_t);
static const flecs::entity_t F64 = ecs_id(ecs_f64_t); static const flecs::entity_t F64 = ecs_id(ecs_f64_t);
static const flecs::entity_t String = ecs_id(ecs_string_t); static const flecs::entity_t String = ecs_id(ecs_string_t);
static const flecs::entity_t Entity = ecs_id(ecs_entity_t); static const flecs::entity_t Entity = ecs_id(ecs_entity_t);
static const flecs::entity_t Constant = EcsConstant; static const flecs::entity_t Constant = EcsConstant;
static const flecs::entity_t Quantity = EcsQuantity; static const flecs::entity_t Quantity = EcsQuantity;
/** Serializer object, used for serializing opaque types */
using serializer = ecs_meta_serializer_t;
/** Serializer function, used to serialize opaque types */
using serialize_t = ecs_meta_serialize_t;
/** Type safe variant of serializer function */
template <typename T>
using serialize = int(*)(const serializer *, const T*);
namespace meta { namespace meta {
/* Type kinds supported by reflection system */
using type_kind_t = ecs_type_kind_t;
static const type_kind_t PrimitiveType = EcsPrimitiveType;
static const type_kind_t BitmaskType = EcsBitmaskType;
static const type_kind_t EnumType = EcsEnumType;
static const type_kind_t StructType = EcsStructType;
static const type_kind_t ArrayType = EcsArrayType;
static const type_kind_t VectorType = EcsVectorType;
static const type_kind_t CustomType = EcsOpaqueType;
static const type_kind_t TypeKindLast = EcsTypeKindLast;
/* Primitive type kinds supported by reflection system */
using primitive_kind_t = ecs_primitive_kind_t;
static const primitive_kind_t Bool = EcsBool;
static const primitive_kind_t Char = EcsChar;
static const primitive_kind_t Byte = EcsByte;
static const primitive_kind_t U8 = EcsU8;
static const primitive_kind_t U16 = EcsU16;
static const primitive_kind_t U32 = EcsU32;
static const primitive_kind_t U64 = EcsU64;
static const primitive_kind_t I8 = EcsI8;
static const primitive_kind_t I16 = EcsI16;
static const primitive_kind_t I32 = EcsI32;
static const primitive_kind_t I64 = EcsI64;
static const primitive_kind_t F32 = EcsF32;
static const primitive_kind_t F64 = EcsF64;
static const primitive_kind_t UPtr = EcsUPtr;
static const primitive_kind_t IPtr = EcsIPtr;
static const primitive_kind_t String = EcsString;
static const primitive_kind_t Entity = EcsEntity;
static const primitive_kind_t PrimitiveKindLast = EcsPrimitiveKindLast;
/** Class for reading/writing dynamic values. /** Class for reading/writing dynamic values.
* *
* \ingroup cpp_addons_meta * \ingroup cpp_addons_meta
@ -17519,7 +17710,7 @@ template <typename T, if_not_t< is_flecs_constructible<T>::value > = 0>
inline void set(world_t *world, flecs::entity_t entity, T&& value, flecs::id_t id) { inline void set(world_t *world, flecs::entity_t entity, T&& value, flecs::id_t id) {
ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL); ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL);
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id)); T& dst = *static_cast<remove_reference_t<T>*>(ecs_get_mut_id(world, entity, id));
dst = FLECS_MOV(value); dst = FLECS_MOV(value);
@ -18903,27 +19094,48 @@ int plecs_from_file(const char *filename) const {
* @{ * @{
*/ */
/** Convert value to string */
flecs::string to_expr(flecs::entity_t tid, const void* value) { flecs::string to_expr(flecs::entity_t tid, const void* value) {
char *expr = ecs_ptr_to_expr(m_world, tid, value); char *expr = ecs_ptr_to_expr(m_world, tid, value);
return flecs::string(expr); return flecs::string(expr);
} }
/** Convert value to string */
template <typename T> template <typename T>
flecs::string to_expr(const T* value) { flecs::string to_expr(const T* value) {
flecs::entity_t tid = _::cpp_type<T>::id(m_world); flecs::entity_t tid = _::cpp_type<T>::id(m_world);
return to_expr(tid, value); return to_expr(tid, value);
} }
/** Return meta cursor to value */
flecs::meta::cursor cursor(flecs::entity_t tid, void *ptr) { flecs::meta::cursor cursor(flecs::entity_t tid, void *ptr) {
return flecs::meta::cursor(m_world, tid, ptr); return flecs::meta::cursor(m_world, tid, ptr);
} }
/** Return meta cursor to value */
template <typename T> template <typename T>
flecs::meta::cursor cursor(void *ptr) { flecs::meta::cursor cursor(void *ptr) {
flecs::entity_t tid = _::cpp_type<T>::id(m_world); flecs::entity_t tid = _::cpp_type<T>::id(m_world);
return cursor(tid, ptr); return cursor(tid, ptr);
} }
/** Create primitive type */
flecs::entity primitive(flecs::meta::primitive_kind_t kind);
/** Create array type. */
flecs::entity array(flecs::entity_t elem_id, int32_t array_count);
/** Create array type. */
template <typename T>
flecs::entity array(int32_t array_count);
/** Create vector type. */
flecs::entity vector(flecs::entity_t elem_id);
/** Create vector type. */
template <typename T>
flecs::entity vector();
/** @} */ /** @} */
# endif # endif
@ -18954,6 +19166,15 @@ flecs::string to_json(const T* value) {
return to_json(tid, value); return to_json(tid, value);
} }
/** Serialize world to JSON.
*
* \memberof flecs::world
* \ingroup cpp_addons_json
*/
flecs::string to_json() {
return flecs::string( ecs_world_to_json(m_world) );
}
# endif # endif
# ifdef FLECS_APP # ifdef FLECS_APP
/** /**
@ -23138,6 +23359,7 @@ untyped_component& bit(const char *name, uint32_t value) {
} }
/** @} */ /** @} */
# endif # endif
}; };
@ -23278,6 +23500,22 @@ struct component : untyped_component {
return *this; return *this;
} }
# ifdef FLECS_META
/** Register custom reflection function for component. */
component& serialize(flecs::id_t as_type, flecs::serialize<T> ser) {
ecs_opaque_desc_t desc = {};
/* Safe cast, from a function with a T* arg to a void* arg */
desc.serialize = reinterpret_cast<flecs::serialize_t>(ser);
desc.entity = m_id;
desc.as_type = as_type;
ecs_opaque_init(m_world, &desc);
return *this;
}
# endif
private: private:
using BindingCtx = _::component_binding_ctx; using BindingCtx = _::component_binding_ctx;
@ -23733,7 +23971,7 @@ inline flecs::entity id::second() const {
if (m_world) { if (m_world) {
return flecs::entity(m_world, ecs_get_alive(m_world, e)); return flecs::entity(m_world, ecs_get_alive(m_world, e));
} else { } else {
return flecs::entity(m_world, e); return flecs::entity(e);
} }
} }
@ -27086,8 +27324,8 @@ inline rule_base::operator rule<>() const {
#pragma once #pragma once
FLECS_ENUM_LAST(flecs::type_kind_t, EcsTypeKindLast) FLECS_ENUM_LAST(flecs::meta::type_kind_t, flecs::meta::TypeKindLast)
FLECS_ENUM_LAST(flecs::primitive_kind_t, EcsPrimitiveKindLast) FLECS_ENUM_LAST(flecs::meta::primitive_kind_t, flecs::meta::PrimitiveKindLast)
namespace flecs { namespace flecs {
namespace meta { namespace meta {
@ -27163,8 +27401,61 @@ inline flecs::entity cursor::get_entity() const {
} }
} // namespace meta } // namespace meta
/** Create primitive type */
inline flecs::entity world::primitive(flecs::meta::primitive_kind_t kind) {
ecs_primitive_desc_t desc = {};
desc.kind = kind;
flecs::entity_t eid = ecs_primitive_init(m_world, &desc);
ecs_assert(eid != 0, ECS_INVALID_OPERATION, NULL);
return flecs::entity(m_world, eid);
}
/** Create array type. */
inline flecs::entity world::array(flecs::entity_t elem_id, int32_t array_count) {
ecs_array_desc_t desc = {};
desc.type = elem_id;
desc.count = array_count;
flecs::entity_t eid = ecs_array_init(m_world, &desc);
ecs_assert(eid != 0, ECS_INVALID_OPERATION, NULL);
return flecs::entity(m_world, eid);
}
/** Create array type. */
template <typename T>
inline flecs::entity world::array(int32_t array_count) {
return this->array(_::cpp_type<T>::id(m_world), array_count);
}
inline flecs::entity world::vector(flecs::entity_t elem_id) {
ecs_vector_desc_t desc = {};
desc.type = elem_id;
flecs::entity_t eid = ecs_vector_init(m_world, &desc);
ecs_assert(eid != 0, ECS_INVALID_OPERATION, NULL);
return flecs::entity(m_world, eid);
}
template <typename T>
inline flecs::entity world::vector() {
return this->vector(_::cpp_type<T>::id());
}
} // namespace flecs } // namespace flecs
inline int ecs_meta_serializer_t::value(ecs_entity_t type, const void *v) const {
return this->value_(this, type, v);
}
template <typename T>
inline int ecs_meta_serializer_t::value(const T& v) const {
return this->value(flecs::_::cpp_type<T>::id(
const_cast<flecs::world_t*>(this->world)), &v);
}
inline int ecs_meta_serializer_t::member(const char *name) const {
return this->member_(this, name);
}
#endif #endif
#ifdef FLECS_UNITS #ifdef FLECS_UNITS
/** /**
@ -27693,8 +27984,6 @@ inline flecs::scoped_world world::scope() const {
/** @} */ /** @} */
extern "C" {
#endif // __cplusplus #endif // __cplusplus
#endif // FLECS_CPP #endif // FLECS_CPP
@ -27702,9 +27991,5 @@ extern "C" {
#endif #endif
#ifdef __cplusplus
}
#endif
#endif #endif