keyboard.monkey2 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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 Gets the key by a given name.
  40. #end
  41. Method KeyFromName:Key( name:String )
  42. For Local i:=0 Until _names.Length
  43. If _names[i]=name
  44. Return Cast<Key>( i )
  45. Endif
  46. Next
  47. Return Key.None
  48. End
  49. #rem monkeydoc Translates a key to/from a raw key.
  50. If `key` is a raw key, returns the corresponding virtual key.
  51. If `key` is a virtual key, returns the corresponding raw key.
  52. #end
  53. Method TranslateKey:Key( key:Key )
  54. If key & Key.Raw
  55. key&=~Key.Raw
  56. If key<=Key.None Or key>=Key.Max Return Null
  57. #If __TARGET__="emscripten"
  58. Return key
  59. #Else
  60. Local keyCode:=SDL_GetKeyFromScancode( Cast<SDL_Scancode>( _raw2scan[key] ) )
  61. Return KeyCodeToKey( keyCode )
  62. #Endif
  63. Else
  64. If key<=Key.None Or key>=Key.Max Return Null
  65. Local scanCode:=_key2scan[key]
  66. Return _scan2raw[scanCode]
  67. Endif
  68. Return Null
  69. End
  70. #rem monkeydoc Checks the current up/down state of a key.
  71. Returns true if `key` is currently held down.
  72. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  73. @param key Key to check.
  74. #end
  75. Method KeyDown:Bool( key:Key )
  76. Local scode:=ScanCode( key )
  77. Return _keys[scode].down
  78. End
  79. #rem monkeydoc Checks if a key was pressed.
  80. Returns true if `key` was pressed since the last call to KeyPressed with the same key.
  81. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  82. if `repeating` is true, then key repeats are included.
  83. @param key Key to check.
  84. #end
  85. Method KeyPressed:Bool( key:Key,repeating:Bool=False )
  86. Local scode:=ScanCode( key )
  87. If repeating
  88. Local pressed:=_keys[scode].rpressed=_frame
  89. _keys[scode].rpressed=0
  90. Return pressed
  91. Endif
  92. Local pressed:=_keys[scode].pressed=_frame
  93. _keys[scode].pressed=0
  94. Return pressed
  95. End
  96. #rem monkeydoc Checks if a key was released.
  97. Returns true if `key` was released since the last call to KeyReleased with the same key.
  98. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  99. @param key Key to check.
  100. #end
  101. Method KeyReleased:Bool( key:Key )
  102. Local scode:=ScanCode( key )
  103. Local released:=_keys[scode].released=_frame
  104. _keys[scode].released=0
  105. Return released
  106. End
  107. #rem monkeydoc @hidden
  108. #end
  109. Method KeyHit:Bool( key:Key,repeating:Bool=False )
  110. Return KeyPressed( key,repeating )
  111. End
  112. #rem monkeydoc Peeks at the next character in the character queue.
  113. #end
  114. Method PeekChar:Int()
  115. If _charPut=_charGet Return 0
  116. Return _charQueue[_charGet & CHAR_QUEUE_MASK]
  117. End
  118. #rem monkeydoc Gets the next character from the character queue.
  119. #end
  120. Method GetChar:Int()
  121. If _charPut=_charGet Return 0
  122. Local char:=_charQueue[_charGet & CHAR_QUEUE_MASK]
  123. _charGet+=1
  124. Return char
  125. End
  126. #rem monkeydoc Flushes the character queue.
  127. Removes all queued characters in the character queue.
  128. Note that [[AppInstance.ResetPolledInput|App.ResetPolledInput]] also flushes the character queue.
  129. #end
  130. Method FlushChars()
  131. _charPut=0
  132. _charGet=0
  133. End
  134. #rem monkeydoc Flushes all keyboard input.
  135. #end
  136. Method FlushKeys()
  137. FlushChars()
  138. _frame+=1
  139. End
  140. Internal
  141. Method ScanCode:Int( key:Key )
  142. If key & Key.Raw
  143. key&=~Key.Raw
  144. If key<=0 Or key>=Key.Max Return 0
  145. Return _raw2scan[ key & ~Key.Raw ]
  146. Endif
  147. If key<=0 Or key>=Key.Max Return 0
  148. Return _key2scan[ key ]
  149. End
  150. Method KeyCodeToKey:Key( keyCode:Int )
  151. If (keyCode & $40000000) keyCode=(keyCode & ~$40000000)+$80
  152. If keyCode<=0 Or keyCode>=Int( Key.Max ) Return Null
  153. Return Cast<Key>( keyCode )
  154. End
  155. Method ScanCodeToRawKey:Key( scanCode:Int )
  156. If scanCode<=0 Or scanCode>=512 Return null
  157. Return _scan2raw[ scanCode ]
  158. End
  159. Method Init()
  160. Local p:=bbKeyInfos
  161. While p->name
  162. Local name:=String.FromCString( p->name )
  163. Local scanCode:=p->scanCode
  164. Local keyCode:=p->keyCode
  165. Local key:=KeyCodeToKey( keyCode )
  166. _names[key]=name
  167. _raw2scan[key]=scanCode
  168. _scan2raw[scanCode]=key | Key.Raw
  169. #If __TARGET__="emscripten"
  170. _key2scan[key]=scanCode
  171. #Else
  172. _key2scan[key]=SDL_GetScancodeFromKey( Cast<SDL_Keycode>( keyCode ) )
  173. #Endif
  174. _scan2key[_key2scan[key]]=key
  175. p=p+1
  176. Wend
  177. End
  178. Method Update()
  179. End
  180. Method SendEvent( event:SDL_Event Ptr )
  181. Select event->type
  182. Case SDL_KEYDOWN
  183. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  184. 'Update key matrix
  185. '
  186. Local scode:=kevent->keysym.scancode
  187. _keys[scode].down=True
  188. If kevent->repeat_
  189. _keys[scode].rpressed=_frame
  190. Else
  191. _keys[scode].pressed=_frame
  192. _keys[scode].rpressed=_frame
  193. Endif
  194. 'Update modifiers
  195. '
  196. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  197. _modifiers=Cast<Modifier>( kevent->keysym.mod_ )
  198. Select key
  199. Case Key.CapsLock,Key.KeypadNumLock
  200. _modifiers~=KeyToModifier( key )
  201. Default
  202. _modifiers|=KeyToModifier( key )
  203. End
  204. 'Update charqueue
  205. '
  206. Local char:=KeyToChar( _scan2key[scode] )
  207. If char PushChar( char )
  208. Case SDL_KEYUP
  209. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  210. 'Update key matrix
  211. '
  212. Local scode:=kevent->keysym.scancode
  213. _keys[scode].down=False
  214. _keys[scode].released=_frame
  215. 'Update modifiers
  216. '
  217. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  218. Select key
  219. Case Key.CapsLock,Key.KeypadNumLock
  220. Default
  221. _modifiers&=~KeyToModifier( key )
  222. End
  223. Case SDL_TEXTINPUT
  224. Local tevent:=Cast<SDL_TextInputEvent Ptr>( event )
  225. Local text:=String.FromCString( tevent->text )
  226. If text PushChar( text[0] )
  227. End
  228. End
  229. Method Reset()
  230. _charPut=0
  231. _charGet=0
  232. For Local i:=0 Until 512
  233. _keys[i].pressed=0
  234. _keys[i].rpressed=0
  235. _keys[i].released=0
  236. Next
  237. End
  238. Private
  239. Struct KeyState
  240. Field down:Bool
  241. Field pressed:Int 'frame of last keydown received
  242. Field rpressed:Int 'frame of last keydown+repeat received
  243. Field released:Int
  244. End
  245. Const CHAR_QUEUE_SIZE:=32
  246. Const CHAR_QUEUE_MASK:=31
  247. Field _frame:Int=1
  248. Field _keys:=New KeyState[512]
  249. Field _charQueue:=New Int[CHAR_QUEUE_SIZE]
  250. Field _charPut:Int
  251. Field _charGet:Int
  252. Field _modifiers:Modifier
  253. Field _names:=New String[512]
  254. Field _raw2scan:=New Int[512] 'no translate
  255. Field _scan2raw:=New Key[512] 'no translate
  256. Field _key2scan:=New Int[512] 'translate
  257. Field _scan2key:=New Int[512] 'translate
  258. Method New()
  259. End
  260. Function KeyToModifier:Modifier( key:Int )
  261. Select key
  262. Case Key.LeftShift Return Modifier.LeftShift
  263. Case Key.RightShift Return Modifier.RightShift
  264. Case Key.LeftControl Return Modifier.LeftControl
  265. Case Key.RightControl Return Modifier.RightControl
  266. Case Key.LeftAlt Return Modifier.LeftAlt
  267. Case Key.RightAlt Return Modifier.RightAlt
  268. Case Key.LeftGui Return Modifier.LeftGui
  269. Case Key.RightGui Return Modifier.RightGui
  270. Case Key.CapsLock Return Modifier.CapsLock
  271. Case Key.KeypadNumLock Return Modifier.NumLock
  272. End
  273. Return Null
  274. End
  275. Function KeyToChar:Int( key:Int )
  276. Select key
  277. Case Key.Backspace,Key.Tab,Key.Enter,Key.Escape,Key.KeyDelete
  278. Return key
  279. Case Key.PageUp,Key.PageDown,Key.KeyEnd,Key.Home,Key.Left,Key.Up,Key.Right,Key.Down,Key.Insert
  280. Return key | $10000
  281. End
  282. Return 0
  283. End
  284. Method PushChar( char:Int )
  285. If _charPut-_charGet=CHAR_QUEUE_SIZE Return
  286. _charQueue[ _charPut & CHAR_QUEUE_MASK ]=char
  287. _charPut+=1
  288. End
  289. End