keyboard.monkey2 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. End
  29. #rem monkeydoc Gets the name of a key.
  30. If `key` is a raw key, returns the name 'printed' on that key.
  31. if `key` is a virtual key
  32. #end
  33. Method KeyName:String( key:Key )
  34. If key & key.Raw key=TranslateKey( key )
  35. Return _names[key]
  36. End
  37. #rem monkeydoc Translates a key to/from a raw key.
  38. If `key` is a raw key, returns the corresponding virual key.
  39. If `key` is a virtual key, returns the corresponding raw key.
  40. #end
  41. Method TranslateKey:Key( key:Key )
  42. If key & Key.Raw
  43. #If __TARGET__="emscripten"
  44. Return key & ~Key.Raw
  45. #Else
  46. Local keyCode:=SDL_GetKeyFromScancode( Cast<SDL_Scancode>( _raw2scan[ key & ~Key.Raw ] ) )
  47. Return KeyCodeToKey( keyCode )
  48. #Endif
  49. Else
  50. Local scanCode:=_key2scan[key]
  51. Return _scan2raw[scanCode]
  52. Endif
  53. Return Key.None
  54. End
  55. #rem monkeydoc Checks the current up/down state of a key.
  56. Returns true if `key` is currently held down.
  57. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  58. @param key Key to check.
  59. #end
  60. Method KeyDown:Bool( key:Key )
  61. Local scode:=ScanCode( key )
  62. Return _keys[scode].down
  63. End
  64. #rem monkeydoc Checks if a key was pressed.
  65. Returns true if `key` was pressed since the last call to KeyPressed with the same key.
  66. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  67. @param key Key to check.
  68. #end
  69. Method KeyPressed:Bool( key:Key,repeating:Bool=False )
  70. Local scode:=ScanCode( key )
  71. If repeating Return _keys[scode].rpressed=_frame
  72. Return _keys[scode].pressed=_frame
  73. End
  74. #rem monkeydoc Checks if a key was released.
  75. Returns true if `key` was released since the last call to KeyReleased 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 KeyReleased:Bool( key:Key )
  80. Local scode:=ScanCode( key )
  81. Return _keys[scode].released=_frame
  82. End
  83. #rem monkeydoc @hidden
  84. #end
  85. Method KeyHit:Bool( key:Key,repeating:Bool=False )
  86. Return KeyPressed( key,repeating )
  87. End
  88. #rem monkeydoc Peeks at the next character in the character queue.
  89. #end
  90. Method PeekChar:Int()
  91. If _charPut=_charGet Return 0
  92. Return _charQueue[_charGet & CHAR_QUEUE_MASK]
  93. End
  94. #rem monkeydoc Gets the next character from the character queue.
  95. #end
  96. Method GetChar:Int()
  97. If _charPut=_charGet Return 0
  98. Local char:=_charQueue[_charGet & CHAR_QUEUE_MASK]
  99. _charGet+=1
  100. Return char
  101. End
  102. #rem monkeydoc Flushes the character queue.
  103. #end
  104. Method FlushChars()
  105. _charPut=0
  106. _charGet=0
  107. End
  108. '***** Internal *****
  109. #rem monkeydoc @hidden
  110. #end
  111. Method ScanCode:Int( key:Key )
  112. If key & Key.Raw Return _raw2scan[ key & ~Key.Raw ]
  113. Return _key2scan[ key ]
  114. End
  115. #rem monkeydoc @hidden
  116. #end
  117. Method KeyCodeToKey:Key( keyCode:Int )
  118. If (keyCode & $40000000) keyCode=(keyCode & ~$40000000)+$80
  119. Return Cast<Key>( keyCode )
  120. End
  121. #rem monkeydoc @hidden
  122. #end
  123. Method ScanCodeToRawKey:Key( scanCode:Int )
  124. Return _scan2raw[ scanCode ]
  125. End
  126. #rem monkeydoc @hidden
  127. #end
  128. Method Init()
  129. Local p:=bbKeyInfos
  130. While p->name
  131. Local name:=String.FromCString( p->name )
  132. Local scanCode:=p->scanCode
  133. Local keyCode:=p->keyCode
  134. Local key:=KeyCodeToKey( keyCode )
  135. _names[key]=name
  136. _raw2scan[key]=scanCode
  137. _scan2raw[scanCode]=key | Key.Raw
  138. #If __TARGET__="emscripten"
  139. _key2scan[key]=scanCode
  140. #Else
  141. _key2scan[key]=SDL_GetScancodeFromKey( Cast<SDL_Keycode>( keyCode ) )
  142. #Endif
  143. _scan2key[_key2scan[key]]=key
  144. p=p+1
  145. Wend
  146. End
  147. #rem monkeydoc @hidden
  148. #end
  149. Method Update()
  150. _frame+=1
  151. FlushChars()
  152. End
  153. #rem monkeydoc @hidden
  154. #end
  155. Method SendEvent( event:SDL_Event Ptr )
  156. Select event->type
  157. Case SDL_KEYDOWN
  158. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  159. Local scode:=kevent->keysym.scancode
  160. _keys[scode].down=True
  161. If kevent->repeat_
  162. _keys[scode].rpressed=_frame
  163. Else
  164. _keys[scode].pressed=_frame
  165. _keys[scode].rpressed=_frame
  166. Endif
  167. _modifiers=Cast<Modifier>( kevent->keysym.mod_ )
  168. Local char:=KeyToChar( _scan2key[scode] )
  169. If char PushChar( char )
  170. Case SDL_KEYUP
  171. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  172. Local scode:=kevent->keysym.scancode
  173. _keys[scode].down=False
  174. _keys[scode].released=_frame
  175. _modifiers=Cast<Modifier>( kevent->keysym.mod_ )
  176. Case SDL_TEXTINPUT
  177. Local tevent:=Cast<SDL_TextInputEvent Ptr>( event )
  178. Local char:=tevent->text[0]
  179. If char PushChar( char )
  180. End
  181. End
  182. Private
  183. Struct KeyState
  184. Field down:Bool
  185. Field pressed:Int 'frame of last keydown received
  186. Field rpressed:Int 'frame of last keydown+repeat received
  187. Field released:Int
  188. End
  189. Const CHAR_QUEUE_SIZE:=32
  190. Const CHAR_QUEUE_MASK:=31
  191. Field _frame:Int=1
  192. Field _keys:=New KeyState[512]
  193. Field _modifiers:Modifier
  194. Field _charQueue:=New Int[CHAR_QUEUE_SIZE]
  195. Field _charPut:Int
  196. Field _charGet:Int
  197. Field _names:=New String[512]
  198. Field _raw2scan:=New Int[512] 'no translate
  199. Field _scan2raw:=New Key[512] 'no translate
  200. Field _key2scan:=New Int[512] 'translate
  201. Field _scan2key:=New Int[512] 'translate
  202. Method New()
  203. End
  204. Function KeyToChar:Int( key:Int )
  205. Select key
  206. Case Key.Backspace,Key.Tab,Key.Enter,Key.Escape,Key.KeyDelete
  207. Return key
  208. Case Key.PageUp,Key.PageDown,Key.KeyEnd,Key.Home,Key.Left,Key.Up,Key.Right,Key.Down,Key.Insert
  209. Return key | $10000
  210. End
  211. Return 0
  212. End
  213. Method PushChar( char:Int )
  214. If _charPut-_charGet=CHAR_QUEUE_SIZE Return
  215. _charQueue[ _charPut & CHAR_QUEUE_MASK ]=char
  216. _charPut+=1
  217. End
  218. End