Skip to content

Instantly share code, notes, and snippets.

@cipharius
Created December 8, 2017 07:46
Show Gist options
  • Save cipharius/adf3323a512023727193c2c65582bf90 to your computer and use it in GitHub Desktop.
Save cipharius/adf3323a512023727193c2c65582bf90 to your computer and use it in GitHub Desktop.
Keyboard input actions for SDL2 on Nim
import strutils
import sdl2
type
ListenerPtr = proc (action: Action) {.closure.}
Action* = ref object
active: bool
kind: string
keysyms: seq[cint]
listeners: seq[ListenerPtr]
Listener = ref object
procedure: ListenerPtr
action: Action
OccupiedException = object of Exception
## Raised if object is already taken
var actions: seq[Action] = @[]
# Action methods
method addListener*(this: Action, listener: ListenerPtr): Listener {.discardable,base.} =
## Add action listener procedure
this.listeners.add listener
result = Listener(procedure: listener, action: this)
method bindKey*(this: Action, key: cint) {.base.} =
## Add a new action keybinding
this.keysyms.add key
method unbindKey*(this: Action, key: cint) {.base.} =
## Unbind key from action
for i, k in this.keysyms:
if k == key:
this.keysyms.delete i
break
method kind*(this: Action): string {.base.} = this.kind
method `$`*(this: Action): string {.base.} = this.kind
method isActive*(this: Action): bool {.base.} = this.active
proc setState(this: Action, state: bool) =
this.active = state
for listener in this.listeners:
listener(this)
# Listener methods
method disconnect*(this: Listener) {.base.} =
## Disconnect listener from it's action
for i,listener in this.action.listeners:
if listener == this.procedure:
this.action.listeners.delete i
break
# Generic procedures
proc registerAction*(kind: string): Action {.discardable.} =
## Registers a new action
# Check if action is already registered
for action in actions:
if action.kind == kind:
raise newException(OccupiedException, "Duplicate action \"$#\"" % kind)
result = Action(kind: kind, active: false, listeners: @[], keysyms: @[])
actions.add result
proc handleInput*(event: KeyboardEventPtr) =
for action in actions:
for keysym in action.keysyms:
if event.keysym.sym == keysym:
action.setState event.state == KeyPressed.uint8
proc getAction*(kind: string): Action =
## Retrieve already registered action
for action in actions:
if action.kind == kind:
return action
return nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment