lovr-keyboard.lua 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. local ffi = assert(type(jit) == 'table' and -- Only run if we have LuaJIT
  2. lovr.system.getOS() ~= 'Android' and lovr.system.getOS() ~= 'Web' and -- and also GLFW
  3. require 'ffi', "lovr-keyboard cannot run on this platform")
  4. local C = ffi.os == 'Windows' and ffi.load('glfw3') or ffi.C
  5. ffi.cdef [[
  6. typedef struct GLFWwindow GLFWwindow;
  7. typedef void(*GLFWkeyfun)(GLFWwindow*, int, int, int, int);
  8. typedef void(*GLFWcharfun)(GLFWwindow*, unsigned int);
  9. GLFWwindow* os_get_glfw_window(void);
  10. int glfwGetKey(GLFWwindow* window, int key);
  11. GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback);
  12. GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun callback);
  13. ]]
  14. local window = ffi.C.os_get_glfw_window()
  15. local keymap = {
  16. ['space'] = { 32, 0, 0 },
  17. ['\''] = { 39, 0, 0 },
  18. [','] = { 44, 0, 0 },
  19. ['-'] = { 45, 0, 0 },
  20. ['.'] = { 46, 0, 0 },
  21. ['/'] = { 47, 0, 0 },
  22. ['0'] = { 48, 0, 0 },
  23. ['1'] = { 49, 0, 0 },
  24. ['2'] = { 50, 0, 0 },
  25. ['3'] = { 51, 0, 0 },
  26. ['4'] = { 52, 0, 0 },
  27. ['5'] = { 53, 0, 0 },
  28. ['6'] = { 54, 0, 0 },
  29. ['7'] = { 55, 0, 0 },
  30. ['8'] = { 56, 0, 0 },
  31. ['9'] = { 57, 0, 0 },
  32. [';'] = { 59, 0, 0 },
  33. ['='] = { 61, 0, 0 },
  34. ['a'] = { 65, 0, 0 },
  35. ['b'] = { 66, 0, 0 },
  36. ['c'] = { 67, 0, 0 },
  37. ['d'] = { 68, 0, 0 },
  38. ['e'] = { 69, 0, 0 },
  39. ['f'] = { 70, 0, 0 },
  40. ['g'] = { 71, 0, 0 },
  41. ['h'] = { 72, 0, 0 },
  42. ['i'] = { 73, 0, 0 },
  43. ['j'] = { 74, 0, 0 },
  44. ['k'] = { 75, 0, 0 },
  45. ['l'] = { 76, 0, 0 },
  46. ['m'] = { 77, 0, 0 },
  47. ['n'] = { 78, 0, 0 },
  48. ['o'] = { 79, 0, 0 },
  49. ['p'] = { 80, 0, 0 },
  50. ['q'] = { 81, 0, 0 },
  51. ['r'] = { 82, 0, 0 },
  52. ['s'] = { 83, 0, 0 },
  53. ['t'] = { 84, 0, 0 },
  54. ['u'] = { 85, 0, 0 },
  55. ['v'] = { 86, 0, 0 },
  56. ['w'] = { 87, 0, 0 },
  57. ['x'] = { 88, 0, 0 },
  58. ['y'] = { 89, 0, 0 },
  59. ['z'] = { 90, 0, 0 },
  60. ['['] = { 91, 0, 0 },
  61. ['\\'] = { 92, 0, 0 },
  62. [']'] = { 93, 0, 0 },
  63. ['`'] = { 96, 0, 0 },
  64. ['escape'] = { 256, 0, 0 },
  65. ['return'] = { 257, 0, 0 },
  66. ['enter'] = { 257, 0, 0 },
  67. ['tab'] = { 258, 0, 0 },
  68. ['backspace'] = { 259, 0, 0 },
  69. ['insert'] = { 260, 0, 0 },
  70. ['delete'] = { 261, 0, 0 },
  71. ['right'] = { 262, 0, 0 },
  72. ['left'] = { 263, 0, 0 },
  73. ['down'] = { 264, 0, 0 },
  74. ['up'] = { 265, 0, 0 },
  75. ['pageup'] = { 266, 0, 0 },
  76. ['pagedown'] = { 267, 0, 0 },
  77. ['home'] = { 268, 0, 0 },
  78. ['end'] = { 269, 0, 0 },
  79. ['capslock'] = { 280, 0, 0 },
  80. ['scrolllock'] = { 281, 0, 0 },
  81. ['numlock'] = { 282, 0, 0 },
  82. ['printscreen'] = { 283, 0, 0 },
  83. ['pause'] = { 284, 0, 0 },
  84. ['f1'] = { 290, 0, 0 },
  85. ['f2'] = { 291, 0, 0 },
  86. ['f3'] = { 292, 0, 0 },
  87. ['f4'] = { 293, 0, 0 },
  88. ['f5'] = { 294, 0, 0 },
  89. ['f6'] = { 295, 0, 0 },
  90. ['f7'] = { 296, 0, 0 },
  91. ['f8'] = { 297, 0, 0 },
  92. ['f9'] = { 298, 0, 0 },
  93. ['f10'] = { 299, 0, 0 },
  94. ['f11'] = { 300, 0, 0 },
  95. ['f12'] = { 301, 0, 0 },
  96. ['kp0'] = { 320, 0, 0 },
  97. ['kp1'] = { 321, 0, 0 },
  98. ['kp2'] = { 322, 0, 0 },
  99. ['kp3'] = { 323, 0, 0 },
  100. ['kp4'] = { 324, 0, 0 },
  101. ['kp5'] = { 325, 0, 0 },
  102. ['kp6'] = { 326, 0, 0 },
  103. ['kp7'] = { 327, 0, 0 },
  104. ['kp8'] = { 328, 0, 0 },
  105. ['kp9'] = { 329, 0, 0 },
  106. ['kp.'] = { 330, 0, 0 },
  107. ['kp/'] = { 331, 0, 0 },
  108. ['kp*'] = { 332, 0, 0 },
  109. ['kp-'] = { 333, 0, 0 },
  110. ['kp+'] = { 334, 0, 0 },
  111. ['kpenter'] = { 335, 0, 0 },
  112. ['kp='] = { 336, 0, 0 },
  113. ['lshift'] = { 340, 0, 0 },
  114. ['lctrl'] = { 341, 0, 0 },
  115. ['lalt'] = { 342, 0, 0 },
  116. ['lgui'] = { 343, 0, 0 },
  117. ['rshift'] = { 344, 0, 0 },
  118. ['rctrl'] = { 345, 0, 0 },
  119. ['ralt'] = { 346, 0, 0 },
  120. ['rgui'] = { 347, 0, 0 },
  121. ['menu'] = { 348, 0, 0 }
  122. }
  123. local reverse = {}
  124. for k, v in pairs(keymap) do
  125. local keycode = v[1]
  126. reverse[keycode] = k
  127. end
  128. for k, v in pairs(reverse) do
  129. keymap[k] = v
  130. end
  131. local keyboard = {}
  132. function keyboard.isDown(key, ...)
  133. if not key then return false end
  134. local keycode = keymap[key][1]
  135. assert(keycode and type(keycode) == 'number', 'Unknown key: ' .. key)
  136. return C.glfwGetKey(window, keycode) == 1 or keyboard.isDown(...)
  137. end
  138. function keyboard.wasPressed(key, ...)
  139. if not key then return false end
  140. local keycode = keymap[key][1]
  141. assert(keycode and type(keycode) == 'number', 'Unknown key: ' .. key)
  142. local pressed = false
  143. keymap[key][3] = C.glfwGetKey(window, keycode)
  144. if keymap[key][2] == 0 and keymap[key][3] == 1 then
  145. pressed = true
  146. else
  147. pressed = false
  148. end
  149. keymap[key][2] = keymap[key][3]
  150. return pressed
  151. end
  152. function keyboard.wasReleased(key, ...)
  153. if not key then return false end
  154. local keycode = keymap[key][1]
  155. assert(keycode and type(keycode) == 'number', 'Unknown key: ' .. key)
  156. local released = false
  157. keymap[key][3] = C.glfwGetKey(window, keycode)
  158. if keymap[key][2] == 1 and keymap[key][3] == 0 then
  159. released = true
  160. else
  161. released = false
  162. end
  163. keymap[key][2] = keymap[key][3]
  164. return released
  165. end
  166. C.glfwSetKeyCallback(window, function(window, key, scancode, action, mods)
  167. if action ~= 2 and keymap[key] then
  168. lovr.event.push(action > 0 and 'keypressed' or 'keyreleased', keymap[key])
  169. end
  170. end)
  171. C.glfwSetCharCallback(window, function(window, char)
  172. lovr.event.push('textinput', string.char(char))
  173. end)
  174. return keyboard