package platform import window "window:window" MAX_KEYS :: 153 // window.Key_Code has ~153 variants MAX_MOUSE_BUTTONS :: 5 Input_State :: struct { // Key states: current and previous frame keys_current: [MAX_KEYS]bool, keys_previous: [MAX_KEYS]bool, // Mouse button states mouse_current: [MAX_MOUSE_BUTTONS]bool, mouse_previous: [MAX_MOUSE_BUTTONS]bool, // Mouse position mouse_x, mouse_y: f32, mouse_prev_x, mouse_prev_y: f32, // Raw mouse delta (from device events) mouse_delta_x, mouse_delta_y: f32, // Scroll wheel scroll_delta: f32, } init_input :: proc(state: ^Input_State) { state^ = {} } // Called at the start of each frame to swap current -> previous begin_input_frame :: proc(state: ^Input_State) { state.keys_previous = state.keys_current state.mouse_previous = state.mouse_current state.mouse_prev_x = state.mouse_x state.mouse_prev_y = state.mouse_y state.mouse_delta_x = 0 state.mouse_delta_y = 0 state.scroll_delta = 0 } // Event handlers called from platform.poll_events handle_key_input :: proc(state: ^Input_State, event: window.Key_Input) { idx := int(event.key) if idx >= 0 && idx < MAX_KEYS { state.keys_current[idx] = event.state == .Pressed } } handle_mouse_button_input :: proc(state: ^Input_State, event: window.Mouse_Button_Input) { idx := int(event.button) if idx >= 0 && idx < MAX_MOUSE_BUTTONS { state.mouse_current[idx] = event.state == .Pressed } } handle_pointer_moved :: proc(state: ^Input_State, event: window.Pointer_Moved) { state.mouse_x = f32(event.position.x) state.mouse_y = f32(event.position.y) } handle_raw_motion :: proc(state: ^Input_State, event: window.Pointer_Motion) { state.mouse_delta_x += f32(event.delta_x) state.mouse_delta_y += f32(event.delta_y) } handle_mouse_wheel :: proc(state: ^Input_State, event: window.Mouse_Wheel) { switch d in event.delta { case window.Line_Delta: state.scroll_delta += d.y case window.Pixel_Delta: state.scroll_delta += d.y / 120.0 // normalize pixel delta } } // Query functions is_key_pressed :: proc(state: ^Platform_State, key: window.Key_Code) -> bool { idx := int(key) if idx < 0 || idx >= MAX_KEYS { return false } return state.input.keys_current[idx] && !state.input.keys_previous[idx] } is_key_down :: proc(state: ^Platform_State, key: window.Key_Code) -> bool { idx := int(key) if idx < 0 || idx >= MAX_KEYS { return false } return state.input.keys_current[idx] } is_key_released :: proc(state: ^Platform_State, key: window.Key_Code) -> bool { idx := int(key) if idx < 0 || idx >= MAX_KEYS { return false } return !state.input.keys_current[idx] && state.input.keys_previous[idx] } is_mouse_button_pressed :: proc(state: ^Platform_State, btn: window.Mouse_Button) -> bool { idx := int(btn) if idx < 0 || idx >= MAX_MOUSE_BUTTONS { return false } return state.input.mouse_current[idx] && !state.input.mouse_previous[idx] } is_mouse_button_down :: proc(state: ^Platform_State, btn: window.Mouse_Button) -> bool { idx := int(btn) if idx < 0 || idx >= MAX_MOUSE_BUTTONS { return false } return state.input.mouse_current[idx] } get_mouse_position :: proc(state: ^Platform_State) -> [2]f32 { return {state.input.mouse_x, state.input.mouse_y} } get_mouse_delta :: proc(state: ^Platform_State) -> [2]f32 { // Prefer raw motion delta; fall back to position delta dx := state.input.mouse_delta_x dy := state.input.mouse_delta_y if dx == 0 && dy == 0 { dx = state.input.mouse_x - state.input.mouse_prev_x dy = state.input.mouse_y - state.input.mouse_prev_y } return {dx, dy} } get_mouse_wheel_move :: proc(state: ^Platform_State) -> f32 { return state.input.scroll_delta }