fix entity gen comparison
This commit is contained in:
parent
53ae299816
commit
bac9d797b9
@ -64,6 +64,7 @@ struct entity *entity_alloc_unlinked(struct entity_store *store)
|
|||||||
/* Reuse from free list */
|
/* Reuse from free list */
|
||||||
entity = entity_from_handle(store, store->first_free);
|
entity = entity_from_handle(store, store->first_free);
|
||||||
handle = entity->handle;
|
handle = entity->handle;
|
||||||
|
++handle.gen;
|
||||||
store->first_free = entity->next_free;
|
store->first_free = entity->next_free;
|
||||||
} else {
|
} else {
|
||||||
/* Make new */
|
/* Make new */
|
||||||
@ -122,7 +123,7 @@ struct entity_store *entity_get_store(struct entity *ent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a valid entity or nil entity. Always safe to read result, need to check `valid` to write. */
|
/* Returns a valid entity or read-only nil entity. Always safe to read result, need to check `valid` to write. */
|
||||||
struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle)
|
struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle)
|
||||||
{
|
{
|
||||||
if (handle.gen != 0 && handle.idx < store->count) {
|
if (handle.gen != 0 && handle.idx < store->count) {
|
||||||
|
|||||||
@ -131,11 +131,6 @@ INLINE struct entity_handle entity_nil_handle(void)
|
|||||||
return (struct entity_handle) { 0 };
|
return (struct entity_handle) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE b32 entity_handle_is_nil(struct entity_handle h)
|
|
||||||
{
|
|
||||||
return h.gen == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE b32 entity_handle_eq(struct entity_handle a, struct entity_handle b)
|
INLINE b32 entity_handle_eq(struct entity_handle a, struct entity_handle b)
|
||||||
{
|
{
|
||||||
return a.gen == b.gen && a.idx == b.idx;
|
return a.gen == b.gen && a.idx == b.idx;
|
||||||
|
|||||||
113
src/game.c
113
src/game.c
@ -95,6 +95,56 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Test
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
/* TODO: Remove this */
|
||||||
|
|
||||||
|
INTERNAL void spawn_test_entities(void)
|
||||||
|
{
|
||||||
|
/* Player ent */
|
||||||
|
struct entity *player_ent;
|
||||||
|
{
|
||||||
|
struct v2 pos = V2(1, 1);
|
||||||
|
struct v2 size = V2(1, 1);
|
||||||
|
f32 r = 0;
|
||||||
|
|
||||||
|
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||||
|
e->xform = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
|
|
||||||
|
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
||||||
|
e->sprite_span_name = STR("idle.unarmed");
|
||||||
|
//e->sprite_span_name = STR("idle.one_handed");
|
||||||
|
//e->sprite_span_name = STR("idle.two_handed");
|
||||||
|
|
||||||
|
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||||
|
e->player_max_speed = 4.f;
|
||||||
|
e->player_acceleration = 20.0f;
|
||||||
|
e->focus = V2(0, -1);
|
||||||
|
|
||||||
|
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
||||||
|
|
||||||
|
player_ent = e;
|
||||||
|
|
||||||
|
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Camera ent */
|
||||||
|
{
|
||||||
|
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||||
|
e->xform = XFORM_IDENT;
|
||||||
|
|
||||||
|
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
||||||
|
entity_enable_prop(e, ENTITY_PROP_CAMERA_ACTIVE);
|
||||||
|
e->camera_follow = player_ent->handle;
|
||||||
|
|
||||||
|
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
|
||||||
|
f32 height = (f32)DEFAULT_CAMERA_HEIGHT;
|
||||||
|
e->camera_quad_xform = XFORM_TRS(.s = V2(width, height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update
|
* Update
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -165,47 +215,7 @@ INTERNAL void game_update(void)
|
|||||||
static b32 run = 0;
|
static b32 run = 0;
|
||||||
if (!run) {
|
if (!run) {
|
||||||
run = 1;
|
run = 1;
|
||||||
|
spawn_test_entities();
|
||||||
/* Player ent */
|
|
||||||
struct entity *player_ent;
|
|
||||||
{
|
|
||||||
struct v2 pos = V2(1, 1);
|
|
||||||
struct v2 size = V2(1, 1);
|
|
||||||
f32 r = 0;
|
|
||||||
|
|
||||||
struct entity *e = entity_alloc_top(G.world.entity_store);
|
|
||||||
e->xform = XFORM_TRS(.t = pos, .r = r, .s = size);
|
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
|
||||||
e->sprite_span_name = STR("idle.unarmed");
|
|
||||||
//e->sprite_span_name = STR("idle.one_handed");
|
|
||||||
//e->sprite_span_name = STR("idle.two_handed");
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
|
||||||
e->player_max_speed = 4.f;
|
|
||||||
e->player_acceleration = 20.0f;
|
|
||||||
e->focus = V2(0, -1);
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
|
||||||
|
|
||||||
player_ent = e;
|
|
||||||
|
|
||||||
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Camera ent */
|
|
||||||
{
|
|
||||||
struct entity *e = entity_alloc_top(G.world.entity_store);
|
|
||||||
e->xform = XFORM_IDENT;
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_CAMERA_ACTIVE);
|
|
||||||
e->camera_follow = player_ent->handle;
|
|
||||||
|
|
||||||
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
|
|
||||||
f32 height = (f32)DEFAULT_CAMERA_HEIGHT;
|
|
||||||
e->camera_quad_xform = XFORM_TRS(.s = V2(width, height));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++G.world.tick_id;
|
++G.world.tick_id;
|
||||||
@ -237,12 +247,18 @@ INTERNAL void game_update(void)
|
|||||||
logf_info("Clearing level");
|
logf_info("Clearing level");
|
||||||
for (u64 i = 0; i < entities_array.count; ++i) {
|
for (u64 i = 0; i < entities_array.count; ++i) {
|
||||||
struct entity *ent = &entities_array.entities[i];
|
struct entity *ent = &entities_array.entities[i];
|
||||||
if (ent->valid) {
|
if (ent->valid && !ent->root) {
|
||||||
entity_release(G.world.entity_store, ent);
|
entity_release(G.world.entity_store, ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
/* Spawn test */
|
||||||
|
case GAME_CMD_KIND_SPAWN_TEST: {
|
||||||
|
logf_info("Spawning (test)");
|
||||||
|
spawn_test_entities();
|
||||||
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -255,6 +271,8 @@ INTERNAL void game_update(void)
|
|||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
struct entity_handle root_handle = G.world.entity_store->root;
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update sprite
|
* Update sprite
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -262,7 +280,7 @@ INTERNAL void game_update(void)
|
|||||||
/* Recalculate world xforms */
|
/* Recalculate world xforms */
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (ent->valid && !ent->parent.gen) {
|
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||||
recalculate_world_xforms_recurse(ent);
|
recalculate_world_xforms_recurse(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +338,7 @@ INTERNAL void game_update(void)
|
|||||||
/* Recalculate world xforms */
|
/* Recalculate world xforms */
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (ent->valid && !ent->parent.gen) {
|
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||||
recalculate_world_xforms_recurse(ent);
|
recalculate_world_xforms_recurse(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,7 +438,7 @@ INTERNAL void game_update(void)
|
|||||||
/* Recalculate world xforms */
|
/* Recalculate world xforms */
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (ent->valid && !ent->parent.gen) {
|
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||||
recalculate_world_xforms_recurse(ent);
|
recalculate_world_xforms_recurse(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,7 +485,7 @@ INTERNAL void game_update(void)
|
|||||||
/* Recalculate world xforms */
|
/* Recalculate world xforms */
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (ent->valid && !ent->parent.gen) {
|
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||||
recalculate_world_xforms_recurse(ent);
|
recalculate_world_xforms_recurse(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -543,7 +561,7 @@ INTERNAL void game_update(void)
|
|||||||
/* Recalculate world xforms */
|
/* Recalculate world xforms */
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (ent->valid && !ent->parent.gen) {
|
if (ent->valid && entity_handle_eq(ent->parent, root_handle)) {
|
||||||
recalculate_world_xforms_recurse(ent);
|
recalculate_world_xforms_recurse(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,6 +602,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
|
|||||||
|
|
||||||
void game_get_latest_tick(struct world *dest)
|
void game_get_latest_tick(struct world *dest)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.published_tick_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.published_tick_mutex);
|
||||||
world_copy_replace(dest, &G.published_tick);
|
world_copy_replace(dest, &G.published_tick);
|
||||||
sys_mutex_unlock(&lock);
|
sys_mutex_unlock(&lock);
|
||||||
|
|||||||
@ -14,6 +14,7 @@ enum game_cmd_kind {
|
|||||||
|
|
||||||
/* Testing */
|
/* Testing */
|
||||||
GAME_CMD_KIND_CLEAR_ALL,
|
GAME_CMD_KIND_CLEAR_ALL,
|
||||||
|
GAME_CMD_KIND_SPAWN_TEST,
|
||||||
|
|
||||||
GAME_CMD_KIND_COUNT
|
GAME_CMD_KIND_COUNT
|
||||||
};
|
};
|
||||||
|
|||||||
@ -115,7 +115,7 @@ INTERNAL struct track *track_alloc_locked(struct sys_lock *lock, struct sound *s
|
|||||||
if (next_free) {
|
if (next_free) {
|
||||||
next_free->prev = NULL;
|
next_free->prev = NULL;
|
||||||
}
|
}
|
||||||
*track = (struct track) { 0 };
|
*track = (struct track) { .gen = track->gen + 1 };
|
||||||
} else {
|
} else {
|
||||||
/* Allocate new */
|
/* Allocate new */
|
||||||
track = arena_push_zero(&G.track_arena, struct track);
|
track = arena_push_zero(&G.track_arena, struct track);
|
||||||
|
|||||||
@ -205,6 +205,7 @@ INTERNAL struct renderer_handle handle_alloc(void *data)
|
|||||||
slot = store->head_free;
|
slot = store->head_free;
|
||||||
store->head_free = slot->next_free;
|
store->head_free = slot->next_free;
|
||||||
slot->next_free = NULL;
|
slot->next_free = NULL;
|
||||||
|
++slot->gen;
|
||||||
} else {
|
} else {
|
||||||
/* Or push onto arena */
|
/* Or push onto arena */
|
||||||
if (store->count + 1 >= HANDLE_IDX_MAX) {
|
if (store->count + 1 >= HANDLE_IDX_MAX) {
|
||||||
|
|||||||
@ -1585,7 +1585,9 @@ INTERNAL struct win32_thread *win32_thread_alloc_locked(struct sys_lock *lock)
|
|||||||
if (G.threads_first_free) {
|
if (G.threads_first_free) {
|
||||||
t = G.threads_first_free;
|
t = G.threads_first_free;
|
||||||
G.threads_first_free = t->next;
|
G.threads_first_free = t->next;
|
||||||
MEMZERO_STRUCT(t);
|
*t = (struct win32_thread) {
|
||||||
|
.gen = t->gen + 1
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
t = arena_push_zero(&G.threads_arena, struct win32_thread);
|
t = arena_push_zero(&G.threads_arena, struct win32_thread);
|
||||||
t->gen = 1;
|
t->gen = 1;
|
||||||
|
|||||||
16
src/user.c
16
src/user.c
@ -84,6 +84,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
|||||||
/* Testing */
|
/* Testing */
|
||||||
|
|
||||||
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||||
|
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
|
||||||
[SYS_BTN_F6] = USER_BIND_KIND_DEBUG_DRAW,
|
[SYS_BTN_F6] = USER_BIND_KIND_DEBUG_DRAW,
|
||||||
[SYS_BTN_F7] = USER_BIND_KIND_DEBUG_CAMERA,
|
[SYS_BTN_F7] = USER_BIND_KIND_DEBUG_CAMERA,
|
||||||
[SYS_BTN_F11] = USER_BIND_KIND_FULLSCREEN,
|
[SYS_BTN_F11] = USER_BIND_KIND_FULLSCREEN,
|
||||||
@ -443,6 +444,8 @@ INTERNAL void user_update(void)
|
|||||||
struct entity_array world_entities = entity_store_as_array(G.world.entity_store);
|
struct entity_array world_entities = entity_store_as_array(G.world.entity_store);
|
||||||
|
|
||||||
u64 num_entities = min_u64(t0_entities.count, t1_entities.count);
|
u64 num_entities = min_u64(t0_entities.count, t1_entities.count);
|
||||||
|
{
|
||||||
|
__profscope(tick_blending);
|
||||||
for (u64 i = 0; i < num_entities; ++i) {
|
for (u64 i = 0; i < num_entities; ++i) {
|
||||||
struct entity *e0 = &t0_entities.entities[i];
|
struct entity *e0 = &t0_entities.entities[i];
|
||||||
struct entity *e1 = &t1_entities.entities[i];
|
struct entity *e1 = &t1_entities.entities[i];
|
||||||
@ -465,6 +468,7 @@ INTERNAL void user_update(void)
|
|||||||
e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend);
|
e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
struct interp_ticks interp_ticks = pull_ticks(G.time);
|
struct interp_ticks interp_ticks = pull_ticks(G.time);
|
||||||
world_copy_replace(&G.world, interp_ticks.to_tick);
|
world_copy_replace(&G.world, interp_ticks.to_tick);
|
||||||
@ -570,13 +574,23 @@ INTERNAL void user_update(void)
|
|||||||
/* Test clear world */
|
/* Test clear world */
|
||||||
{
|
{
|
||||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
|
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
|
||||||
if (state.num_presses || state.is_held) {
|
if (state.num_presses) {
|
||||||
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
||||||
.kind = GAME_CMD_KIND_CLEAR_ALL
|
.kind = GAME_CMD_KIND_CLEAR_ALL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test spawn */
|
||||||
|
{
|
||||||
|
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
|
||||||
|
if (state.num_presses) {
|
||||||
|
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
||||||
|
.kind = GAME_CMD_KIND_SPAWN_TEST
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (G.bind_states[USER_BIND_KIND_DEBUG_DRAW].num_presses > 0) {
|
if (G.bind_states[USER_BIND_KIND_DEBUG_DRAW].num_presses > 0) {
|
||||||
G.debug_draw = !G.debug_draw;
|
G.debug_draw = !G.debug_draw;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ enum user_bind_kind {
|
|||||||
/* Testing */
|
/* Testing */
|
||||||
|
|
||||||
USER_BIND_KIND_DEBUG_CLEAR,
|
USER_BIND_KIND_DEBUG_CLEAR,
|
||||||
|
USER_BIND_KIND_DEBUG_SPAWN,
|
||||||
USER_BIND_KIND_DEBUG_DRAW,
|
USER_BIND_KIND_DEBUG_DRAW,
|
||||||
USER_BIND_KIND_DEBUG_CAMERA,
|
USER_BIND_KIND_DEBUG_CAMERA,
|
||||||
USER_BIND_KIND_FULLSCREEN,
|
USER_BIND_KIND_FULLSCREEN,
|
||||||
|
|||||||
@ -176,7 +176,7 @@ INTERNAL struct work *work_alloc_locked(struct sys_lock *lock)
|
|||||||
G.free_work_head = work->next_free;
|
G.free_work_head = work->next_free;
|
||||||
*work = (struct work) {
|
*work = (struct work) {
|
||||||
.condition_variable_finished = work->condition_variable_finished,
|
.condition_variable_finished = work->condition_variable_finished,
|
||||||
.gen = work->gen
|
.gen = work->gen + 1
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
/* Make new */
|
/* Make new */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user