keyboard.monkey2 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. Namespace mojo.input
  2. #Import "native/keyinfo.h"
  3. #Import "native/keyinfo.cpp"
  4. Extern Private
  5. Struct bbKeyInfo
  6. Field name:Void Ptr
  7. Field scanCode:Int
  8. Field keyCode:Int
  9. End
  10. Global bbKeyInfos:bbKeyInfo Ptr
  11. Public
  12. #rem monkeydoc Global instance of the KeyboardDevice class.
  13. #end
  14. Const Keyboard:=New KeyboardDevice
  15. #rem monkeydoc The KeyboardDevice class.
  16. To access the keyboard device, use the global [[Keyboard]] constant.
  17. The keyboard device should only used after a new [[AppInstance]] is created.
  18. All methods that take a `key` parameter can also be combined with 'raw' keys.
  19. A raw key represents the physical location of a key on US keyboards. For example, `Key.Q|Key.Raw` indicates the key at the top left of the
  20. QWERTY keys, as this is where the 'Q' key is on US keyboards.
  21. #end
  22. Class KeyboardDevice
  23. #rem monkeydoc The current state of the modifier keys.
  24. #end
  25. Property Modifiers:Modifier()
  26. Return _modifiers
  27. End
  28. #rem monkeydoc Gets the name of a key.
  29. If `key` is a raw key, returns the name 'printed' on the key, eg: KeyName( Key.W|Key.Raw ) will always return the name of key at the top left of the QWERTY keys.
  30. if `key` is a virtual key, returns the name of the key, eg: KeyName( Key.W ) will always return "W".
  31. #end
  32. Method KeyName:String( key:Key )
  33. If key & Key.Raw
  34. key=TranslateKey( key&~Key.Raw ) & ~Key.Raw
  35. Endif
  36. If key<=Key.None Or key>=Key.Max Return "?????"
  37. Return _names[key]
  38. End
  39. #rem monkeydoc Translates a key to/from a raw key.
  40. If `key` is a raw key, returns the corresponding virtual key.
  41. If `key` is a virtual key, returns the corresponding raw key.
  42. #end
  43. Method TranslateKey:Key( key:Key )
  44. If key & Key.Raw
  45. key&=~Key.Raw
  46. If key<=Key.None Or key>=Key.Max Return Null
  47. #If __TARGET__="emscripten"
  48. Return key
  49. #Else
  50. Local keyCode:=SDL_GetKeyFromScancode( Cast<SDL_Scancode>( _raw2scan[key] ) )
  51. Return KeyCodeToKey( keyCode )
  52. #Endif
  53. Else
  54. If key<=Key.None Or key>=Key.Max Return Null
  55. Local scanCode:=_key2scan[key]
  56. Return _scan2raw[scanCode]
  57. Endif
  58. Return Null
  59. End
  60. #rem monkeydoc Checks the current up/down state of a key.
  61. Returns true if `key` is currently held down.
  62. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  63. @param key Key to check.
  64. #end
  65. Method KeyDown:Bool( key:Key )
  66. Local scode:=ScanCode( key )
  67. Return _keys[scode].down
  68. End
  69. #rem monkeydoc Checks if a key was pressed.
  70. Returns true if `key` was pressed since the last call to KeyPressed with the same key.
  71. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  72. if `repeating` is true, then key repeats are included.
  73. @param key Key to check.
  74. #end
  75. Method KeyPressed:Bool( key:Key,repeating:Bool=False )
  76. Local scode:=ScanCode( key )
  77. If repeating
  78. Local pressed:=_keys[scode].rpressed<>0
  79. _keys[scode].rpressed=0
  80. Return pressed
  81. Endif
  82. Local pressed:=_keys[scode].pressed<>0
  83. _keys[scode].pressed=0
  84. Return pressed
  85. End
  86. #rem monkeydoc Checks if a key was released.
  87. Returns true if `key` was released since the last call to KeyReleased with the same key.
  88. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  89. @param key Key to check.
  90. #end
  91. Method KeyReleased:Bool( key:Key )
  92. Local scode:=ScanCode( key )
  93. Local released:=_keys[scode].released<>0
  94. _keys[scode].released=0
  95. Return released
  96. End
  97. #rem monkeydoc @hidden
  98. #end
  99. Method KeyHit:Bool( key:Key,repeating:Bool=False )
  100. Return KeyPressed( key,repeating )
  101. End
  102. #rem monkeydoc Peeks at the next character in the character queue.
  103. #end
  104. Method PeekChar:Int()
  105. If _charPut=_charGet Return 0
  106. Return _charQueue[_charGet & CHAR_QUEUE_MASK]
  107. End
  108. #rem monkeydoc Gets the next character from the character queue.
  109. #end
  110. Method GetChar:Int()
  111. If _charPut=_charGet Return 0
  112. Local char:=_charQueue[_charGet & CHAR_QUEUE_MASK]
  113. _charGet+=1
  114. Return char
  115. End
  116. #rem monkeydoc Flushes the character queue.
  117. Removes all queued characters in the character queue.
  118. Note that [[AppInstance.ResetPolledInput|App.ResetPolledInput]] also flushes the character queue.
  119. #end
  120. Method FlushChars()
  121. _charPut=0
  122. _charGet=0
  123. End
  124. Internal
  125. Method ScanCode:Int( key:Key )
  126. If key & Key.Raw
  127. key&=~Key.Raw
  128. If key<=0 Or key>=Key.Max Return 0
  129. Return _raw2scan[ key & ~Key.Raw ]
  130. Endif
  131. If key<=0 Or key>=Key.Max Return 0
  132. Return _key2scan[ key ]
  133. End
  134. Method KeyCodeToKey:Key( keyCode:Int )
  135. If (keyCode & $40000000) keyCode=(keyCode & ~$40000000)+$80
  136. If keyCode<=0 Or keyCode>=Int( Key.Max ) Return Null
  137. Return Cast<Key>( keyCode )
  138. End
  139. Method ScanCodeToRawKey:Key( scanCode:Int )
  140. If scanCode<=0 Or scanCode>=512 Return null
  141. Return _scan2raw[ scanCode ]
  142. End
  143. Method Init()
  144. Local p:=bbKeyInfos
  145. While p->name
  146. Local name:=String.FromCString( p->name )
  147. Local scanCode:=p->scanCode
  148. Local keyCode:=p->keyCode
  149. Local key:=KeyCodeToKey( keyCode )
  150. _names[key]=name
  151. _raw2scan[key]=scanCode
  152. _scan2raw[scanCode]=key | Key.Raw
  153. #If __TARGET__="emscripten"
  154. _key2scan[key]=scanCode
  155. #Else
  156. _key2scan[key]=SDL_GetScancodeFromKey( Cast<SDL_Keycode>( keyCode ) )
  157. #Endif
  158. _scan2key[_key2scan[key]]=key
  159. p=p+1
  160. Wend
  161. End
  162. Method Update()
  163. _frame+=1
  164. FlushChars()
  165. End
  166. Method SendEvent( event:SDL_Event Ptr )
  167. Select event->type
  168. Case SDL_KEYDOWN
  169. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  170. 'Update key matrix
  171. '
  172. Local scode:=kevent->keysym.scancode
  173. _keys[scode].down=True
  174. If kevent->repeat_
  175. _keys[scode].rpressed=_frame
  176. Else
  177. _keys[scode].pressed=_frame
  178. _keys[scode].rpressed=_frame
  179. Endif
  180. 'Update modifiers
  181. '
  182. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  183. _modifiers=Cast<Modifier>( kevent->keysym.mod_ )
  184. Select key
  185. Case Key.CapsLock,Key.KeypadNumLock
  186. _modifiers~=KeyToModifier( key )
  187. Default
  188. _modifiers|=KeyToModifier( key )
  189. End
  190. 'Update charqueue
  191. '
  192. Local char:=KeyToChar( _scan2key[scode] )
  193. If char PushChar( char )
  194. Case SDL_KEYUP
  195. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  196. 'Update key matrix
  197. '
  198. Local scode:=kevent->keysym.scancode
  199. _keys[scode].down=False
  200. _keys[scode].released=_frame
  201. 'Update modifiers
  202. '
  203. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  204. Select key
  205. Case Key.CapsLock,Key.KeypadNumLock
  206. Default
  207. _modifiers&=~KeyToModifier( key )
  208. End
  209. Case SDL_TEXTINPUT
  210. Local tevent:=Cast<SDL_TextInputEvent Ptr>( event )
  211. Local text:=String.FromCString( tevent->text )
  212. If text PushChar( text[0] )
  213. End
  214. End
  215. Method Reset()
  216. _charPut=0
  217. _charGet=0
  218. For Local i:=0 Until 512
  219. _keys[i].pressed=0
  220. _keys[i].rpressed=0
  221. _keys[i].released=0
  222. Next
  223. End
  224. Private
  225. Struct KeyState
  226. Field down:Bool
  227. Field pressed:Int 'frame of last keydown received
  228. Field rpressed:Int 'frame of last keydown+repeat received
  229. Field released:Int
  230. End
  231. Const CHAR_QUEUE_SIZE:=32
  232. Const CHAR_QUEUE_MASK:=31
  233. Field _frame:Int=1
  234. Field _keys:=New KeyState[512]
  235. Field _charQueue:=New Int[CHAR_QUEUE_SIZE]
  236. Field _charPut:Int
  237. Field _charGet:Int
  238. Field _modifiers:Modifier
  239. Field _names:=New String[512]
  240. Field _raw2scan:=New Int[512] 'no translate
  241. Field _scan2raw:=New Key[512] 'no translate
  242. Field _key2scan:=New Int[512] 'translate
  243. Field _scan2key:=New Int[512] 'translate
  244. Method New()
  245. End
  246. Function KeyToModifier:Modifier( key:Int )
  247. Select key
  248. Case Key.LeftShift Return Modifier.LeftShift
  249. Case Key.RightShift Return Modifier.RightShift
  250. Case Key.LeftControl Return Modifier.LeftControl
  251. Case Key.RightControl Return Modifier.RightControl
  252. Case Key.LeftAlt Return Modifier.LeftAlt
  253. Case Key.RightAlt Return Modifier.RightAlt
  254. Case Key.LeftGui Return Modifier.LeftGui
  255. Case Key.RightGui Return Modifier.RightGui
  256. Case Key.CapsLock Return Modifier.CapsLock
  257. Case Key.KeypadNumLock Return Modifier.NumLock
  258. End
  259. Return Null
  260. End
  261. Function KeyToChar:Int( key:Int )
  262. Select key
  263. Case Key.Backspace,Key.Tab,Key.Enter,Key.Escape,Key.KeyDelete
  264. Return key
  265. Case Key.PageUp,Key.PageDown,Key.KeyEnd,Key.Home,Key.Left,Key.Up,Key.Right,Key.Down,Key.Insert
  266. Return key | $10000
  267. End
  268. Return 0
  269. End
  270. Method PushChar( char:Int )
  271. If _charPut-_charGet=CHAR_QUEUE_SIZE Return
  272. _charQueue[ _charPut & CHAR_QUEUE_MASK ]=char
  273. _charPut+=1
  274. End
  275. End