keyboard.monkey2 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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=_frame
  79. _keys[scode].rpressed=0
  80. Return pressed
  81. Endif
  82. Local pressed:=_keys[scode].pressed=_frame
  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=_frame
  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. #rem monkeydoc Flushes all keyboard input.
  125. #end
  126. Method FlushKeys()
  127. FlushChars()
  128. _frame+=1
  129. End
  130. Internal
  131. Method ScanCode:Int( key:Key )
  132. If key & Key.Raw
  133. key&=~Key.Raw
  134. If key<=0 Or key>=Key.Max Return 0
  135. Return _raw2scan[ key & ~Key.Raw ]
  136. Endif
  137. If key<=0 Or key>=Key.Max Return 0
  138. Return _key2scan[ key ]
  139. End
  140. Method KeyCodeToKey:Key( keyCode:Int )
  141. If (keyCode & $40000000) keyCode=(keyCode & ~$40000000)+$80
  142. If keyCode<=0 Or keyCode>=Int( Key.Max ) Return Null
  143. Return Cast<Key>( keyCode )
  144. End
  145. Method ScanCodeToRawKey:Key( scanCode:Int )
  146. If scanCode<=0 Or scanCode>=512 Return null
  147. Return _scan2raw[ scanCode ]
  148. End
  149. Method Init()
  150. Local p:=bbKeyInfos
  151. While p->name
  152. Local name:=String.FromCString( p->name )
  153. Local scanCode:=p->scanCode
  154. Local keyCode:=p->keyCode
  155. Local key:=KeyCodeToKey( keyCode )
  156. _names[key]=name
  157. _raw2scan[key]=scanCode
  158. _scan2raw[scanCode]=key | Key.Raw
  159. #If __TARGET__="emscripten"
  160. _key2scan[key]=scanCode
  161. #Else
  162. _key2scan[key]=SDL_GetScancodeFromKey( Cast<SDL_Keycode>( keyCode ) )
  163. #Endif
  164. _scan2key[_key2scan[key]]=key
  165. p=p+1
  166. Wend
  167. End
  168. Method Update()
  169. End
  170. Method SendEvent( event:SDL_Event Ptr )
  171. Select event->type
  172. Case SDL_KEYDOWN
  173. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  174. 'Update key matrix
  175. '
  176. Local scode:=kevent->keysym.scancode
  177. _keys[scode].down=True
  178. If kevent->repeat_
  179. _keys[scode].rpressed=_frame
  180. Else
  181. _keys[scode].pressed=_frame
  182. _keys[scode].rpressed=_frame
  183. Endif
  184. 'Update modifiers
  185. '
  186. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  187. _modifiers=Cast<Modifier>( kevent->keysym.mod_ )
  188. Select key
  189. Case Key.CapsLock,Key.KeypadNumLock
  190. _modifiers~=KeyToModifier( key )
  191. Default
  192. _modifiers|=KeyToModifier( key )
  193. End
  194. 'Update charqueue
  195. '
  196. Local char:=KeyToChar( _scan2key[scode] )
  197. If char PushChar( char )
  198. Case SDL_KEYUP
  199. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  200. 'Update key matrix
  201. '
  202. Local scode:=kevent->keysym.scancode
  203. _keys[scode].down=False
  204. _keys[scode].released=_frame
  205. 'Update modifiers
  206. '
  207. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  208. Select key
  209. Case Key.CapsLock,Key.KeypadNumLock
  210. Default
  211. _modifiers&=~KeyToModifier( key )
  212. End
  213. Case SDL_TEXTINPUT
  214. Local tevent:=Cast<SDL_TextInputEvent Ptr>( event )
  215. Local text:=String.FromCString( tevent->text )
  216. If text PushChar( text[0] )
  217. End
  218. End
  219. Method Reset()
  220. _charPut=0
  221. _charGet=0
  222. For Local i:=0 Until 512
  223. _keys[i].pressed=0
  224. _keys[i].rpressed=0
  225. _keys[i].released=0
  226. Next
  227. End
  228. Private
  229. Struct KeyState
  230. Field down:Bool
  231. Field pressed:Int 'frame of last keydown received
  232. Field rpressed:Int 'frame of last keydown+repeat received
  233. Field released:Int
  234. End
  235. Const CHAR_QUEUE_SIZE:=32
  236. Const CHAR_QUEUE_MASK:=31
  237. Field _frame:Int=1
  238. Field _keys:=New KeyState[512]
  239. Field _charQueue:=New Int[CHAR_QUEUE_SIZE]
  240. Field _charPut:Int
  241. Field _charGet:Int
  242. Field _modifiers:Modifier
  243. Field _names:=New String[512]
  244. Field _raw2scan:=New Int[512] 'no translate
  245. Field _scan2raw:=New Key[512] 'no translate
  246. Field _key2scan:=New Int[512] 'translate
  247. Field _scan2key:=New Int[512] 'translate
  248. Method New()
  249. End
  250. Function KeyToModifier:Modifier( key:Int )
  251. Select key
  252. Case Key.LeftShift Return Modifier.LeftShift
  253. Case Key.RightShift Return Modifier.RightShift
  254. Case Key.LeftControl Return Modifier.LeftControl
  255. Case Key.RightControl Return Modifier.RightControl
  256. Case Key.LeftAlt Return Modifier.LeftAlt
  257. Case Key.RightAlt Return Modifier.RightAlt
  258. Case Key.LeftGui Return Modifier.LeftGui
  259. Case Key.RightGui Return Modifier.RightGui
  260. Case Key.CapsLock Return Modifier.CapsLock
  261. Case Key.KeypadNumLock Return Modifier.NumLock
  262. End
  263. Return Null
  264. End
  265. Function KeyToChar:Int( key:Int )
  266. Select key
  267. Case Key.Backspace,Key.Tab,Key.Enter,Key.Escape,Key.KeyDelete
  268. Return key
  269. Case Key.PageUp,Key.PageDown,Key.KeyEnd,Key.Home,Key.Left,Key.Up,Key.Right,Key.Down,Key.Insert
  270. Return key | $10000
  271. End
  272. Return 0
  273. End
  274. Method PushChar( char:Int )
  275. If _charPut-_charGet=CHAR_QUEUE_SIZE Return
  276. _charQueue[ _charPut & CHAR_QUEUE_MASK ]=char
  277. _charPut+=1
  278. End
  279. End