const std = @import("std"); const assert = std.debug.assert; const sokol = @import("sokol"); const Math = @import("math"); const Vec2 = Math.Vec2; const Input = @This(); key_code_mapping: std.EnumMap(KeyCode, u21), window_size: Vec2, focused: bool, keyboard: KeyStateType(KeyCode), mouse_buttons: KeyStateType(MouseButton), mouse_position: ?Vec2, mouse_scroll: Vec2, pub fn init(window_size: Vec2) Input { return Input{ .key_code_mapping = .{}, .focused = false, .keyboard = .empty, .mouse_buttons = .empty, .mouse_position = null, .mouse_scroll = .init(0, 0), .window_size = window_size }; } pub fn isKeyPressed(self: Input, key: KeyCode) bool { return self.keyboard.pressed.contains(key); } pub fn isKeyReleased(self: Input, key: KeyCode) bool { return self.keyboard.released.contains(key); } pub fn isKeyDown(self: Input, key: KeyCode) bool { return self.keyboard.down.contains(key); } pub fn isMousePressed(self: Input, button: MouseButton) bool { return self.mouse_buttons.pressed.contains(button); } pub fn iMouseReleased(self: Input, button: MouseButton) bool { return self.mouse_buttons.released.contains(button); } pub fn isMouseDown(self: Input, button: MouseButton) bool { return self.mouse_buttons.down.contains(button); } pub const KeyCode = enum(std.math.IntFittingRange(0, sokol.app.max_keycodes-1)) { SPACE = 32, APOSTROPHE = 39, COMMA = 44, MINUS = 45, PERIOD = 46, SLASH = 47, _0 = 48, _1 = 49, _2 = 50, _3 = 51, _4 = 52, _5 = 53, _6 = 54, _7 = 55, _8 = 56, _9 = 57, SEMICOLON = 59, EQUAL = 61, A = 65, B = 66, C = 67, D = 68, E = 69, F = 70, G = 71, H = 72, I = 73, J = 74, K = 75, L = 76, M = 77, N = 78, O = 79, P = 80, Q = 81, R = 82, S = 83, T = 84, U = 85, V = 86, W = 87, X = 88, Y = 89, Z = 90, LEFT_BRACKET = 91, BACKSLASH = 92, RIGHT_BRACKET = 93, GRAVE_ACCENT = 96, WORLD_1 = 161, WORLD_2 = 162, ESCAPE = 256, ENTER = 257, TAB = 258, BACKSPACE = 259, INSERT = 260, DELETE = 261, RIGHT = 262, LEFT = 263, DOWN = 264, UP = 265, PAGE_UP = 266, PAGE_DOWN = 267, HOME = 268, END = 269, CAPS_LOCK = 280, SCROLL_LOCK = 281, NUM_LOCK = 282, PRINT_SCREEN = 283, PAUSE = 284, F1 = 290, F2 = 291, F3 = 292, F4 = 293, F5 = 294, F6 = 295, F7 = 296, F8 = 297, F9 = 298, F10 = 299, F11 = 300, F12 = 301, F13 = 302, F14 = 303, F15 = 304, F16 = 305, F17 = 306, F18 = 307, F19 = 308, F20 = 309, F21 = 310, F22 = 311, F23 = 312, F24 = 313, F25 = 314, KP_0 = 320, KP_1 = 321, KP_2 = 322, KP_3 = 323, KP_4 = 324, KP_5 = 325, KP_6 = 326, KP_7 = 327, KP_8 = 328, KP_9 = 329, KP_DECIMAL = 330, KP_DIVIDE = 331, KP_MULTIPLY = 332, KP_SUBTRACT = 333, KP_ADD = 334, KP_ENTER = 335, KP_EQUAL = 336, LEFT_SHIFT = 340, LEFT_CONTROL = 341, LEFT_ALT = 342, LEFT_SUPER = 343, RIGHT_SHIFT = 344, RIGHT_CONTROL = 345, RIGHT_ALT = 346, RIGHT_SUPER = 347, MENU = 348, }; pub const MouseButton = enum { left, right, middle, pub fn fromSokol(mouse_button: sokol.app.Mousebutton) ?MouseButton { return switch(mouse_button) { .LEFT => .left, .RIGHT => .right, .MIDDLE => .middle, else => null }; } }; pub const Event = union(enum) { mouse_pressed: MouseButton, mouse_released: MouseButton, mouse_move: Vec2, mouse_enter: Vec2, mouse_leave, mouse_scroll: Vec2, key_pressed: KeyCode, key_released: KeyCode, char: u21, window_resize: Vec2, focused, unfocused, }; fn KeyStateType(T: type) type { return struct { pressed: std.EnumSet(T), released: std.EnumSet(T), down: std.EnumSet(T), pub const empty = @This(){ .pressed = .empty, .released = .empty, .down = .empty, }; pub fn press(self: *@This(), key: T) void { self.pressed.insert(key); self.down.insert(key); } pub fn release(self: *@This(), key: T) void { self.released.insert(key); self.down.remove(key); } pub fn releaseAll(self: *@This()) void { var iter = self.down.iterator(); while (iter.next()) |key| { self.release(key); } } }; }