Mercurial > games > semicongine
view semiconginev2/input.nim @ 1256:bfb75c934f4e
add: window focus handling, improve window api a bit
author | sam <sam@basx.dev> |
---|---|
date | Sun, 28 Jul 2024 17:33:41 +0700 |
parents | b0f4c8ccd49a |
children |
line wrap: on
line source
type Input = object keyIsDown: set[Key] keyWasPressed: set[Key] keyWasReleased: set[Key] mouseIsDown: set[MouseButton] mouseWasPressed: set[MouseButton] mouseWasReleased: set[MouseButton] mousePosition: Vec2f mouseMove: Vec2f mouseWheel: float32 windowWasResized: bool = true windowIsMinimized: bool = false lockMouse: bool = false hasFocus: bool = false # warning, shit is not thread safe var input = Input() proc UpdateInputs*(): bool = # reset input states input.keyWasPressed = {} input.keyWasReleased = {} input.mouseWasPressed = {} input.mouseWasReleased = {} input.mouseWheel = 0 input.mouseMove = NewVec2f() input.windowWasResized = false if input.lockMouse and input.hasFocus: SetMousePosition(vulkan.window, x=int(vulkan.swapchain.width div 2), y=int(vulkan.swapchain.height div 2)) var killed = false for event in vulkan.window.PendingEvents(): case event.eventType: of Quit: killed = true of ResizedWindow: input.windowWasResized = true of KeyPressed: input.keyWasPressed.incl event.key input.keyIsDown.incl event.key of KeyReleased: input.keyWasReleased.incl event.key input.keyIsDown.excl event.key of MousePressed: input.mouseWasPressed.incl event.button input.mouseIsDown.incl event.button of MouseReleased: input.mouseWasReleased.incl event.button input.mouseIsDown.excl event.button of MouseMoved: let newPos = NewVec2(float32(event.x), float32(event.y)) input.mouseMove = newPos - input.mousePosition input.mousePosition = newPos of MouseWheel: input.mouseWheel = event.amount of MinimizedWindow: input.windowIsMinimized = true of RestoredWindow: input.windowIsMinimized = false of GotFocus: input.hasFocus = true of LostFocus: input.hasFocus = false return not killed proc KeyIsDown*(key: Key): bool = key in input.keyIsDown proc KeyWasPressed*(key: Key): bool = key in input.keyWasPressed proc KeyWasPressed*(): bool = input.keyWasPressed.len > 0 proc KeyWasReleased*(key: Key): bool = key in input.keyWasReleased proc MouseIsDown*(button: MouseButton): bool = button in input.mouseIsDown proc MouseWasPressed*(): bool = input.mouseWasPressed.len > 0 proc MouseWasPressed*(button: MouseButton): bool = button in input.mouseWasPressed proc MousePressedButtons*(): set[MouseButton] = input.mouseWasPressed proc MouseWasReleased*(): bool = input.mouseWasReleased.len > 0 proc MouseWasReleased*(button: MouseButton): bool = button in input.mouseWasReleased proc MouseReleasedButtons*(): set[MouseButton] = input.mouseWasReleased proc MousePosition*(): Vec2f = input.mousePosition proc MousePositionNormalized*(size: (int, int)): Vec2f = result.x = (input.mousePosition.x / float32(size[0])) * 2.0 - 1.0 result.y = (input.mousePosition.y / float32(size[1])) * 2.0 - 1.0 proc MouseMove*(): Vec2f = input.mouseMove proc MouseWheel*(): float32 = input.mouseWheel proc WindowWasResized*(): auto = input.windowWasResized proc WindowIsMinimized*(): auto = input.windowIsMinimized proc LockMouse*(value: bool) = input.lockMouse = value proc HasFocus*(): bool = input.hasFocus # actions as a slight abstraction over raw input type ActionMap = object keyActions: Table[string, set[Key]] mouseActions: Table[string, set[MouseButton]] # warning, shit is not thread safe var actionMap: ActionMap proc MapAction*[T: enum](action: T, key: Key) = if not actionMap.keyActions.contains($action): actionMap.keyActions[$action] = {} actionMap.keyActions[$action].incl key proc MapAction*[T: enum](action: T, button: MouseButton) = if not actionMap.mouseActions.contains($action): actionMap.mouseActions[$action] = {} actionMap.mouseActions[$action].incl button proc MapAction*[T: enum](action: T, keys: openArray[Key|MouseButton]) = for key in keys: MapAction(action, key) proc UnmapAction*[T: enum](action: T, key: Key) = if actionMap.keyActions.contains($action): actionMap.keyActions[$action].excl(key) proc UnmapAction*[T: enum](action: T, button: MouseButton) = if actionMap.mouseActions.contains($action): actionMap.mouseActions[$action].excl(button) proc UnmapAction*[T: enum](action: T) = if actionMap.keyActions.contains($action): actionMap.keyActions[$action] = {} if actionMap.mouseActions.contains($action): actionMap.mouseActions[$action] = {} proc SaveCurrentActionMapping*() = for name, keys in actionMap.keyActions.pairs: SystemStorage.Store(name, keys, table = "input_mapping_key") for name, buttons in actionMap.mouseActions.pairs: SystemStorage.Store(name, buttons, table = "input_mapping_mouse") proc LoadActionMapping*[T]() = reset(actionMap) for name in SystemStorage.List(table = "input_mapping_key"): let action = parseEnum[T](name) let keys = SystemStorage.Load(name, set[Key](), table = "input_mapping_key") for key in keys: MapAction(action, key) proc ActionDown*[T](action: T): bool = if actionMap.keyActions.contains($action): for key in actionMap.keyActions[$action]: if key in input.keyIsDown: return true return false if actionMap.mouseActions.contains($action): for button in actionMap.mouseActions[$action]: if button in input.mouseIsDown: return true return false proc ActionPressed*[T](action: T): bool = if actionMap.keyActions.contains($action): for key in actionMap.keyActions[$action]: if key in input.keyWasPressed: return true elif actionMap.mouseActions.contains($action): for button in actionMap.mouseActions[$action]: if button in input.mouseWasPressed: return true proc ActionReleased*[T](action: T): bool = if actionMap.keyActions.contains($action): for key in actionMap.keyActions[$action]: if key in input.keyWasReleased: return true elif actionMap.mouseActions.contains($action): for button in actionMap.mouseActions[$action]: if button in input.mouseWasReleased: return true proc ActionValue*[T](action: T): float32 = if actionMap.keyActions.contains($action): for key in actionMap.keyActions[$action]: if key in input.keyIsDown: return 1 elif actionMap.mouseActions.contains($action): for button in actionMap.mouseActions[$action]: if button in input.mouseIsDown: return 1