keyboard.monkey2 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. All method that take a `key` parameter can also be used with 'raw' keys.
  17. 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
  18. 'qwerty' keys regardless of the current keyboard layout.
  19. Please see the [[Key]] enum for more information on raw keys.
  20. To access the keyboard device, use the global [[Keyboard]] constant.
  21. The keyboard device should only used after a new [[app.AppInstance]] is created.
  22. #end
  23. Class KeyboardDevice Extends InputDevice
  24. #rem monkeydoc The current state of the modifier keys.
  25. #end
  26. Property Modifiers:Modifier()
  27. Return _modifiers
  28. ' Return Cast<Modifier>( Int( SDL_GetModState() ) )
  29. End
  30. #rem monkeydoc Gets the name of a key.
  31. If `key` is a raw key, returns the name 'printed' on that key.
  32. if `key` is a virtual key
  33. #end
  34. Method KeyName:String( key:Key )
  35. If key & key.Raw
  36. key&=~Key.Raw
  37. If key<=Key.None Or key>=Key.Max Return "?????"
  38. key=TranslateKey( key )
  39. Else
  40. If key<=Key.None Or key>=Key.Max Return "?????"
  41. Endif
  42. Return _names[key]
  43. End
  44. #rem monkeydoc Translates a key to/from a raw key.
  45. If `key` is a raw key, returns the corresponding virual key.
  46. If `key` is a virtual key, returns the corresponding raw key.
  47. #end
  48. Method TranslateKey:Key( key:Key )
  49. If key & Key.Raw
  50. key&=~Key.Raw
  51. If key<=Key.None Or key>=Key.Max Return Null
  52. #If __TARGET__="emscripten"
  53. Return key
  54. #Else
  55. Local keyCode:=SDL_GetKeyFromScancode( Cast<SDL_Scancode>( _raw2scan[key] ) )
  56. Return KeyCodeToKey( keyCode )
  57. #Endif
  58. Else
  59. If key<=Key.None Or key>=Key.Max Return Null
  60. Local scanCode:=_key2scan[key]
  61. Return _scan2raw[scanCode]
  62. Endif
  63. Return Null
  64. End
  65. #rem monkeydoc Checks the current up/down state of a key.
  66. Returns true if `key` is currently held down.
  67. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  68. @param key Key to check.
  69. #end
  70. Method KeyDown:Bool( key:Key )
  71. Local scode:=ScanCode( key )
  72. Return _keys[scode].down
  73. End
  74. #rem monkeydoc Checks if a key was pressed.
  75. Returns true if `key` was pressed since the last call to KeyPressed with the same key.
  76. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  77. @param key Key to check.
  78. #end
  79. Method KeyPressed:Bool( key:Key,repeating:Bool=False )
  80. Local scode:=ScanCode( key )
  81. If repeating Return _keys[scode].rpressed=_frame
  82. Return _keys[scode].pressed=_frame
  83. End
  84. #rem monkeydoc Checks if a key was released.
  85. Returns true if `key` was released since the last call to KeyReleased with the same key.
  86. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  87. @param key Key to check.
  88. #end
  89. Method KeyReleased:Bool( key:Key )
  90. Local scode:=ScanCode( key )
  91. Return _keys[scode].released=_frame
  92. End
  93. #rem monkeydoc @hidden
  94. #end
  95. Method KeyHit:Bool( key:Key,repeating:Bool=False )
  96. Return KeyPressed( key,repeating )
  97. End
  98. #rem monkeydoc Peeks at the next character in the character queue.
  99. #end
  100. Method PeekChar:Int()
  101. If _charPut=_charGet Return 0
  102. Return _charQueue[_charGet & CHAR_QUEUE_MASK]
  103. End
  104. #rem monkeydoc Gets the next character from the character queue.
  105. #end
  106. Method GetChar:Int()
  107. If _charPut=_charGet Return 0
  108. Local char:=_charQueue[_charGet & CHAR_QUEUE_MASK]
  109. _charGet+=1
  110. Return char
  111. End
  112. #rem monkeydoc Flushes the character queue.
  113. #end
  114. Method FlushChars()
  115. _charPut=0
  116. _charGet=0
  117. End
  118. '***** Internal *****
  119. #rem monkeydoc @hidden
  120. #end
  121. Method ScanCode:Int( key:Key )
  122. If key & Key.Raw
  123. key&=~Key.Raw
  124. If key<=0 Or key>=Key.Max Return 0
  125. Return _raw2scan[ key & ~Key.Raw ]
  126. Endif
  127. If key<=0 Or key>=Key.Max Return 0
  128. Return _key2scan[ key ]
  129. End
  130. #rem monkeydoc @hidden
  131. #end
  132. Method KeyCodeToKey:Key( keyCode:Int )
  133. If (keyCode & $40000000) keyCode=(keyCode & ~$40000000)+$80
  134. If keyCode<=0 Or keyCode>=Int( Key.Max ) Return Null
  135. Return Cast<Key>( keyCode )
  136. End
  137. #rem monkeydoc @hidden
  138. #end
  139. Method ScanCodeToRawKey:Key( scanCode:Int )
  140. If scanCode<=0 Or scanCode>=512 Return null
  141. Return _scan2raw[ scanCode ]
  142. End
  143. #rem monkeydoc @hidden
  144. #end
  145. Method Init()
  146. Local p:=bbKeyInfos
  147. While p->name
  148. Local name:=String.FromCString( p->name )
  149. Local scanCode:=p->scanCode
  150. Local keyCode:=p->keyCode
  151. Local key:=KeyCodeToKey( keyCode )
  152. _names[key]=name
  153. _raw2scan[key]=scanCode
  154. _scan2raw[scanCode]=key | Key.Raw
  155. #If __TARGET__="emscripten"
  156. _key2scan[key]=scanCode
  157. #Else
  158. _key2scan[key]=SDL_GetScancodeFromKey( Cast<SDL_Keycode>( keyCode ) )
  159. #Endif
  160. _scan2key[_key2scan[key]]=key
  161. p=p+1
  162. Wend
  163. End
  164. #rem monkeydoc @hidden
  165. #end
  166. Method Update()
  167. _frame+=1
  168. FlushChars()
  169. End
  170. #rem monkeydoc @hidden
  171. #end
  172. Method SendEvent( event:SDL_Event Ptr )
  173. Select event->type
  174. Case SDL_KEYDOWN
  175. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  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. Local char:=KeyToChar( _scan2key[scode] )
  185. If char PushChar( char )
  186. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  187. _modifiers|=KeyToModifier( key )
  188. Case SDL_KEYUP
  189. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  190. Local scode:=kevent->keysym.scancode
  191. _keys[scode].down=False
  192. _keys[scode].released=_frame
  193. Local key:=KeyCodeToKey( Int( kevent->keysym.sym ) )
  194. _modifiers&=~KeyToModifier( key )
  195. Case SDL_TEXTINPUT
  196. Local tevent:=Cast<SDL_TextInputEvent Ptr>( event )
  197. Local char:=tevent->text[0]
  198. If char PushChar( char )
  199. End
  200. End
  201. Private
  202. Struct KeyState
  203. Field down:Bool
  204. Field pressed:Int 'frame of last keydown received
  205. Field rpressed:Int 'frame of last keydown+repeat received
  206. Field released:Int
  207. End
  208. Const CHAR_QUEUE_SIZE:=32
  209. Const CHAR_QUEUE_MASK:=31
  210. Field _frame:Int=1
  211. Field _keys:=New KeyState[512]
  212. Field _charQueue:=New Int[CHAR_QUEUE_SIZE]
  213. Field _charPut:Int
  214. Field _charGet:Int
  215. Field _modifiers:Modifier
  216. Field _names:=New String[512]
  217. Field _raw2scan:=New Int[512] 'no translate
  218. Field _scan2raw:=New Key[512] 'no translate
  219. Field _key2scan:=New Int[512] 'translate
  220. Field _scan2key:=New Int[512] 'translate
  221. Method New()
  222. End
  223. Function KeyToModifier:Modifier( key:Int )
  224. Select key
  225. Case Key.LeftShift Return Modifier.LeftShift
  226. Case Key.RightShift Return Modifier.RightShift
  227. Case Key.LeftControl Return Modifier.LeftControl
  228. Case Key.RightControl Return Modifier.RightControl
  229. Case Key.LeftAlt Return Modifier.LeftAlt
  230. Case Key.RightAlt Return Modifier.RightAlt
  231. Case Key.LeftGui Return Modifier.LeftGui
  232. Case Key.RightGui Return Modifier.RightGui
  233. ' Case Key.CapsLock Return Modifier.CapsLock 'Doesn't really work - here or in SDL...Also, need to find Key.NumLock, not in sdl headers...
  234. End
  235. Return Null
  236. End
  237. Function KeyToChar:Int( key:Int )
  238. Select key
  239. Case Key.Backspace,Key.Tab,Key.Enter,Key.Escape,Key.KeyDelete
  240. Return key
  241. Case Key.PageUp,Key.PageDown,Key.KeyEnd,Key.Home,Key.Left,Key.Up,Key.Right,Key.Down,Key.Insert
  242. Return key | $10000
  243. End
  244. Return 0
  245. End
  246. Method PushChar( char:Int )
  247. If _charPut-_charGet=CHAR_QUEUE_SIZE Return
  248. _charQueue[ _charPut & CHAR_QUEUE_MASK ]=char
  249. _charPut+=1
  250. End
  251. End