player focus dir relative to player. raw mouse input. crosshair.

This commit is contained in:
jacob 2024-03-13 21:44:25 -05:00
parent aa8dd7a4fa
commit bdd8db60c3
18 changed files with 388 additions and 183 deletions

BIN
res/graphics/crosshair.ase (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -32,7 +32,6 @@ INTERNAL u32 peek_bits(struct bitbuf *bb, u32 nbits)
val32 &= U32_MAX >> (32 - nbits); val32 &= U32_MAX >> (32 - nbits);
return val32; return val32;
} }
INTERNAL u32 consume_bits(struct bitbuf *bb, u32 nbits) INTERNAL u32 consume_bits(struct bitbuf *bb, u32 nbits)

View File

@ -7,10 +7,7 @@
#define PIXELS_PER_UNIT 256 #define PIXELS_PER_UNIT 256
#define AUDIO_ENABLED 0 #define GAME_FPS 50
#define VSYNC_ENABLED 0
#define GAME_FPS 30
#define USER_FRAME_LIMIT 300 #define USER_FRAME_LIMIT 300
@ -18,4 +15,16 @@
* Delay ms = USER_INTERP_OFFSET_TICK_RATIO * Game tick rate * Delay ms = USER_INTERP_OFFSET_TICK_RATIO * Game tick rate
* E.g: At 1.5, the user thread will render 49.5ms back in time (if game thread runs at 30FPS) * E.g: At 1.5, the user thread will render 49.5ms back in time (if game thread runs at 30FPS)
*/ */
#define USER_INTERP_OFFSET_TICK_RATIO 1.5 #define USER_INTERP_OFFSET_TICK_RATIO 1.2
/* ========================== *
* Settings
* ========================== */
/* TODO: Move these to user-configurable settings */
#define AUDIO_ENABLED 0
#define VSYNC_ENABLED 0
#define MOUSE_SENSITIVITY 1.5

View File

@ -295,13 +295,13 @@ void draw_text_ex(struct renderer_canvas *canvas, struct font *font, struct v2 p
struct clip_rect clip = { struct clip_rect clip = {
{ {
glyph->atlas_rect.x / font->texture.width, glyph->atlas_rect.x / font->texture.size.x,
glyph->atlas_rect.y / font->texture.height glyph->atlas_rect.y / font->texture.size.y
}, },
{ {
(glyph->atlas_rect.x + glyph->atlas_rect.width) / font->texture.width, (glyph->atlas_rect.x + glyph->atlas_rect.width) / font->texture.size.x,
(glyph->atlas_rect.y + glyph->atlas_rect.height) / font->texture.height (glyph->atlas_rect.y + glyph->atlas_rect.height) / font->texture.size.y
} }
}; };

View File

@ -63,11 +63,18 @@ void entity_release(struct entity_store *store, struct entity *entity)
store->first_free = handle; store->first_free = handle;
} }
/* ========================== * /* ========================== *
* Lookup * Query
* ========================== */ * ========================== */
struct entity_array entity_store_as_array(struct entity_store *store)
{
return (struct entity_array) {
.entities = (struct entity *)store->arena.base,
.count = store->count
};
}
/* Returns a valid entity or nil entity. Always safe to read result, need to check to write. */ /* Returns a valid entity or nil entity. Always safe to read result, need to check 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)
{ {
@ -81,6 +88,22 @@ struct entity *entity_from_handle(struct entity_store *store, struct entity_hand
return entity_nil(); return entity_nil();
} }
struct entity *entity_find_first_with_prop(struct entity_store *store, enum entity_prop prop)
{
struct entity_array entities_array = entity_store_as_array(store);
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
struct entity *ent = &entities_array.entities[entity_index];
if (ent->valid && entity_has_prop(ent, prop)) {
return ent;
}
}
return entity_nil();
}
/* ========================== *
* Tree
* ========================== */
void entity_link(struct entity_store *store, struct entity *parent, struct entity *child) void entity_link(struct entity_store *store, struct entity *parent, struct entity *child)
{ {
struct entity *first_child = entity_from_handle(store, parent->first); struct entity *first_child = entity_from_handle(store, parent->first);

View File

@ -14,7 +14,6 @@ enum entity_prop {
/* Test props */ /* Test props */
ENTITY_PROP_TEST, ENTITY_PROP_TEST,
ENTITY_PROP_TEST_FOLLOW_MOUSE,
ENTITY_PROP_TEST_SOUND_EMITTER, ENTITY_PROP_TEST_SOUND_EMITTER,
ENTITY_PROP_COUNT ENTITY_PROP_COUNT
@ -60,6 +59,7 @@ struct entity {
/* ENTITY_PROP_PLAYER_CONTROLLED */ /* ENTITY_PROP_PLAYER_CONTROLLED */
f32 player_max_speed; f32 player_max_speed;
f32 player_acceleration; f32 player_acceleration;
struct v2 player_focus_dir;
/* ====================================================================== */ /* ====================================================================== */
/* Sprite */ /* Sprite */
@ -146,7 +146,11 @@ void entity_store_copy_replace(struct entity_store *dest, struct entity_store *s
/* Entity */ /* Entity */
struct entity *entity_alloc(struct entity_store *store); struct entity *entity_alloc(struct entity_store *store);
void entity_release(struct entity_store *store, struct entity *entity); void entity_release(struct entity_store *store, struct entity *entity);
struct entity_array entity_store_as_array(struct entity_store *store);
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);
struct entity *entity_find_first_with_prop(struct entity_store *store, enum entity_prop prop);
void entity_link(struct entity_store *store, struct entity *parent, struct entity *child); void entity_link(struct entity_store *store, struct entity *parent, struct entity *child);
#endif #endif

View File

@ -119,8 +119,7 @@ INTERNAL void font_load_asset_task(void *vparams)
/* Set font data */ /* Set font data */
font->texture = (struct texture) { font->texture = (struct texture) {
.renderer_handle = texture_renderer_handle, .renderer_handle = texture_renderer_handle,
.width = result.image_data.width, .size = V2(result.image_data.width, result.image_data.height),
.height = result.image_data.height
}; };
font->glyphs_count = result.glyphs_count; font->glyphs_count = result.glyphs_count;
font->point_size = point_size; font->point_size = point_size;

View File

@ -121,6 +121,7 @@ INTERNAL void game_update(void)
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
e->player_max_speed = 5.f; e->player_max_speed = 5.f;
e->player_acceleration = 15.0f; e->player_acceleration = 15.0f;
e->player_focus_dir = V2(0, -1);
entity_enable_prop(e, ENTITY_PROP_ANIMATING); entity_enable_prop(e, ENTITY_PROP_ANIMATING);
@ -180,7 +181,7 @@ INTERNAL void game_update(void)
entity_link(&L.world.entity_store, parent, e); entity_link(&L.world.entity_store, parent, e);
if (sys_rand_u32() % 2 == 0) { if (sys_rand_u32() % 2 == 0) {
u64 parent_idx = sys_rand_u32() % world_get_entities(&L.world).count; u64 parent_idx = sys_rand_u32() % entity_store_as_array(&L.world.entity_store).count;
struct entity *rand_ent = entity_from_handle(&L.world.entity_store, (struct entity_handle) { .idx = parent_idx, .gen = 1 }); struct entity *rand_ent = entity_from_handle(&L.world.entity_store, (struct entity_handle) { .idx = parent_idx, .gen = 1 });
if (rand_ent->valid) { if (rand_ent->valid) {
parent = rand_ent; parent = rand_ent;
@ -208,13 +209,13 @@ INTERNAL void game_update(void)
L.world.tick_ts = sys_timestamp(); L.world.tick_ts = sys_timestamp();
L.world.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.world.timescale); L.world.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.world.timescale);
L.world.time += L.world.dt; L.world.time += L.world.dt;
struct entity_array entities_array = world_get_entities(&L.world); struct entity_array entities_array = entity_store_as_array(&L.world.entity_store);
/* ========================== * /* ========================== *
* Process game cmds * Process game cmds
* ========================== */ * ========================== */
L.world.player_move_dir = V2(0, 0); L.world.player_focus_move_dir = V2(0, 0);
struct game_cmd_array game_cmds = pop_cmds(scratch.arena); struct game_cmd_array game_cmds = pop_cmds(scratch.arena);
for (u64 cmd_index = 0; cmd_index < game_cmds.count; ++cmd_index) { for (u64 cmd_index = 0; cmd_index < game_cmds.count; ++cmd_index) {
@ -223,13 +224,8 @@ INTERNAL void game_update(void)
switch (cmd.kind) { switch (cmd.kind) {
/* Movement */ /* Movement */
case GAME_CMD_KIND_PLAYER_MOVE: { case GAME_CMD_KIND_PLAYER_MOVE: {
struct v2 dir = cmd.dir; L.world.player_move_dir = cmd.move_dir;
L.world.player_move_dir = v2_add(L.world.player_move_dir, dir); L.world.player_focus_move_dir = v2_add(L.world.player_focus_move_dir, cmd.focus_move_dir);
} break;
/* Focus */
case GAME_CMD_KIND_PLAYER_FOCUS: {
L.world.player_focus = cmd.pos;
} break; } break;
/* Clear level */ /* Clear level */
@ -361,26 +357,20 @@ INTERNAL void game_update(void)
} }
/* ========================== * /* ========================== *
* Player look direction * Player focus
* ========================== */ * ========================== */
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
/* Update focus */
ent->player_focus_dir = v2_add(ent->player_focus_dir, L.world.player_focus_move_dir);
/* Update view angle */
struct v2 ent_pos = ent->rel_xform.og; struct v2 ent_pos = ent->rel_xform.og;
struct v2 look_pos = L.world.player_focus; struct v2 look_pos = v2_add(ent_pos, ent->player_focus_dir);
f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2; f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2;
ent->rel_xform = xform_with_rotation(ent->rel_xform, r); ent->rel_xform = xform_with_rotation(ent->rel_xform, r);
} }
/* ========================== *
* Update position from mouse
* ========================== */
/* ENTITY_PROP_TEST_FOLLOW_MOUSE */
if (entity_has_prop(ent, ENTITY_PROP_TEST_FOLLOW_MOUSE)) {
ent->rel_xform.og = L.world.player_focus;
ent->test_start_rel_xform.og = L.world.player_focus;
}
/* ========================== * /* ========================== *
* Calculate xforms * Calculate xforms
* ========================== */ * ========================== */

View File

@ -7,7 +7,6 @@ enum game_cmd_kind {
GAME_CMD_KIND_NONE, GAME_CMD_KIND_NONE,
GAME_CMD_KIND_PLAYER_MOVE, GAME_CMD_KIND_PLAYER_MOVE,
GAME_CMD_KIND_PLAYER_FOCUS,
/* Testing */ /* Testing */
GAME_CMD_KIND_CLEAR_ALL, GAME_CMD_KIND_CLEAR_ALL,
@ -19,10 +18,8 @@ struct game_cmd {
enum game_cmd_kind kind; enum game_cmd_kind kind;
/* GAME_CMD_KIND_PLAYER_MOVE */ /* GAME_CMD_KIND_PLAYER_MOVE */
struct v2 dir; struct v2 move_dir;
struct v2 focus_move_dir;
/* GAME_CMD_KIND_PLAYER_FOCUS */
struct v2 pos;
}; };
struct game_cmd_array { struct game_cmd_array {

View File

@ -323,6 +323,22 @@ INLINE struct v2 v2_round(struct v2 a)
); );
} }
INLINE struct v2 v2_floor(struct v2 a)
{
return V2(
(f32)math_floor(a.x),
(f32)math_floor(a.y)
);
}
INLINE struct v2 v2_ceil(struct v2 a)
{
return V2(
(f32)math_ceil(a.x),
(f32)math_ceil(a.y)
);
}
INLINE f32 v2_dot(struct v2 a, struct v2 b) INLINE f32 v2_dot(struct v2 a, struct v2 b)
{ {
return a.x * b.x + a.y * b.y; return a.x * b.x + a.y * b.y;
@ -751,4 +767,24 @@ INLINE struct quad quad_mul_xform(struct quad quad, struct xform m)
}; };
} }
INLINE struct quad quad_round(struct quad quad)
{
return (struct quad) {
v2_round(quad.p1),
v2_round(quad.p2),
v2_round(quad.p3),
v2_round(quad.p4)
};
}
INLINE struct quad quad_floor(struct quad quad)
{
return (struct quad) {
v2_floor(quad.p1),
v2_round(quad.p2),
v2_round(quad.p3),
v2_round(quad.p4)
};
}
#endif #endif

View File

@ -13,10 +13,9 @@ enum sys_event_kind {
SYS_EVENT_KIND_BUTTON_DOWN, SYS_EVENT_KIND_BUTTON_DOWN,
SYS_EVENT_KIND_BUTTON_UP, SYS_EVENT_KIND_BUTTON_UP,
//SYS_EVENT_KIND_MOUSE_MOVE, SYS_EVENT_KIND_MOUSE_MOVE,
SYS_EVENT_KIND_RAW_MOUSE_MOVE,
SYS_EVENT_KIND_TEXT, SYS_EVENT_KIND_TEXT,
SYS_EVENT_KIND_QUIT, SYS_EVENT_KIND_QUIT,
SYS_EVENT_KIND_COUNT SYS_EVENT_KIND_COUNT
@ -134,7 +133,10 @@ struct sys_event {
u32 text_character; u32 text_character;
struct v2 position; struct v2 mouse_position;
struct v2 mouse_delta;
struct v2 raw_mouse_delta;
}; };
struct sys_event_array { struct sys_event_array {
@ -276,14 +278,18 @@ struct sys_window_settings sys_window_get_settings(struct sys_window *sys_window
void sys_window_show(struct sys_window *sys_window); void sys_window_show(struct sys_window *sys_window);
void sys_window_set_cursor_pos(struct sys_window *sys_window, struct v2 pos);
struct v2 sys_window_get_size(struct sys_window *sys_window); struct v2 sys_window_get_size(struct sys_window *sys_window);
struct v2 sys_window_get_monitor_size(struct sys_window *sys_window); struct v2 sys_window_get_monitor_size(struct sys_window *sys_window);
struct v2 sys_window_get_mouse_pos(struct sys_window *sys_window);
/* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */ /* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */
u64 sys_window_get_internal_handle(struct sys_window *sys_window); u64 sys_window_get_internal_handle(struct sys_window *sys_window);
void sys_window_cursor_set_pos(struct sys_window *sys_window, struct v2 pos);
void sys_window_cursor_show(struct sys_window *sys_window);
void sys_window_cursor_hide(struct sys_window *sys_window);
/* ========================== * /* ========================== *
* Mutex * Mutex
* ========================== */ * ========================== */

View File

@ -11,6 +11,7 @@
#include "util.h" #include "util.h"
#include <Windows.h> #include <Windows.h>
#include <windowsx.h>
#include <ShlObj_core.h> #include <ShlObj_core.h>
#include <fileapi.h> #include <fileapi.h>
#include <dwmapi.h> #include <dwmapi.h>
@ -31,13 +32,21 @@ struct win32_condition_variable {
struct win32_condition_variable *next_free; struct win32_condition_variable *next_free;
}; };
enum win32_window_cursor_set_flag {
WIN32_WINDOW_CURSOR_SET_FLAG_NONE = 0x0,
WIN32_WINDOW_CURSOR_SET_FLAG_POSITION = 0x1,
WIN32_WINDOW_CURSOR_SET_FLAG_HIDE = 0x2,
WIN32_WINDOW_CURSOR_SET_FLAG_SHOW = 0x4
};
struct win32_window { struct win32_window {
u32 flags; u32 flags;
HWND hwnd; HWND hwnd;
u32 tid;
struct sync_flag ready_sf; struct sync_flag ready_sf;
struct sys_mutex settings_mutex; struct sys_rw_mutex settings_rw_mutex;
struct sys_window_settings settings; struct sys_window_settings settings;
i32 monitor_width; i32 monitor_width;
@ -48,6 +57,10 @@ struct win32_window {
* their pre-minimized values) */ * their pre-minimized values) */
i32 x, y, width, height; i32 x, y, width, height;
struct v2 cursor_pos;
u32 cursor_set_flags;
struct v2 cursor_set_position;
b32 event_thread_shutdown; b32 event_thread_shutdown;
struct sys_thread event_thread; struct sys_thread event_thread;
@ -489,13 +502,13 @@ INTERNAL void win32_update_window_from_system(struct win32_window *window);
INTERNAL void win32_window_process_event(struct win32_window *window, struct sys_event event) INTERNAL void win32_window_process_event(struct win32_window *window, struct sys_event event)
{ {
sys_mutex_lock(&window->event_callbacks_mutex);
{ {
sys_mutex_lock(&window->event_callbacks_mutex);
for (u64 i = 0; i < window->event_callbacks_count; ++i) { for (u64 i = 0; i < window->event_callbacks_count; ++i) {
window->event_callbacks[i](event); window->event_callbacks[i](event);
} }
sys_mutex_unlock(&window->event_callbacks_mutex);
} }
sys_mutex_unlock(&window->event_callbacks_mutex);
} }
INTERNAL HWND win32_create_window(struct win32_window *window) INTERNAL HWND win32_create_window(struct win32_window *window)
@ -541,6 +554,7 @@ INTERNAL void window_thread_entry_point(void *arg)
/* Win32 limitation: Window must be initialized on same thread that processes events */ /* Win32 limitation: Window must be initialized on same thread that processes events */
window->hwnd = win32_create_window(window); window->hwnd = win32_create_window(window);
window->tid = sys_thread_id();
win32_update_window_from_system(window); win32_update_window_from_system(window);
BringWindowToTop(window->hwnd); BringWindowToTop(window->hwnd);
@ -561,9 +575,33 @@ INTERNAL void window_thread_entry_point(void *arg)
} break; } break;
} }
/* TODO: update mouse pos w/ GetCursorPos */ /* Update cursor */
if (GetFocus() == window->hwnd) {
u32 cursor_flags = window->cursor_set_flags;
/* Hide cursor */
if (cursor_flags & WIN32_WINDOW_CURSOR_SET_FLAG_HIDE) {
while(ShowCursor(false) >= 0);
}
/* Show cursor */
if (cursor_flags & WIN32_WINDOW_CURSOR_SET_FLAG_SHOW) {
while(ShowCursor(true) < 0);
}
/* Update position */
if (cursor_flags & WIN32_WINDOW_CURSOR_SET_FLAG_POSITION) {
struct v2 window_space_pos = window->cursor_set_position;
POINT p = { window_space_pos.x, window_space_pos.y };
ClientToScreen(window->hwnd, &p);
SetCursorPos(p.x, p.y);
}
window->cursor_set_flags = 0;
}
} }
/* Destroy window hwnd */ /* Destroy window hwnd */
DestroyWindow(window->hwnd); DestroyWindow(window->hwnd);
} }
@ -588,7 +626,7 @@ INTERNAL struct win32_window *win32_window_alloc(void)
window->ready_sf = sync_flag_alloc(); window->ready_sf = sync_flag_alloc();
/* Allocate mutexes */ /* Allocate mutexes */
window->settings_mutex = sys_mutex_alloc(); window->settings_rw_mutex = sys_rw_mutex_alloc();
window->event_callbacks_mutex = sys_mutex_alloc(); window->event_callbacks_mutex = sys_mutex_alloc();
/* Start window thread for processing events */ /* Start window thread for processing events */
@ -613,7 +651,7 @@ INTERNAL void win32_window_release(struct win32_window *window)
/* Release mutexes */ /* Release mutexes */
sys_mutex_release(&window->event_callbacks_mutex); sys_mutex_release(&window->event_callbacks_mutex);
sys_mutex_release(&window->settings_mutex); sys_rw_mutex_release(&window->settings_rw_mutex);
/* Release sync flag */ /* Release sync flag */
sync_flag_release(&window->ready_sf); sync_flag_release(&window->ready_sf);
@ -729,17 +767,10 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str
SetWindowTextA(hwnd, settings->title); SetWindowTextA(hwnd, settings->title);
} }
INTERNAL struct v2 win32_window_get_mouse_pos(struct win32_window *window) INTERNAL void win32_window_wake(struct win32_window *window)
{ {
HWND hwnd = window->hwnd; /* Post a blank message to the window's thread message queue to wake it. */
PostThreadMessageA(window->tid, 0, 0, 0);
struct v2 res = V2(0, 0);
POINT p;
if (GetCursorPos(&p) && ScreenToClient(hwnd, &p)) {
res = V2(p.x, p.y);
}
return res;
} }
INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@ -867,7 +898,7 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
(struct sys_event) { (struct sys_event) {
.kind = event_kind, .kind = event_kind,
.button = button, .button = button,
.position = win32_window_get_mouse_pos(window) .mouse_position = window->cursor_pos
} }
); );
} }
@ -885,6 +916,53 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
} }
} break; } break;
/* Mouse move */
case WM_MOUSEMOVE: {
i32 x = GET_X_LPARAM(lparam);
i32 y = GET_Y_LPARAM(lparam);
struct v2 old = window->cursor_pos;
window->cursor_pos = V2(x, y);
struct v2 delta = v2_sub(window->cursor_pos, old);
win32_window_process_event(
window,
(struct sys_event) {
.kind = SYS_EVENT_KIND_MOUSE_MOVE,
.mouse_position = window->cursor_pos,
.mouse_delta = delta
}
);
} break;
/* Raw mouse move */
case WM_INPUT: {
struct temp_arena scratch = scratch_begin_no_conflict();
/* Read raw input buffer */
UINT buff_size;
GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &buff_size, sizeof(RAWINPUTHEADER));
u8 *buff = arena_push_array_zero(scratch.arena, u8, buff_size);
if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buff, &buff_size, sizeof(RAWINPUTHEADER)) != buff_size) {
logf_error("GetRawInputData did not return correct size");
break;
}
RAWINPUT *raw = (RAWINPUT *)buff;
if (raw->header.dwType == RIM_TYPEMOUSE) {
i32 x = raw->data.mouse.lLastX;
i32 y = raw->data.mouse.lLastY;
struct v2 delta = V2(x, y);
win32_window_process_event(
window,
(struct sys_event) {
.kind = SYS_EVENT_KIND_RAW_MOUSE_MOVE,
.raw_mouse_delta = delta
}
);
}
scratch_end(scratch);
} break;
default: { default: {
result = DefWindowProcA(hwnd, msg, wparam, lparam); result = DefWindowProcA(hwnd, msg, wparam, lparam);
@ -930,7 +1008,6 @@ void sys_window_unregister_event_callback(struct sys_window *sys_window, sys_win
sys_mutex_lock(&window->event_callbacks_mutex); sys_mutex_lock(&window->event_callbacks_mutex);
{ {
u64 count = window->event_callbacks_count; u64 count = window->event_callbacks_count;
sys_window_event_callback_func *last = count > 0 ? window->event_callbacks[count - 1] : NULL; sys_window_event_callback_func *last = count > 0 ? window->event_callbacks[count - 1] : NULL;
@ -951,11 +1028,11 @@ void sys_window_update_settings(struct sys_window *sys_window, struct sys_window
{ {
__prof; __prof;
struct win32_window *window = (struct win32_window *)sys_window->handle; struct win32_window *window = (struct win32_window *)sys_window->handle;
sys_mutex_lock(&window->settings_mutex); sys_rw_mutex_lock_exclusive(&window->settings_rw_mutex);
{ {
win32_update_window_from_settings(window, settings); win32_update_window_from_settings(window, settings);
} }
sys_mutex_unlock(&window->settings_mutex); sys_rw_mutex_unlock_exclusive(&window->settings_rw_mutex);
} }
/* TODO: Lock settings mutex for these functions */ /* TODO: Lock settings mutex for these functions */
@ -970,7 +1047,7 @@ void sys_window_show(struct sys_window *sys_window)
{ {
struct win32_window *window = (struct win32_window *)sys_window->handle; struct win32_window *window = (struct win32_window *)sys_window->handle;
HWND hwnd = window->hwnd; HWND hwnd = window->hwnd;
sys_mutex_lock(&window->settings_mutex); sys_rw_mutex_lock_exclusive(&window->settings_rw_mutex);
{ {
i32 show_cmd = SW_NORMAL; i32 show_cmd = SW_NORMAL;
struct sys_window_settings *settings = &window->settings; struct sys_window_settings *settings = &window->settings;
@ -983,7 +1060,7 @@ void sys_window_show(struct sys_window *sys_window)
ShowWindow(hwnd, show_cmd); ShowWindow(hwnd, show_cmd);
BringWindowToTop(hwnd); BringWindowToTop(hwnd);
} }
sys_mutex_unlock(&window->settings_mutex); sys_rw_mutex_unlock_exclusive(&window->settings_rw_mutex);
} }
struct v2 sys_window_get_size(struct sys_window *sys_window) struct v2 sys_window_get_size(struct sys_window *sys_window)
@ -998,18 +1075,34 @@ struct v2 sys_window_get_monitor_size(struct sys_window *sys_window)
return V2((f32)window->monitor_width, (f32)window->monitor_height); return V2((f32)window->monitor_width, (f32)window->monitor_height);
} }
struct v2 sys_window_get_mouse_pos(struct sys_window *sys_window)
{
struct win32_window *window = (struct win32_window *)sys_window->handle;
return win32_window_get_mouse_pos(window);
}
u64 sys_window_get_internal_handle(struct sys_window *sys_window) u64 sys_window_get_internal_handle(struct sys_window *sys_window)
{ {
struct win32_window *window = (struct win32_window *)sys_window->handle; struct win32_window *window = (struct win32_window *)sys_window->handle;
return (u64)window->hwnd; return (u64)window->hwnd;
} }
void sys_window_cursor_set_pos(struct sys_window *sys_window, struct v2 pos)
{
struct win32_window *window = (struct win32_window *)sys_window->handle;
window->cursor_set_position = pos;
window->cursor_set_flags |= WIN32_WINDOW_CURSOR_SET_FLAG_POSITION;
win32_window_wake(window);
}
void sys_window_cursor_show(struct sys_window *sys_window)
{
struct win32_window *window = (struct win32_window *)sys_window->handle;
window->cursor_set_flags |= WIN32_WINDOW_CURSOR_SET_FLAG_SHOW;
win32_window_wake(window);
}
void sys_window_cursor_hide(struct sys_window *sys_window)
{
struct win32_window *window = (struct win32_window *)sys_window->handle;
window->cursor_set_flags |= WIN32_WINDOW_CURSOR_SET_FLAG_HIDE;
win32_window_wake(window);
}
/* ========================== * /* ========================== *
* Mutex * Mutex
* ========================== */ * ========================== */
@ -1719,6 +1812,21 @@ int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
} }
} }
/* Register raw input */
{
RAWINPUTDEVICE rid = (RAWINPUTDEVICE) {
.usUsagePage = 0x01, /* HID_USAGE_PAGE_GENERIC */
.usUsage = 0x02, /* HID_USAGE_GENERIC_MOUSE */
//.dwFlags = RIDEV_NOLEGACY /* Adds mouse and also ignores legacy mouse messages */
};
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) {
/* TODO: GetLastError */
error_msg = "Failed to register raw input device";
goto error;
}
}
error: error:
if (error_msg) { if (error_msg) {
MessageBoxExA(NULL, error_msg, "Fatal initialization error", MB_ICONSTOP, 0); MessageBoxExA(NULL, error_msg, "Fatal initialization error", MB_ICONSTOP, 0);

View File

@ -167,8 +167,7 @@ INTERNAL void texture_load_asset_task(void *vparams)
struct asset_cache_store store = asset_cache_store_open(); struct asset_cache_store store = asset_cache_store_open();
texture = arena_push(store.arena, struct texture); texture = arena_push(store.arena, struct texture);
*texture = (struct texture) { *texture = (struct texture) {
.width = image_data.width, .size = V2(image_data.width, image_data.height),
.height = image_data.height,
.renderer_handle = handle .renderer_handle = handle
}; };
asset_cache_store_close(&store); asset_cache_store_close(&store);
@ -200,9 +199,8 @@ abort:
struct asset_cache_store store = asset_cache_store_open(); struct asset_cache_store store = asset_cache_store_open();
texture = arena_push(store.arena, struct texture); texture = arena_push(store.arena, struct texture);
*texture = (struct texture) { *texture = (struct texture) {
.width = default_image_data.width, .renderer_handle = handle,
.height = default_image_data.height, .size = V2(default_image_data.width, default_image_data.height)
.renderer_handle = handle
}; };
asset_cache_store_close(&store); asset_cache_store_close(&store);
} }

View File

@ -23,8 +23,7 @@ struct texture_anim {
struct texture { struct texture {
struct renderer_handle renderer_handle; struct renderer_handle renderer_handle;
u32 width; struct v2 size;
u32 height;
}; };
void texture_startup(void); void texture_startup(void);

View File

@ -28,8 +28,9 @@ struct view {
}; };
struct bind_state { struct bind_state {
b32 is_held; /* Is this bind held down this frame */ b32 is_held; /* Is this bind held down this frame */
u32 num_presses; /* How many times was this bind pressed since last frame */ u32 num_presses; /* How many times was this bind pressed since last frame */
u32 num_releases; /* How many times was this bind released since last frame */
}; };
struct blend_tick { struct blend_tick {
@ -57,7 +58,7 @@ GLOBAL struct {
b32 debug_camera; b32 debug_camera;
b32 debug_camera_panning; b32 debug_camera_panning;
struct v2 debug_camera_panning_from; struct v2 debug_camera_pan_start;
b32 debug_draw; b32 debug_draw;
@ -71,6 +72,9 @@ GLOBAL struct {
struct v2 screen_size; struct v2 screen_size;
struct v2 screen_center; struct v2 screen_center;
struct v2 screen_mouse; struct v2 screen_mouse;
struct v2 screen_mouse_delta;
struct v2 world_mouse;
struct v2 last_focus_screen_pos;
} L = { 0 }, DEBUG_LVAR(L_user); } L = { 0 }, DEBUG_LVAR(L_user);
/* ========================== * /* ========================== *
@ -91,7 +95,8 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
[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_MWHEELUP] = USER_BIND_KIND_ZOOM_IN, [SYS_BTN_MWHEELUP] = USER_BIND_KIND_ZOOM_IN,
[SYS_BTN_MWHEELDOWN] = USER_BIND_KIND_ZOOM_OUT [SYS_BTN_MWHEELDOWN] = USER_BIND_KIND_ZOOM_OUT,
[SYS_BTN_M3] = USER_BIND_KIND_PAN
}; };
/* ========================== * /* ========================== *
@ -314,22 +319,17 @@ INTERNAL struct xform view_get_xform(struct view view)
return res; return res;
} }
INTERNAL struct v2 view_xform_point(struct view view, struct v2 p) INTERNAL struct v2 view_xform_v2(struct view view, struct v2 p)
{ {
struct xform mtx = view_get_xform(view); struct xform mtx = view_get_xform(view);
return xform_mul_v2(mtx, p); return xform_mul_v2(mtx, p);
} }
INTERNAL struct v2 view_inverse_xform_point(struct view view, struct v2 p) INTERNAL struct v2 view_inverse_xform_v2(struct view view, struct v2 p)
{ {
return xform_invert_mul_v2(view_get_xform(view), p); return xform_invert_mul_v2(view_get_xform(view), p);
} }
INTERNAL struct v2 view_mouse_pos(struct view view)
{
return view_inverse_xform_point(view, L.screen_mouse);
}
/* ========================== * /* ========================== *
* Update * Update
* ========================== */ * ========================== */
@ -395,7 +395,6 @@ INTERNAL void user_update(void)
L.screen_center = v2_mul(L.screen_size, 0.5); L.screen_center = v2_mul(L.screen_size, 0.5);
/* Read input */ /* Read input */
L.screen_mouse = sys_window_get_mouse_pos(L.window);
struct sys_event_array events = pop_sys_events(scratch.arena); struct sys_event_array events = pop_sys_events(scratch.arena);
/* ========================== * /* ========================== *
@ -409,6 +408,8 @@ INTERNAL void user_update(void)
}; };
} }
L.screen_mouse_delta = V2(0, 0);
for (u64 entity_index = 0; entity_index < events.count; ++entity_index) { for (u64 entity_index = 0; entity_index < events.count; ++entity_index) {
struct sys_event *event = &events.events[entity_index]; struct sys_event *event = &events.events[entity_index];
@ -421,16 +422,6 @@ INTERNAL void user_update(void)
app_quit(); app_quit();
} }
/* Move camera/view */
if (event->button == SYS_BTN_M3) {
if (event->kind == SYS_EVENT_KIND_BUTTON_DOWN) {
L.debug_camera_panning = true;
L.debug_camera_panning_from = view_mouse_pos(L.world_view);
} else if (event->kind == SYS_EVENT_KIND_BUTTON_UP) {
L.debug_camera_panning = false;
}
}
if (event->kind == SYS_EVENT_KIND_BUTTON_UP) { if (event->kind == SYS_EVENT_KIND_BUTTON_UP) {
#if DEVELOPER #if DEVELOPER
/* Escape quit */ /* Escape quit */
@ -453,6 +444,16 @@ INTERNAL void user_update(void)
} }
} }
/* Update mouse pos */
if (event->kind == SYS_EVENT_KIND_MOUSE_MOVE) {
L.screen_mouse = event->mouse_position;
}
/* Update mouse delta */
if (event->kind == SYS_EVENT_KIND_RAW_MOUSE_MOVE) {
L.screen_mouse_delta = v2_add(L.screen_mouse_delta, event->raw_mouse_delta);
}
/* Update bind states */ /* Update bind states */
if ((event->kind == SYS_EVENT_KIND_BUTTON_DOWN || event->kind == SYS_EVENT_KIND_BUTTON_UP) && !event->is_repeat) { if ((event->kind == SYS_EVENT_KIND_BUTTON_DOWN || event->kind == SYS_EVENT_KIND_BUTTON_UP) && !event->is_repeat) {
enum sys_btn button = event->button; enum sys_btn button = event->button;
@ -463,52 +464,13 @@ INTERNAL void user_update(void)
L.bind_states[bind].is_held = pressed; L.bind_states[bind].is_held = pressed;
if (pressed) { if (pressed) {
++L.bind_states[bind].num_presses; ++L.bind_states[bind].num_presses;
} else {
++L.bind_states[bind].num_releases;
} }
} }
} }
} }
/* ========================== *
* Process movement input
* ========================== */
/* Movement */
{
struct v2 input_move_dir = { 0 };
for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(L.bind_states); ++bind) {
struct bind_state state = L.bind_states[bind];
if (!state.is_held && state.num_presses <= 0) {
continue;
}
switch (bind) {
/* Movement */
case USER_BIND_KIND_MOVE_UP: {
input_move_dir.y -= 1;
} break;
case USER_BIND_KIND_MOVE_DOWN: {
input_move_dir.y += 1;
} break;
case USER_BIND_KIND_MOVE_LEFT: {
input_move_dir.x -= 1;
} break;
case USER_BIND_KIND_MOVE_RIGHT: {
input_move_dir.x += 1;
} break;
default: break;
}
}
queue_game_cmd(&cmd_list, (struct game_cmd) {
.kind = GAME_CMD_KIND_PLAYER_MOVE,
.dir = v2_norm(input_move_dir)
});
}
/* ========================== * /* ========================== *
* Debug commands * Debug commands
* ========================== */ * ========================== */
@ -532,18 +494,27 @@ INTERNAL void user_update(void)
} }
if (L.bind_states[USER_BIND_KIND_DEBUG_CAMERA].num_presses > 0) { if (L.bind_states[USER_BIND_KIND_DEBUG_CAMERA].num_presses > 0) {
if (!L.debug_camera) {
/* Move cursor to last crosshair pos */
sys_window_cursor_set_pos(L.window, L.last_focus_screen_pos);
}
L.debug_camera = !L.debug_camera; L.debug_camera = !L.debug_camera;
} }
if (L.debug_camera) { if (L.debug_camera) {
sys_window_cursor_show(L.window);
//L.world_view.rot += 1 * (f32)L.dt;
/* Pan view */ /* Pan view */
if (L.debug_camera_panning) { if (L.bind_states[USER_BIND_KIND_PAN].is_held) {
struct v2 offset = v2_sub(L.debug_camera_panning_from, view_mouse_pos(L.world_view)); if (!L.debug_camera_panning) {
L.debug_camera_pan_start = view_inverse_xform_v2(L.world_view, L.screen_mouse);
}
L.debug_camera_panning = true;
struct v2 offset = v2_sub(L.debug_camera_pan_start, view_inverse_xform_v2(L.world_view, L.screen_mouse));
L.world_view.center = v2_add(L.world_view.center, offset); L.world_view.center = v2_add(L.world_view.center, offset);
L.debug_camera_panning_from = view_mouse_pos(L.world_view); L.debug_camera_pan_start = view_inverse_xform_v2(L.world_view, L.screen_mouse);
} else {
L.debug_camera_panning = false;
} }
/* Zoom view */ /* Zoom view */
@ -566,14 +537,65 @@ INTERNAL void user_update(void)
new_zoom = clamp_f32(new_zoom, zoom_min, zoom_max); new_zoom = clamp_f32(new_zoom, zoom_min, zoom_max);
} }
struct v2 old_mouse = view_mouse_pos(L.world_view); struct v2 old_mouse = view_inverse_xform_v2(L.world_view, L.screen_mouse);
L.world_view.zoom = new_zoom; L.world_view.zoom = new_zoom;
struct v2 new_mouse = view_mouse_pos(L.world_view); struct v2 new_mouse = view_inverse_xform_v2(L.world_view, L.screen_mouse);
/* Offset view to zoom in on mouse */ /* Offset view to zoom in on mouse */
struct v2 offset = v2_sub(old_mouse, new_mouse); struct v2 offset = v2_sub(old_mouse, new_mouse);
L.world_view.center = v2_add(L.world_view.center, offset); L.world_view.center = v2_add(L.world_view.center, offset);
} }
} else {
/* Keep cursor invisible at center of screen */
sys_window_cursor_hide(L.window);
sys_window_cursor_set_pos(L.window, L.screen_center);
}
/* ========================== *
* Process movement input
* ========================== */
/* Movement */
{
struct v2 player_move_dir = { 0 };
for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(L.bind_states); ++bind) {
struct bind_state state = L.bind_states[bind];
if (!state.is_held && state.num_presses <= 0) {
continue;
}
switch (bind) {
/* Movement */
case USER_BIND_KIND_MOVE_UP: {
player_move_dir.y -= 1;
} break;
case USER_BIND_KIND_MOVE_DOWN: {
player_move_dir.y += 1;
} break;
case USER_BIND_KIND_MOVE_LEFT: {
player_move_dir.x -= 1;
} break;
case USER_BIND_KIND_MOVE_RIGHT: {
player_move_dir.x += 1;
} break;
default: break;
}
}
struct game_cmd cmd = (struct game_cmd) {
.kind = GAME_CMD_KIND_PLAYER_MOVE,
.move_dir = v2_norm(player_move_dir)
};
if (!L.debug_camera) {
struct v2 focus_move_dir = v2_div(L.screen_mouse_delta, PIXELS_PER_UNIT * L.world_view.zoom);
focus_move_dir = v2_mul(focus_move_dir, MOUSE_SENSITIVITY);
cmd.focus_move_dir = focus_move_dir;
}
queue_game_cmd(&cmd_list, cmd);
} }
/* ========================== * /* ========================== *
@ -582,7 +604,6 @@ INTERNAL void user_update(void)
/* Pull ticks */ /* Pull ticks */
/* FIXME: use real game DT */
f64 blend_time_offset = (1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO; f64 blend_time_offset = (1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO;
f64 blend_time = L.time > blend_time_offset ? L.time - blend_time_offset : 0; f64 blend_time = L.time > blend_time_offset ? L.time - blend_time_offset : 0;
@ -610,9 +631,9 @@ INTERNAL void user_update(void)
L.world.time = math_lerp_f64(t0->time, t1->time, (f64)tick_blend); L.world.time = math_lerp_f64(t0->time, t1->time, (f64)tick_blend);
/* Blend entities */ /* Blend entities */
struct entity_array t0_entities = world_get_entities(t0); struct entity_array t0_entities = entity_store_as_array(&t0->entity_store);
struct entity_array t1_entities = world_get_entities(t1); struct entity_array t1_entities = entity_store_as_array(&t1->entity_store);
struct entity_array world_entities = world_get_entities(&L.world); struct entity_array world_entities = entity_store_as_array(&L.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);
for (u64 i = 0; i < num_entities; ++i) { for (u64 i = 0; i < num_entities; ++i) {
@ -626,6 +647,7 @@ INTERNAL void user_update(void)
e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend); e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend);
e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend); e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend);
e->player_acceleration = math_lerp_f32(e0->player_acceleration, e1->player_acceleration, tick_blend); e->player_acceleration = math_lerp_f32(e0->player_acceleration, e1->player_acceleration, tick_blend);
e->player_focus_dir = v2_lerp(e0->player_focus_dir, e1->player_focus_dir, tick_blend);
e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend); e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend);
e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend); e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
@ -638,13 +660,12 @@ INTERNAL void user_update(void)
#endif #endif
} }
struct entity_array entities_array = world_get_entities(&L.world); struct entity_array entities_array = entity_store_as_array(&L.world.entity_store);
/* ========================== * /* ========================== *
* Update view from game camera * Update view from game camera
* ========================== */ * ========================== */
/* Find camera */
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) continue; if (!ent->valid) continue;
@ -657,6 +678,7 @@ INTERNAL void user_update(void)
L.world_view.center = center; L.world_view.center = center;
L.world_view.rot = rot; L.world_view.rot = rot;
L.world_view.zoom = zoom; L.world_view.zoom = zoom;
L.world_mouse = view_inverse_xform_v2(L.world_view, L.screen_mouse);
} }
} }
@ -776,6 +798,22 @@ INTERNAL void user_update(void)
} }
} }
/* Draw crosshair */
if (!L.debug_camera && entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
struct v2 focus_pos = v2_add(ent->world_xform.og, ent->player_focus_dir);
struct v2 focus_pos_screen = view_xform_v2(L.world_view, focus_pos);
u32 tint = RGBA_F(1, 1, 1, 0.5);
struct texture *t = texture_load_async(STR("res/graphics/crosshair.ase"));
if (t) {
struct xform xf = XFORM_TRS(.t = focus_pos_screen, .s = t->size);
struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xf);
draw_texture_quad(L.screen_canvas, DRAW_TEXTURE_PARAMS(.texture = t, .tint = tint), quad);
}
L.last_focus_screen_pos = focus_pos_screen;
}
/* Debug draw info */ /* Debug draw info */
if (L.debug_draw && !is_camera) { if (L.debug_draw && !is_camera) {
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
@ -790,7 +828,7 @@ INTERNAL void user_update(void)
f32 offset = 1; f32 offset = 1;
struct v2 pos = v2_add(xf.og, v2_mul(V2(0, -1), offset)); struct v2 pos = v2_add(xf.og, v2_mul(V2(0, -1), offset));
pos = view_xform_point(L.world_view, pos); pos = view_xform_v2(L.world_view, pos);
pos = v2_round(pos); pos = v2_round(pos);
struct string disp_name = ent->sprite_name; struct string disp_name = ent->sprite_name;
@ -827,8 +865,21 @@ INTERNAL void user_update(void)
f32 thickness = 5; f32 thickness = 5;
f32 arrow_height = 15; f32 arrow_height = 15;
struct v2 start = view_xform_point(L.world_view, ent->world_xform.og); struct v2 start = view_xform_v2(L.world_view, ent->world_xform.og);
struct v2 end = view_xform_point(L.world_view, parent->world_xform.og); struct v2 end = view_xform_v2(L.world_view, parent->world_xform.og);
draw_solid_arrow_line(L.screen_canvas, start, end, thickness, arrow_height, color);
}
/* Draw focus */
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
u32 color = RGBA_F(0.75, 0, 0.75, 0.5);
f32 thickness = 3;
f32 arrow_height = 10;
struct v2 focus_pos = v2_add(ent->world_xform.og, ent->player_focus_dir);
struct v2 start = view_xform_v2(L.world_view, ent->world_xform.og);
struct v2 end = view_xform_v2(L.world_view, focus_pos);
draw_solid_arrow_line(L.screen_canvas, start, end, thickness, arrow_height, color); draw_solid_arrow_line(L.screen_canvas, start, end, thickness, arrow_height, color);
} }
@ -842,15 +893,6 @@ INTERNAL void user_update(void)
/* Update listener using world view */ /* Update listener using world view */
mixer_set_listener(L.world_view.center, V2(-math_sin(L.world_view.rot), -math_cos(L.world_view.rot))); mixer_set_listener(L.world_view.center, V2(-math_sin(L.world_view.rot), -math_cos(L.world_view.rot)));
/* Send world mouse pos */
struct v2 world_mouse = view_mouse_pos(L.world_view);
if (!L.debug_camera) {
queue_game_cmd(&cmd_list, (struct game_cmd) {
.kind = GAME_CMD_KIND_PLAYER_FOCUS,
.pos = world_mouse
});
}
/* Debug draw info */ /* Debug draw info */
if (L.debug_draw) { if (L.debug_draw) {
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
@ -880,7 +922,7 @@ INTERNAL void user_update(void)
draw_text(L.screen_canvas, font, pos, string_format(temp.arena, STR("world_view.zoom: %F"), FMT_FLOAT((f64)L.world_view.zoom))); draw_text(L.screen_canvas, font, pos, string_format(temp.arena, STR("world_view.zoom: %F"), FMT_FLOAT((f64)L.world_view.zoom)));
pos.y += spacing; pos.y += spacing;
draw_text(L.screen_canvas, font, pos, string_format(temp.arena, STR("world_mouse: (%F, %F)"), FMT_FLOAT((f64)world_mouse.x), FMT_FLOAT((f64)world_mouse.y))); draw_text(L.screen_canvas, font, pos, string_format(temp.arena, STR("world_mouse: (%F, %F)"), FMT_FLOAT((f64)L.world_mouse.x), FMT_FLOAT((f64)L.world_mouse.y)));
pos.y += spacing; pos.y += spacing;
draw_text(L.screen_canvas, font, pos, string_format(temp.arena, STR("debug_camera: %F"), FMT_STR(L.debug_camera ? STR("true") : STR("false")))); draw_text(L.screen_canvas, font, pos, string_format(temp.arena, STR("debug_camera: %F"), FMT_STR(L.debug_camera ? STR("true") : STR("false"))));

View File

@ -18,6 +18,7 @@ enum user_bind_kind {
USER_BIND_KIND_DEBUG_CAMERA, USER_BIND_KIND_DEBUG_CAMERA,
USER_BIND_KIND_ZOOM_IN, USER_BIND_KIND_ZOOM_IN,
USER_BIND_KIND_ZOOM_OUT, USER_BIND_KIND_ZOOM_OUT,
USER_BIND_KIND_PAN,
USER_BIND_KIND_COUNT USER_BIND_KIND_COUNT
}; };

View File

@ -22,11 +22,3 @@ void world_copy_replace(struct world *dest, struct world *src)
scratch_end(scratch); scratch_end(scratch);
} }
struct entity_array world_get_entities(struct world *world)
{
return (struct entity_array) {
.entities = (struct entity *)world->entity_store.arena.base,
.count = world->entity_store.count
};
}

View File

@ -12,14 +12,13 @@ struct world {
f64 dt; f64 dt;
f64 time; f64 time;
struct v2 player_move_dir; /* Player movement direction */ struct v2 player_move_dir; /* Player movement direction */
struct v2 player_focus; /* Mouse cursor pos in world coordinates */ struct v2 player_focus_move_dir; /* Focus movement direction */
struct entity_store entity_store; struct entity_store entity_store;
}; };
void world_alloc(struct world *world); void world_alloc(struct world *world);
void world_copy_replace(struct world *dest, struct world *src); void world_copy_replace(struct world *dest, struct world *src);
struct entity_array world_get_entities(struct world *world);
#endif #endif