diff --git a/src/main.cpp b/src/main.cpp index e48d76f..09ccebc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,40 +17,6 @@ #include "midi/midi_win32.cpp" #include "menus.cpp" -//////////////////////////////// -// Win32 input gathering - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include - -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 @@ -430,13 +396,12 @@ static void do_frame(AppState *app) { return; // Gather input - input_gather(platform_get_native_handle(app->window)); - PlatformInputEvents input_events = platform_get_input_events(app->window); - ui_widgets_begin_frame(input_events, g_input.mouse_down, g_input.was_mouse_down); + PlatformInput input = platform_get_input(app->window); + ui_widgets_begin_frame(input); // Build UI with Clay - ui_begin_frame(app->ui, (F32)w, (F32)h, g_input.mouse, g_input.mouse_down, - g_input.scroll_delta, dt); + ui_begin_frame(app->ui, (F32)w, (F32)h, input.mouse_pos, input.mouse_down, + input.scroll_delta, dt); build_ui(app); Clay_RenderCommandArray render_commands = ui_end_frame(app->ui); diff --git a/src/platform/platform.h b/src/platform/platform.h index 59cf913..d52149e 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -2,10 +2,11 @@ #include #include +#include "base/base_core.h" +#include "base/base_math.h" //////////////////////////////// -// Input event buffer -// Accumulated per frame, consumed by the app each tick. +// Input — accumulated per frame, consumed by the app each tick. #define PLATFORM_MAX_CHARS_PER_FRAME 64 #define PLATFORM_MAX_KEYS_PER_FRAME 32 @@ -29,7 +30,7 @@ enum { PKEY_X = 0x58, }; -struct PlatformInputEvents { +struct PlatformInput { // Typed characters (UTF-16 code units, printable only) uint16_t chars[PLATFORM_MAX_CHARS_PER_FRAME]; int32_t char_count; @@ -41,6 +42,12 @@ struct PlatformInputEvents { // Modifier state at time of last key event bool ctrl_held; bool shift_held; + + // Mouse state (polled per frame) + Vec2F32 mouse_pos; + Vec2F32 scroll_delta; + B32 mouse_down; + B32 was_mouse_down; }; 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); int32_t platform_poll_menu_command(PlatformWindow *window); -// Returns accumulated input events since last call, then clears the buffer. -PlatformInputEvents platform_get_input_events(PlatformWindow *window); +// Returns accumulated input since last call (keyboard events + polled mouse state), then clears the buffer. +PlatformInput platform_get_input(PlatformWindow *window); // Clipboard operations (null-terminated UTF-8 strings). // platform_clipboard_set copies text to the system clipboard. diff --git a/src/platform/platform_win32.cpp b/src/platform/platform_win32.cpp index 6c23a75..c5f83ee 100644 --- a/src/platform/platform_win32.cpp +++ b/src/platform/platform_win32.cpp @@ -14,7 +14,8 @@ struct PlatformWindow { int32_t pending_menu_cmd; PlatformFrameCallback frame_callback; void *frame_callback_user_data; - PlatformInputEvents input_events; + PlatformInput input; + B32 prev_mouse_down; }; static PlatformWindow *g_current_window = nullptr; @@ -34,7 +35,7 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM return 0; case WM_CHAR: 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) 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_SYSKEYDOWN: 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) ev->keys[ev->key_count++] = (uint8_t)wparam; ev->ctrl_held = (GetKeyState(VK_CONTROL) & 0x8000) != 0; ev->shift_held = (GetKeyState(VK_SHIFT) & 0x8000) != 0; } 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: if (g_current_window && HIWORD(wparam) == 0) g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam); @@ -201,9 +208,22 @@ int32_t platform_poll_menu_command(PlatformWindow *window) { return cmd; } -PlatformInputEvents platform_get_input_events(PlatformWindow *window) { - PlatformInputEvents result = window->input_events; - window->input_events = {}; +PlatformInput platform_get_input(PlatformWindow *window) { + PlatformInput result = window->input; + + // 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; } diff --git a/src/ui/ui_widgets.cpp b/src/ui/ui_widgets.cpp index de1ccca..701de51 100644 --- a/src/ui/ui_widgets.cpp +++ b/src/ui/ui_widgets.cpp @@ -14,11 +14,9 @@ void ui_widgets_init() { 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.was_mouse_down = g_wstate.mouse_down; - g_wstate.mouse_down = mouse_down; - g_wstate.mouse_clicked = (mouse_down && !g_wstate.was_mouse_down); + g_wstate.mouse_clicked = (input.mouse_down && !input.was_mouse_down); g_wstate.cursor_blink += 1.0f / 60.0f; g_wstate.text_input_count = 0; g_wstate.tab_pressed = 0; diff --git a/src/ui/ui_widgets.h b/src/ui/ui_widgets.h index 4f89811..f8788b5 100644 --- a/src/ui/ui_widgets.h +++ b/src/ui/ui_widgets.h @@ -33,12 +33,10 @@ struct UI_WidgetState { // Dropdown uint32_t open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none) - // Input events for this frame - PlatformInputEvents input; + // Input for this frame + PlatformInput input; // Click detection - B32 mouse_down; - B32 was_mouse_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 void ui_widgets_init(); -// Call each frame before building widgets. Pass in the frame's input events. -void ui_widgets_begin_frame(PlatformInputEvents input, B32 mouse_down, B32 was_mouse_down); +// Call each frame before building widgets. Pass in the frame's input. +void ui_widgets_begin_frame(PlatformInput input); // Reset per-frame text input display buffer allocator (called by begin_frame, but // can also be called manually if needed)