tiles in progress

This commit is contained in:
jacob 2025-04-24 13:21:36 -05:00
parent f821ce6490
commit fc3c67b445
12 changed files with 241 additions and 45 deletions

View File

@ -36,8 +36,11 @@
#define USER_INTERP_ENABLED 1
/* 64^2 = 4096 bins */
#define SPACE_CELL_BINS_SQRT (64)
#define SPACE_CELL_SIZE 1.0f
#define SPACE_CELL_BINS_SQRT (64)
#define SPACE_CELL_SIZE (1.0f)
#define SIM_TILES_PER_UNIT_SQRT (2)
#define SIM_TILES_PER_CHUNK_SQRT (16)
#define SIM_TICKS_PER_SECOND 50
#define SIM_TIMESCALE 1

View File

@ -47,6 +47,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
res.a = arena_dry_push(arena, struct phys_collision_data);
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
struct space *space = ctx->sim_step_ctx->accel->space;
struct sim_ent_id local_player = ss->local_player;
struct sim_ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
u64 tick = ss->tick;
@ -93,7 +94,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
e1_collider = check0_collider;
}
struct sim_ent_id constraint_id = sim_ent_contact_constraint_id_from_contacting_ids(e0->id, e1->id);
struct sim_ent_id constraint_id = sim_ent_contact_constraint_id_from_contacting_ids(local_player, e0->id, e1->id);
struct sim_ent *constraint_ent = sim_ent_from_id(ss, constraint_id);
if (constraint_ent->valid) {

View File

@ -141,7 +141,8 @@ enum sim_control_flag {
SIM_CONTROL_FLAG_CLEAR_ALL = 1 << 2,
SIM_CONTROL_FLAG_SPAWN_TEST = 1 << 3,
SIM_CONTROL_FLAG_PAUSE = 1 << 4,
SIM_CONTROL_FLAG_STEP = 1 << 5
SIM_CONTROL_FLAG_STEP = 1 << 5,
SIM_CONTROL_FLAG_TILE_TEST = 1 << 6,
};
struct sim_control {
@ -157,6 +158,11 @@ enum sim_cmd_kind {
SIM_CMD_KIND_CHAT
};
enum sim_tile_kind {
SIM_TILE_KIND_NONE,
SIM_TILE_KIND_TEST
};
struct sim_ent_bin;
struct sim_snapshot {

View File

@ -3,9 +3,11 @@
#include "math.h"
#include "bitbuff.h"
#include "uid.h"
#include "rand.h"
/* Id magic number constants (to be used in conjunction with ent ids in deterministic id combinations) */
#define SIM_ENT_CONTACT_BASIS_ID (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
#define SIM_ENT_CONTACT_BASIS_UID (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
#define SIM_ENT_TILE_CHUNK_BASIS_UID (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
INTERNAL u32 index_from_ent(struct sim_snapshot *ss, struct sim_ent *ent)
{
@ -271,10 +273,23 @@ struct sim_ent_id sim_ent_random_id(void)
}
/* Returns the deterministic id of the contact constraint ent id that should be produced from e0 & e1 colliding */
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id id0, struct sim_ent_id id1)
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1)
{
struct sim_ent_id res = ZI;
res.uid = uid_combine(uid_combine(SIM_ENT_CONTACT_BASIS_ID, id0.uid), id1.uid);
res.uid = SIM_ENT_CONTACT_BASIS_UID;
res.uid = uid_combine(res.uid, player_id.uid);
res.uid = uid_combine(res.uid, id0.uid);
res.uid = uid_combine(res.uid, id1.uid);
return res;
}
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos)
{
struct sim_ent_id res = ZI;
res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID;
res.uid = uid_combine(res.uid, player_id.uid);
res.uid = uid_combine(res.uid, UID(rand_u64_from_seed(chunk_pos.x), rand_u64_from_seed(chunk_pos.y)));
return res;
}
@ -512,6 +527,25 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque)
ent->torque += torque;
}
/* ========================== *
* Tile chunk
* ========================== */
struct string sim_ent_get_tile_chunk_data(struct sim_ent *ent)
{
DEBUGBREAKABLE;
(UNUSED)ent;
struct string res = ZI;
return res;
}
void sim_ent_set_tile_chunk_data(struct sim_ent *ent, struct string data)
{
DEBUGBREAKABLE;
(UNUSED)ent;
(UNUSED)data;
}
/* ========================== *
* Ent lerp
* ========================== */

View File

@ -7,7 +7,7 @@
#include "phys.h"
#define SIM_ENT_NIL_ID ((struct sim_ent_id) { UID(0, 0) })
#define SIM_ENT_ROOT_ID ((struct sim_ent_id) { UID(0x66a36cc2bcc752da, 0x6c286c09b366eae6) })
#define SIM_ENT_ROOT_ID ((struct sim_ent_id) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
struct bitbuff_writer;
struct bitbuff_reader;
@ -24,6 +24,8 @@ enum sim_ent_prop {
SIM_ENT_PROP_CMD,
SIM_ENT_PROP_TILE_CHUNK,
SIM_ENT_PROP_PHYSICAL_DYNAMIC,
SIM_ENT_PROP_PHYSICAL_KINEMATIC,
@ -456,7 +458,8 @@ void sim_ent_activate(struct sim_ent *ent, u64 current_tick);
void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id);
struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id);
struct sim_ent_id sim_ent_random_id(void);
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id id0, struct sim_ent_id id1);
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos);
/* Query */
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop);
@ -481,6 +484,10 @@ void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force);
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
/* Tile chunk */
struct string sim_ent_get_tile_chunk_data(struct sim_ent *ent);
void sim_ent_set_tile_chunk_data(struct sim_ent *ent, struct string data);
/* Lerp */
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);

View File

@ -551,6 +551,37 @@ void sim_step(struct sim_step_ctx *ctx)
}
}
}
if (flags & SIM_CONTROL_FLAG_TILE_TEST) {
#if 0
if (is_master) {
struct v2 cursor_pos = player->player_cursor_pos;
/* FIXME: Negative indices */
struct v2i32 tile_pos = V2I32(cursor_pos.x * SIM_TILES_PER_UNIT_SQRT, cursor_pos.y * SIM_TILES_PER_UNIT_SQRT);
struct v2i32 chunk_pos = V2I32(tile_pos.x * SIM_TILES_PER_CHUNK_SQRT, tile_pos.y * SIM_TILES_PER_CHUNK_SQRT);
struct v2i32 tile_pos_in_chunk = V2I32(tile_pos.x % SIM_TILES_PER_CHUNK_SQRT, tile_pos.y % SIM_TILES_PER_CHUNK_SQRT);
struct sim_ent_id chunk_id = sim_ent_chunk_id_from_chunk_pos(player->id, chunk_pos);
struct sim_ent *chunk_ent = sim_ent_from_id(world, chunk_id);
if (!chunk_ent->valid) {
chunk_ent = sim_ent_alloc_sync_src_with_id(root, chunk_id);
sim_ent_enable_prop(chunk_ent, SIM_ENT_PROP_TILE_CHUNK);
}
struct string old_data = sim_ent_get_tile_chunk_data(chunk_ent);
struct string new_data = ZI;
new_data.len = SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT;
new_data.text = arena_push_array(scratch.arena, u8, new_data.len);
if (old_data.len == new_data.len) {
MEMCPY(new_data.text, old_data.text, new_data.len);
} else {
MEMZERO(new_data.text, new_data.len);
}
u64 tile_index = tile_pos_in_chunk.x + (tile_pos_in_chunk.y * SIM_TILES_PER_CHUNK_SQRT);
new_data.text[tile_index] = SIM_TILE_KIND_TEST;
sim_ent_set_tile_chunk_data(chunk_ent, new_data);
}
#endif
}
}
} break;

View File

@ -28,11 +28,11 @@
struct string string_from_char(struct arena *arena, char c)
{
u8 *dest = arena_push(arena, u8);
*dest = c;
u8 *dst = arena_push(arena, u8);
*dst = c;
return (struct string) {
.len = 1,
.text = dest
.text = dst
};
}
@ -592,8 +592,8 @@ struct string string_from_string16(struct arena *arena, struct string16 str16)
struct uni_decode_utf16_result decoded = uni_decode_utf16(str16_remaining);
struct uni_encode_utf8_result encoded = uni_encode_utf8(decoded.codepoint);
u8 *dest = arena_push_array(arena, u8, encoded.count8);
MEMCPY(dest, encoded.chars8, encoded.count8);
u8 *dst = arena_push_array(arena, u8, encoded.count8);
MEMCPY(dst, encoded.chars8, encoded.count8);
pos16 += decoded.advance16;
res.len += encoded.count8;
@ -616,8 +616,8 @@ struct string string_from_string32(struct arena *arena, struct string32 str32)
struct uni_decode_utf32_result decoded = uni_decode_utf32(str32_remaining);
struct uni_encode_utf8_result encoded = uni_encode_utf8(decoded.codepoint);
u8 *dest = arena_push_array(arena, u8, encoded.count8);
MEMCPY(dest, &encoded.chars8, encoded.count8);
u8 *dst = arena_push_array(arena, u8, encoded.count8);
MEMCPY(dst, &encoded.chars8, encoded.count8);
pos32 += 1;
res.len += encoded.count8;
@ -640,8 +640,8 @@ struct string16 string16_from_string(struct arena *arena, struct string str8)
struct uni_decode_utf8_result decoded = uni_decode_utf8(str8_remaining);
struct uni_encode_utf16_result encoded = uni_encode_utf16(decoded.codepoint);
u16 *dest = arena_push_array(arena, u16, encoded.count16);
MEMCPY(dest, encoded.chars16, (encoded.count16 << 1));
u16 *dst = arena_push_array(arena, u16, encoded.count16);
MEMCPY(dst, encoded.chars16, (encoded.count16 << 1));
pos8 += decoded.advance8;
res.len += encoded.count16;
@ -664,8 +664,8 @@ struct string32 string32_from_string(struct arena *arena, struct string str8)
struct uni_decode_utf8_result decoded = uni_decode_utf8(str8_remaining);
struct uni_encode_utf32_result encoded = uni_encode_utf32(decoded.codepoint);
u32 *dest = arena_push(arena, u32);
*dest = encoded.chars32;
u32 *dst = arena_push(arena, u32);
*dst = encoded.chars32;
pos8 += decoded.advance8;
res.len += 1;
@ -712,14 +712,14 @@ char *cstr_from_string(struct arena *arena, struct string src)
return (char *)text;
}
char *cstr_buff_from_string(struct string dest_buff, struct string src)
char *cstr_buff_from_string(struct string dst_buff, struct string src)
{
if (dest_buff.len > 0) {
u64 len = min_u64(src.len, dest_buff.len - 1);
MEMCPY(dest_buff.text, src.text, len);
dest_buff.text[len] = 0;
if (dst_buff.len > 0) {
u64 len = min_u64(src.len, dst_buff.len - 1);
MEMCPY(dst_buff.text, src.text, len);
dst_buff.text[len] = 0;
}
return (char *)dest_buff.text;
return (char *)dst_buff.text;
}
struct string string_from_cstr_no_limit(char *cstr)

View File

@ -37,6 +37,7 @@ struct win32_thread {
sys_thread_entry_point_func *entry_point;
void *thread_data;
char thread_name_cstr[256];
wchar_t thread_name_wstr[256];
struct win32_thread *next;
struct win32_thread *prev;
@ -1596,13 +1597,11 @@ struct win32_tls {
INTERNAL void win32_thread_set_tls(struct win32_tls *ctx)
{
/* TODO: Fail if error */
TlsSetValue(G.thread_tls_index, (LPVOID)ctx);
}
INTERNAL struct win32_tls *win32_thread_get_tls(void)
{
/* TODO: Fail if error */
return TlsGetValue(G.thread_tls_index);
}
@ -1688,16 +1687,11 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
win32_thread_set_tls(&tls);
/* Set thread name */
struct string thread_name = string_from_cstr_no_limit(t->thread_name_cstr);
if (thread_name.len > 0) {
/* FIXME: Don't use scratch arena here, to avoid scratch TLS being initialized for threads that don't need them otherwise */
struct temp_arena scratch = scratch_begin_no_conflict();
wchar_t *wc_thread_name = wstr_from_string(scratch.arena, thread_name);
SetThreadDescription(GetCurrentThread(), wc_thread_name);
scratch_end(scratch);
if (t->thread_name_wstr[0] != 0) {
SetThreadDescription(GetCurrentThread(), t->thread_name_wstr);
}
logf_info("New thread \"%F\" created with ID %F", FMT_STR(thread_name), FMT_UINT(sys_thread_id()));
logf_info("New thread \"%F\" created with ID %F", FMT_STR(string_from_cstr_no_limit(t->thread_name_cstr)), FMT_UINT(sys_thread_id()));
/* Enter thread entry point */
t->entry_point(t->thread_data);
@ -1714,6 +1708,7 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, void *thread_data, struct string thread_name)
{
__prof;
struct temp_arena scratch = scratch_begin_no_conflict();
ASSERT(entry_point != NULL);
logf_info("Creating thread \"%F\"", FMT_STR(thread_name));
@ -1725,7 +1720,17 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi
t->thread_data = thread_data;
/* Copy thread name to params */
cstr_buff_from_string(STRING_FROM_ARRAY(t->thread_name_cstr), thread_name);
{
u64 cstr_len = min_u64((ARRAY_COUNT(t->thread_name_cstr) - 1), thread_name.len);
MEMCPY(t->thread_name_cstr, thread_name.text, cstr_len * sizeof(*t->thread_name_cstr));
t->thread_name_cstr[cstr_len] = 0;
}
{
struct string16 thread_name16 = string16_from_string(scratch.arena, thread_name);
u64 wstr_len = min_u64((ARRAY_COUNT(t->thread_name_wstr) - 1), thread_name16.len);
MEMCPY(t->thread_name_wstr, thread_name16.text, wstr_len * sizeof(*t->thread_name_wstr));
t->thread_name_wstr[wstr_len] = 0;
}
t->handle = CreateThread(
NULL,
@ -1741,6 +1746,7 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi
}
res.handle = (u64)t;
scratch_end(scratch);
return res;
}

View File

@ -86,9 +86,10 @@ void *_thread_local_var_eval(struct thread_local_var_meta *meta)
}
}
/* Allocate var for thread if unallocated */
struct thread_local_store *t = sys_thread_get_thread_local_store();
void *data = t->lookup[id];
/* Allocate var for thread if unallocated */
if (!data) {
__profscope(_thread_local_var_eval__ALLOC);
/* Allocate */

View File

@ -10,11 +10,17 @@ struct uid uid_true_rand(void)
return res;
}
/* Commutatively combines 2 uids into a new uid */
/* Combines 2 uids into a new uid */
struct uid uid_combine(struct uid a, struct uid b)
{
struct uid res;
res.hi = rand_u64_from_seed(a.hi + b.hi);
res.lo = rand_u64_from_seed(a.lo + b.lo);
res.hi = (a.hi * 3) + b.hi;
res.lo = (a.lo * 3) + b.lo;
res.hi += res.lo;
res.lo += res.hi;
res.hi = rand_u64_from_seed(res.hi);
res.lo = rand_u64_from_seed(res.lo);
res.hi += res.lo;
res.lo += res.hi;
return res;
}

View File

@ -138,6 +138,8 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
/* Testing */
[SYS_BTN_M4] = USER_BIND_KIND_TILE_TEST,
[SYS_BTN_M2] = USER_BIND_KIND_DEBUG_DRAG,
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
@ -644,6 +646,7 @@ INTERNAL void user_update(void)
* Find local entities
* ========================== */
struct sim_ent *master_player = sim_ent_find_first_match_one(G.ss_blended, SIM_ENT_PROP_PLAYER_IS_MASTER);
struct sim_ent *local_player = sim_ent_from_id(G.ss_blended, G.ss_blended->local_player);
struct sim_ent *local_control = sim_ent_from_id(G.ss_blended, local_player->player_control_ent);
struct sim_ent *local_camera = sim_ent_from_id(G.ss_blended, local_player->player_camera_ent);
@ -744,7 +747,7 @@ INTERNAL void user_update(void)
f32 angle1 = rand_f64_from_seed(angle_seed1, 0, TAU);
struct v2 vec0 = v2_with_len(v2_from_angle(angle0), shake);
/* NOTE: vec1 not completely accurate since shake can change between frames, just a prediction */
/* NOTE: vec1 not completely accurate since shake can change between frames, it's just a prediction */
struct v2 vec1 = v2_with_len(v2_from_angle(angle1), shake);
/* TODO: Cubic interp? */
@ -884,11 +887,102 @@ INTERNAL void user_update(void)
draw_grid(G.world_cmd_buffer, RECT_FROM_V2(pos, size), color, thickness, spacing, offset);
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ========================== *
* Alloc / release tile cache entries
* ========================== */
/* Alloc entries from new sim chunks */
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
struct sim_ent *chunk_ent = &G.ss_blended->ents[ent_index];
if (sim_ent_is_valid_and_active(chunk_ent) && sim_ent_has_prop(chunk_ent, SIM_ENT_PROP_TILE_CHUNK)) {
struct user_tile_cache_entry *entry = user_tile_cache_entry_from_chunk_pos(chunk_ent->tile_chunk_pos);
if (!entry->valid) {
entry = user_tile_cache_entry_alloc(chunk_ent->tile_chunk_pos);
}
}
}
/* Release entries with invalid sim chunks */
for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) {
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
if (entry->valid) {
struct sim_ent *chunk_ent = sim_ent_from_chunk_pos(entry->pos);
if (!chunk_ent->valid) {
user_tile_cache_entry_release(entry);
}
}
}
/* ========================== *
* Sort entities
* Draw dirty tile cache entries
* ========================== */
for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) {
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
if (entry->valid) {
struct v2i32 chunk_pos = entry->pos;
struct sim_ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
if (entry->applied_dirty_gen != chunk_ent->dirty_gen) {
entry->applied_dirty_gen = chunk_ent->dirty_gen;
/* TODO: Autotiling */
struct string data = sim_ent_get_chunk_tile_data(chunk_ent);
u64 tile_count = data.len;
if (tile_count == SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT) {
for (u64 y_in_chunk = 0; y_in_chunk < SIM_TILES_PER_CHUNK_SQRT; ++y_in_chunk) {
for (u64 x_in_chunk = 0; x_in_chunk < SIM_TILES_PER_CHUNK_SQRT; ++x_in_chunk) {
}
}
} else {
/* TODO: Clear gpu buffer if it exists */
}
}
}
}
#if 0
for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) {
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
if (entry->valid) {
struct v2i32 chunk_pos = entry->pos;
struct sim_ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
if (entry->applied_dirty_gen != chunk_ent->dirty_gen) {
entry->applied_dirty_gen = chunk_ent->dirty_gen;
/* Retreive surrounding chunk info since we're auto-tiling
* [TL] [T] [TR]
* [L ] X [R ]
* [BL] [B] [BR]
*/
struct v2i32 chunk_pos_tl = V2I32(chunk_pos.x - 1, chunk_pos.y - 1);
struct v2i32 chunk_pos_t = V2I32(chunk_pos.x, chunk_pos.y - 1);
struct v2i32 chunk_pos_tr = V2I32(chunk_pos.x + 1, chunk_pos.y - 1);
struct v2i32 chunk_pos_l = V2I32(chunk_pos.x - 1, chunk_pos.y);
struct v2i32 chunk_pos_r = V2I32(chunk_pos.x + 1, chunk_pos.y);
struct v2i32 chunk_pos_bl = V2I32(chunk_pos.x - 1, chunk_pos.y + 1);
struct v2i32 chunk_pos_b = V2I32(chunk_pos.x, chunk_pos.y + 1);
struct v2i32 chunk_pos_br = V2I32(chunk_pos.x + 1, chunk_pos.y + 1);
struct sim_ent *chunk_ent_tl = sim_ent_from_chunk_pos(chunk_pos_tl);
struct sim_ent *chunk_ent_t = sim_ent_from_chunk_pos(chunk_pos_t);
struct sim_ent *chunk_ent_tr = sim_ent_from_chunk_pos(chunk_pos_tr);
struct sim_ent *chunk_ent_l = sim_ent_from_chunk_pos(chunk_pos_l);
struct sim_ent *chunk_ent_r = sim_ent_from_chunk_pos(chunk_pos_r);
struct sim_ent *chunk_ent_bl = sim_ent_from_chunk_pos(chunk_pos_bl);
struct sim_ent *chunk_ent_b = sim_ent_from_chunk_pos(chunk_pos_b);
struct sim_ent *chunk_ent_br = sim_ent_from_chunk_pos(chunk_pos_br);
struct string data = sim_ent_get_chunk_tile_data(chunk_ent);
//for (u64 x = 0; x <
}
}
}
#endif
/* ========================== *
* Sort drawable entities
* ========================== */
struct sim_ent **sorted = arena_dry_push(scratch.arena, struct sim_ent *);
@ -1491,6 +1585,7 @@ INTERNAL void user_update(void)
struct bind_state pause_state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
struct bind_state spawn_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
struct bind_state tile_state = G.bind_states[USER_BIND_KIND_TILE_TEST];
if (fire_state.num_presses || fire_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_FIRE;
@ -1510,6 +1605,9 @@ INTERNAL void user_update(void)
if (spawn_state.num_presses) {
control.flags |= SIM_CONTROL_FLAG_SPAWN_TEST;
}
if (tile_state.num_presses) {
control.flags |= SIM_CONTROL_FLAG_TILE_TEST;
}
/* Set user sim control */
{

View File

@ -25,6 +25,9 @@ enum user_bind_kind {
USER_BIND_KIND_FIRE,
/* Testing */
USER_BIND_KIND_TILE_TEST,
USER_BIND_KIND_DEBUG_CLEAR,
USER_BIND_KIND_DEBUG_SPAWN,
USER_BIND_KIND_DEBUG_FOLLOW,