summary refs log tree commit diff stats
path: root/tests/manyloc/keineschweine/lib/input_helpers.nim
blob: 120576dfb656ba916ec17f22bc3442022c159dd4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import
  sfml, tables, hashes
type
  TKeyEventKind* = enum down, up
  TInputFinishedProc* = proc() 
  TKeyCallback = proc()
  PKeyClient* = ref object
    onKeyDown: TTable[int32, TKeyCallback]
    onKeyUp: TTable[int32, TKeyCallback]
    name: string
  PTextInput* = ref object
    text*: string
    cursor: int
    onEnter: TInputFinishedProc
var
  keyState:    array[-MouseButtonCount.int32 .. KeyCount.int32, bool]
  mousePos: TVector2f
  activeClient: PKeyClient = nil
  activeInput: PTextInput  = nil

proc setActive*(client: PKeyClient) = 
  activeClient = client
  echo("** set active client ", client.name)
proc newKeyClient*(name: string = "unnamed", setactive = false): PKeyClient =
  new(result)
  result.onKeyDown = initTable[int32, TKeyCallback](16)
  result.onKeyUp   = initTable[int32, TKeyCallback](16)
  result.name = name
  if setActive:
    setActive(result)

proc keyPressed*(key: TKeyCode): bool {.inline.} =
  return keyState[key.int32]
proc buttonPressed*(btn: TMouseButton): bool {.inline.} =
  return keyState[-btn.int32]

proc clearKey*(key: TKeyCode) {.inline.} =
  keyState[key.int32]  = false
proc clearButton*(btn: TMouseButton) {.inline.} =
  keyState[-btn.int32] = false

proc addKeyEvent*(key: TKeyCode, ev: TKeyEventKind) {.inline.} =
  if activeClient.isNil: return
  let k = key.int32
  case ev
  of down: 
    keyState[k] = true
    if activeClient.onKeyDown.hasKey(k):
      activeClient.onKeyDown[k]()
  else:    
    keyState[k] = false
    if activeClient.onKeyUp.hasKey(k):
      activeClient.onKeyUp[k]()
proc addButtonEvent*(btn: TMouseButton, ev: TKeyEventKind) {.inline.} =
  if activeClient.isNil: return 
  let b = -btn.int32
  case ev
  of down: 
    keyState[b] = true 
    if activeClient.onKeyDown.hasKey(b):
      activeClient.onKeyDown[b]()
  else: 
    keyState[b] = false
    if activeClient.onKeyUp.hasKey(b):
      activeClient.onKeyUp[b]()
proc registerHandler*(client: PKeyClient; key: TKeyCode;
                       ev: TKeyEventKind; fn: TKeyCallback) = 
  case ev
  of down: client.onKeyDown[key.int32] = fn
  of up:   client.onKeyUp[key.int32]   = fn
proc registerHandler*(client: PKeyClient; btn: TMouseButton;
                       ev: TKeyEventKind; fn: TKeyCallback) =
  case ev
  of down: client.onKeyDown[-btn.int32] = fn
  of up:   client.onKeyUp[-btn.int32]   = fn

proc newTextInput*(text = "", pos = 0, onEnter: TInputFinishedProc = nil): PTextInput =
  new(result)
  result.text = text
  result.cursor = pos
  result.onEnter = onEnter
proc setActive*(i: PTextInput) =
  activeInput = i
proc stopCapturingText*() =
  activeInput = nil
proc clear*(i: PTextInput) =
  i.text.setLen 0
  i.cursor = 0
proc recordText*(i: PTextInput; c: cint) =
  if c > 127 or i.isNil: return
  if c in 32..126: ##printable
    if i.cursor == i.text.len: i.text.add(c.int.chr)
    else: 
      let rem = i.text.substr(i.cursor)
      i.text.setLen(i.cursor)
      i.text.add(chr(c.int))
      i.text.add(rem)
    inc(i.cursor)
  elif c == 8: ## \b  backspace
    if i.text.len > 0 and i.cursor > 0:
      dec(i.cursor)
      let rem = i.text.substr(i.cursor + 1)
      i.text.setLen(i.cursor)
      i.text.add(rem)
  elif c == 10 or c == 13:## \n, \r  enter
    if not i.onEnter.isNil: i.onEnter()
proc recordText*(i: PTextInput; e: TTextEvent) {.inline.} = 
  recordText(i, e.unicode)

proc setMousePos*(x, y: cint) {.inline.} =
  mousePos.x = x.float
  mousePos.y = y.float
proc getMousePos*(): TVector2f {.inline.} = result = mousePos

var event: TEvent
# Handle and filter input-related events
iterator filterEvents*(window: PRenderWindow): PEvent =
  while window.pollEvent(addr event):
    case event.kind
    of EvtKeyPressed: addKeyEvent(event.key.code, down)
    of EvtKeyReleased: addKeyEvent(event.key.code, up)
    of EvtMouseButtonPressed: addButtonEvent(event.mouseButton.button, down)
    of EvtMouseButtonReleased: addButtonEvent(event.mouseButton.button, up)
    of EvtTextEntered: recordText(activeInput, event.text)
    of EvtMouseMoved: setMousePos(event.mouseMove.x, event.mouseMove.y)
    else: yield(addr event)
# Handle and return input-related events
iterator pollEvents*(window: PRenderWindow): PEvent =
  while window.pollEvent(addr event):
    case event.kind
    of EvtKeyPressed: addKeyEvent(event.key.code, down)
    of EvtKeyReleased: addKeyEvent(event.key.code, up)
    of EvtMouseButtonPressed: addButtonEvent(event.mouseButton.button, down)
    of EvtMouseButtonReleased: addButtonEvent(event.mouseButton.button, up)
    of EvtTextEntered: recordText(activeInput, event.text)
    of EvtMouseMoved: setMousePos(event.mouseMove.x, event.mouseMove.y)
    else: nil
    yield(addr event)