From bac9d797b9c806ba845e0869972f07c131c95962 Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 6 Aug 2024 16:05:29 -0500 Subject: [PATCH] fix entity gen comparison --- src/entity.c | 3 +- src/entity.h | 5 -- src/game.c | 113 +++++++++++++++++++++++++------------------ src/game.h | 1 + src/mixer.c | 2 +- src/renderer_d3d11.c | 1 + src/sys_win32.c | 4 +- src/user.c | 50 ++++++++++++------- src/user.h | 1 + src/work.c | 2 +- 10 files changed, 108 insertions(+), 74 deletions(-) diff --git a/src/entity.c b/src/entity.c index c894d57d..f355193f 100644 --- a/src/entity.c +++ b/src/entity.c @@ -64,6 +64,7 @@ struct entity *entity_alloc_unlinked(struct entity_store *store) /* Reuse from free list */ entity = entity_from_handle(store, store->first_free); handle = entity->handle; + ++handle.gen; store->first_free = entity->next_free; } else { /* 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) { if (handle.gen != 0 && handle.idx < store->count) { diff --git a/src/entity.h b/src/entity.h index c549c901..3ac87069 100644 --- a/src/entity.h +++ b/src/entity.h @@ -131,11 +131,6 @@ INLINE struct entity_handle entity_nil_handle(void) 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) { return a.gen == b.gen && a.idx == b.idx; diff --git a/src/game.c b/src/game.c index 36ebe59c..2d02a60a 100644 --- a/src/game.c +++ b/src/game.c @@ -95,6 +95,56 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena) 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 * ========================== */ @@ -165,47 +215,7 @@ INTERNAL void game_update(void) static b32 run = 0; if (!run) { run = 1; - - /* 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)); - } + spawn_test_entities(); } ++G.world.tick_id; @@ -237,12 +247,18 @@ INTERNAL void game_update(void) logf_info("Clearing level"); for (u64 i = 0; i < entities_array.count; ++i) { struct entity *ent = &entities_array.entities[i]; - if (ent->valid) { + if (ent->valid && !ent->root) { entity_release(G.world.entity_store, ent); } } } break; + /* Spawn test */ + case GAME_CMD_KIND_SPAWN_TEST: { + logf_info("Spawning (test)"); + spawn_test_entities(); + } break; + default: break; }; } @@ -255,6 +271,8 @@ INTERNAL void game_update(void) /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ + struct entity_handle root_handle = G.world.entity_store->root; + /* ========================== * * Update sprite * ========================== */ @@ -262,7 +280,7 @@ INTERNAL void game_update(void) /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++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); } } @@ -320,7 +338,7 @@ INTERNAL void game_update(void) /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++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); } } @@ -420,7 +438,7 @@ INTERNAL void game_update(void) /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++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); } } @@ -467,7 +485,7 @@ INTERNAL void game_update(void) /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++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); } } @@ -543,7 +561,7 @@ INTERNAL void game_update(void) /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++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); } } @@ -584,6 +602,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg) void game_get_latest_tick(struct world *dest) { + __prof; struct sys_lock lock = sys_mutex_lock_e(&G.published_tick_mutex); world_copy_replace(dest, &G.published_tick); sys_mutex_unlock(&lock); diff --git a/src/game.h b/src/game.h index cbb8186f..4d9c1f85 100644 --- a/src/game.h +++ b/src/game.h @@ -14,6 +14,7 @@ enum game_cmd_kind { /* Testing */ GAME_CMD_KIND_CLEAR_ALL, + GAME_CMD_KIND_SPAWN_TEST, GAME_CMD_KIND_COUNT }; diff --git a/src/mixer.c b/src/mixer.c index d8effc29..16448561 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -115,7 +115,7 @@ INTERNAL struct track *track_alloc_locked(struct sys_lock *lock, struct sound *s if (next_free) { next_free->prev = NULL; } - *track = (struct track) { 0 }; + *track = (struct track) { .gen = track->gen + 1 }; } else { /* Allocate new */ track = arena_push_zero(&G.track_arena, struct track); diff --git a/src/renderer_d3d11.c b/src/renderer_d3d11.c index ede613b3..f6997387 100644 --- a/src/renderer_d3d11.c +++ b/src/renderer_d3d11.c @@ -205,6 +205,7 @@ INTERNAL struct renderer_handle handle_alloc(void *data) slot = store->head_free; store->head_free = slot->next_free; slot->next_free = NULL; + ++slot->gen; } else { /* Or push onto arena */ if (store->count + 1 >= HANDLE_IDX_MAX) { diff --git a/src/sys_win32.c b/src/sys_win32.c index 2345d90b..0002b72b 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -1585,7 +1585,9 @@ INTERNAL struct win32_thread *win32_thread_alloc_locked(struct sys_lock *lock) if (G.threads_first_free) { t = G.threads_first_free; G.threads_first_free = t->next; - MEMZERO_STRUCT(t); + *t = (struct win32_thread) { + .gen = t->gen + 1 + }; } else { t = arena_push_zero(&G.threads_arena, struct win32_thread); t->gen = 1; diff --git a/src/user.c b/src/user.c index 51e1b68d..585cc512 100644 --- a/src/user.c +++ b/src/user.c @@ -84,6 +84,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = { /* Testing */ [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_F7] = USER_BIND_KIND_DEBUG_CAMERA, [SYS_BTN_F11] = USER_BIND_KIND_FULLSCREEN, @@ -443,26 +444,29 @@ INTERNAL void user_update(void) struct entity_array world_entities = entity_store_as_array(G.world.entity_store); u64 num_entities = min_u64(t0_entities.count, t1_entities.count); - for (u64 i = 0; i < num_entities; ++i) { - struct entity *e0 = &t0_entities.entities[i]; - struct entity *e1 = &t1_entities.entities[i]; - struct entity *e = &world_entities.entities[i]; - if (e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) { - e->xform = xform_lerp(e0->xform, e1->xform, tick_blend); - e->xform_world = xform_lerp(e0->xform_world, e1->xform_world, tick_blend); + { + __profscope(tick_blending); + for (u64 i = 0; i < num_entities; ++i) { + struct entity *e0 = &t0_entities.entities[i]; + struct entity *e1 = &t1_entities.entities[i]; + struct entity *e = &world_entities.entities[i]; + if (e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) { + e->xform = xform_lerp(e0->xform, e1->xform, tick_blend); + e->xform_world = xform_lerp(e0->xform_world, e1->xform_world, tick_blend); - e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend); - e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend); - e->player_acceleration = math_lerp(e0->player_acceleration, e1->player_acceleration, tick_blend); - e->focus = v2_lerp(e0->focus, e1->focus, tick_blend); + e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend); + e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend); + e->player_acceleration = math_lerp(e0->player_acceleration, e1->player_acceleration, tick_blend); + e->focus = v2_lerp(e0->focus, e1->focus, tick_blend); - e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend); - e->sprite_xform_world = xform_lerp(e0->sprite_xform_world, e1->sprite_xform_world, tick_blend); - e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend); - e->animation_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend)); + e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend); + e->sprite_xform_world = xform_lerp(e0->sprite_xform_world, e1->sprite_xform_world, tick_blend); + e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend); + e->animation_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend)); - e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend); - e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend); + e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend); + e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend); + } } } #else @@ -570,13 +574,23 @@ INTERNAL void user_update(void) /* Test clear world */ { 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) { .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) { G.debug_draw = !G.debug_draw; } diff --git a/src/user.h b/src/user.h index 4e92a9d7..b2f25ce6 100644 --- a/src/user.h +++ b/src/user.h @@ -22,6 +22,7 @@ enum user_bind_kind { /* Testing */ USER_BIND_KIND_DEBUG_CLEAR, + USER_BIND_KIND_DEBUG_SPAWN, USER_BIND_KIND_DEBUG_DRAW, USER_BIND_KIND_DEBUG_CAMERA, USER_BIND_KIND_FULLSCREEN, diff --git a/src/work.c b/src/work.c index 5d3c83a2..a57caa39 100644 --- a/src/work.c +++ b/src/work.c @@ -176,7 +176,7 @@ INTERNAL struct work *work_alloc_locked(struct sys_lock *lock) G.free_work_head = work->next_free; *work = (struct work) { .condition_variable_finished = work->condition_variable_finished, - .gen = work->gen + .gen = work->gen + 1 }; } else { /* Make new */