abstract input into platform layer
This commit is contained in:
43
src/main.cpp
43
src/main.cpp
@@ -17,40 +17,6 @@
|
|||||||
#include "midi/midi_win32.cpp"
|
#include "midi/midi_win32.cpp"
|
||||||
#include "menus.cpp"
|
#include "menus.cpp"
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Win32 input gathering
|
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
struct InputState {
|
|
||||||
Vec2F32 mouse;
|
|
||||||
Vec2F32 scroll_delta;
|
|
||||||
B32 mouse_down;
|
|
||||||
B32 was_mouse_down;
|
|
||||||
};
|
|
||||||
|
|
||||||
static InputState g_input;
|
|
||||||
|
|
||||||
static void input_gather(void *window_handle) {
|
|
||||||
HWND hwnd = (HWND)window_handle;
|
|
||||||
|
|
||||||
// Mouse position
|
|
||||||
POINT cursor;
|
|
||||||
GetCursorPos(&cursor);
|
|
||||||
ScreenToClient(hwnd, &cursor);
|
|
||||||
g_input.mouse = v2f32((F32)cursor.x, (F32)cursor.y);
|
|
||||||
|
|
||||||
// Mouse button
|
|
||||||
g_input.was_mouse_down = g_input.mouse_down;
|
|
||||||
g_input.mouse_down = (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0;
|
|
||||||
|
|
||||||
// Scroll (TODO: hook WM_MOUSEWHEEL for real scroll deltas)
|
|
||||||
g_input.scroll_delta = v2f32(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Clay text config helpers
|
// Clay text config helpers
|
||||||
|
|
||||||
@@ -430,13 +396,12 @@ static void do_frame(AppState *app) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Gather input
|
// Gather input
|
||||||
input_gather(platform_get_native_handle(app->window));
|
PlatformInput input = platform_get_input(app->window);
|
||||||
PlatformInputEvents input_events = platform_get_input_events(app->window);
|
ui_widgets_begin_frame(input);
|
||||||
ui_widgets_begin_frame(input_events, g_input.mouse_down, g_input.was_mouse_down);
|
|
||||||
|
|
||||||
// Build UI with Clay
|
// Build UI with Clay
|
||||||
ui_begin_frame(app->ui, (F32)w, (F32)h, g_input.mouse, g_input.mouse_down,
|
ui_begin_frame(app->ui, (F32)w, (F32)h, input.mouse_pos, input.mouse_down,
|
||||||
g_input.scroll_delta, dt);
|
input.scroll_delta, dt);
|
||||||
build_ui(app);
|
build_ui(app);
|
||||||
Clay_RenderCommandArray render_commands = ui_end_frame(app->ui);
|
Clay_RenderCommandArray render_commands = ui_end_frame(app->ui);
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "base/base_core.h"
|
||||||
|
#include "base/base_math.h"
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Input event buffer
|
// Input — accumulated per frame, consumed by the app each tick.
|
||||||
// Accumulated per frame, consumed by the app each tick.
|
|
||||||
|
|
||||||
#define PLATFORM_MAX_CHARS_PER_FRAME 64
|
#define PLATFORM_MAX_CHARS_PER_FRAME 64
|
||||||
#define PLATFORM_MAX_KEYS_PER_FRAME 32
|
#define PLATFORM_MAX_KEYS_PER_FRAME 32
|
||||||
@@ -29,7 +30,7 @@ enum {
|
|||||||
PKEY_X = 0x58,
|
PKEY_X = 0x58,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlatformInputEvents {
|
struct PlatformInput {
|
||||||
// Typed characters (UTF-16 code units, printable only)
|
// Typed characters (UTF-16 code units, printable only)
|
||||||
uint16_t chars[PLATFORM_MAX_CHARS_PER_FRAME];
|
uint16_t chars[PLATFORM_MAX_CHARS_PER_FRAME];
|
||||||
int32_t char_count;
|
int32_t char_count;
|
||||||
@@ -41,6 +42,12 @@ struct PlatformInputEvents {
|
|||||||
// Modifier state at time of last key event
|
// Modifier state at time of last key event
|
||||||
bool ctrl_held;
|
bool ctrl_held;
|
||||||
bool shift_held;
|
bool shift_held;
|
||||||
|
|
||||||
|
// Mouse state (polled per frame)
|
||||||
|
Vec2F32 mouse_pos;
|
||||||
|
Vec2F32 scroll_delta;
|
||||||
|
B32 mouse_down;
|
||||||
|
B32 was_mouse_down;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlatformWindow;
|
struct PlatformWindow;
|
||||||
@@ -77,8 +84,8 @@ void platform_set_frame_callback(PlatformWindow *window, PlatformFram
|
|||||||
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count);
|
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count);
|
||||||
int32_t platform_poll_menu_command(PlatformWindow *window);
|
int32_t platform_poll_menu_command(PlatformWindow *window);
|
||||||
|
|
||||||
// Returns accumulated input events since last call, then clears the buffer.
|
// Returns accumulated input since last call (keyboard events + polled mouse state), then clears the buffer.
|
||||||
PlatformInputEvents platform_get_input_events(PlatformWindow *window);
|
PlatformInput platform_get_input(PlatformWindow *window);
|
||||||
|
|
||||||
// Clipboard operations (null-terminated UTF-8 strings).
|
// Clipboard operations (null-terminated UTF-8 strings).
|
||||||
// platform_clipboard_set copies text to the system clipboard.
|
// platform_clipboard_set copies text to the system clipboard.
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ struct PlatformWindow {
|
|||||||
int32_t pending_menu_cmd;
|
int32_t pending_menu_cmd;
|
||||||
PlatformFrameCallback frame_callback;
|
PlatformFrameCallback frame_callback;
|
||||||
void *frame_callback_user_data;
|
void *frame_callback_user_data;
|
||||||
PlatformInputEvents input_events;
|
PlatformInput input;
|
||||||
|
B32 prev_mouse_down;
|
||||||
};
|
};
|
||||||
|
|
||||||
static PlatformWindow *g_current_window = nullptr;
|
static PlatformWindow *g_current_window = nullptr;
|
||||||
@@ -34,7 +35,7 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||||||
return 0;
|
return 0;
|
||||||
case WM_CHAR:
|
case WM_CHAR:
|
||||||
if (g_current_window && wparam >= 32 && wparam < 0xFFFF) {
|
if (g_current_window && wparam >= 32 && wparam < 0xFFFF) {
|
||||||
PlatformInputEvents *ev = &g_current_window->input_events;
|
PlatformInput *ev = &g_current_window->input;
|
||||||
if (ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME)
|
if (ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME)
|
||||||
ev->chars[ev->char_count++] = (uint16_t)wparam;
|
ev->chars[ev->char_count++] = (uint16_t)wparam;
|
||||||
}
|
}
|
||||||
@@ -42,13 +43,19 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
case WM_SYSKEYDOWN:
|
case WM_SYSKEYDOWN:
|
||||||
if (g_current_window) {
|
if (g_current_window) {
|
||||||
PlatformInputEvents *ev = &g_current_window->input_events;
|
PlatformInput *ev = &g_current_window->input;
|
||||||
if (ev->key_count < PLATFORM_MAX_KEYS_PER_FRAME)
|
if (ev->key_count < PLATFORM_MAX_KEYS_PER_FRAME)
|
||||||
ev->keys[ev->key_count++] = (uint8_t)wparam;
|
ev->keys[ev->key_count++] = (uint8_t)wparam;
|
||||||
ev->ctrl_held = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
ev->ctrl_held = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||||
ev->shift_held = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
ev->shift_held = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||||
}
|
}
|
||||||
break; // fall through to DefWindowProc for system keys
|
break; // fall through to DefWindowProc for system keys
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
if (g_current_window) {
|
||||||
|
int16_t wheel_delta = (int16_t)HIWORD(wparam);
|
||||||
|
g_current_window->input.scroll_delta.y += (F32)wheel_delta / (F32)WHEEL_DELTA;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
if (g_current_window && HIWORD(wparam) == 0)
|
if (g_current_window && HIWORD(wparam) == 0)
|
||||||
g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam);
|
g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam);
|
||||||
@@ -201,9 +208,22 @@ int32_t platform_poll_menu_command(PlatformWindow *window) {
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformInputEvents platform_get_input_events(PlatformWindow *window) {
|
PlatformInput platform_get_input(PlatformWindow *window) {
|
||||||
PlatformInputEvents result = window->input_events;
|
PlatformInput result = window->input;
|
||||||
window->input_events = {};
|
|
||||||
|
// Poll mouse position
|
||||||
|
POINT cursor;
|
||||||
|
GetCursorPos(&cursor);
|
||||||
|
ScreenToClient(window->hwnd, &cursor);
|
||||||
|
result.mouse_pos = v2f32((F32)cursor.x, (F32)cursor.y);
|
||||||
|
|
||||||
|
// Poll mouse button
|
||||||
|
result.was_mouse_down = window->prev_mouse_down;
|
||||||
|
result.mouse_down = (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0;
|
||||||
|
window->prev_mouse_down = result.mouse_down;
|
||||||
|
|
||||||
|
// Clear accumulated events for next frame
|
||||||
|
window->input = {};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ void ui_widgets_init() {
|
|||||||
g_wstate = {};
|
g_wstate = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_widgets_begin_frame(PlatformInputEvents input, B32 mouse_down, B32 was_mouse_down) {
|
void ui_widgets_begin_frame(PlatformInput input) {
|
||||||
g_wstate.input = input;
|
g_wstate.input = input;
|
||||||
g_wstate.was_mouse_down = g_wstate.mouse_down;
|
g_wstate.mouse_clicked = (input.mouse_down && !input.was_mouse_down);
|
||||||
g_wstate.mouse_down = mouse_down;
|
|
||||||
g_wstate.mouse_clicked = (mouse_down && !g_wstate.was_mouse_down);
|
|
||||||
g_wstate.cursor_blink += 1.0f / 60.0f;
|
g_wstate.cursor_blink += 1.0f / 60.0f;
|
||||||
g_wstate.text_input_count = 0;
|
g_wstate.text_input_count = 0;
|
||||||
g_wstate.tab_pressed = 0;
|
g_wstate.tab_pressed = 0;
|
||||||
|
|||||||
@@ -33,12 +33,10 @@ struct UI_WidgetState {
|
|||||||
// Dropdown
|
// Dropdown
|
||||||
uint32_t open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none)
|
uint32_t open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none)
|
||||||
|
|
||||||
// Input events for this frame
|
// Input for this frame
|
||||||
PlatformInputEvents input;
|
PlatformInput input;
|
||||||
|
|
||||||
// Click detection
|
// Click detection
|
||||||
B32 mouse_down;
|
|
||||||
B32 was_mouse_down;
|
|
||||||
B32 mouse_clicked; // true on the frame mouse transitions from up->down
|
B32 mouse_clicked; // true on the frame mouse transitions from up->down
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,8 +45,8 @@ extern UI_WidgetState g_wstate;
|
|||||||
// Call once at startup
|
// Call once at startup
|
||||||
void ui_widgets_init();
|
void ui_widgets_init();
|
||||||
|
|
||||||
// Call each frame before building widgets. Pass in the frame's input events.
|
// Call each frame before building widgets. Pass in the frame's input.
|
||||||
void ui_widgets_begin_frame(PlatformInputEvents input, B32 mouse_down, B32 was_mouse_down);
|
void ui_widgets_begin_frame(PlatformInput input);
|
||||||
|
|
||||||
// Reset per-frame text input display buffer allocator (called by begin_frame, but
|
// Reset per-frame text input display buffer allocator (called by begin_frame, but
|
||||||
// can also be called manually if needed)
|
// can also be called manually if needed)
|
||||||
|
|||||||
Reference in New Issue
Block a user