mouse.lua 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. -- Source: https://github.com/bjornbytes/lovr-mouse/
  2. -- Source: c2f704db2463e05c453580b80b26200d5dd508a9
  3. local ffi = require 'ffi'
  4. local C = ffi.os == 'Windows' and ffi.load('glfw3') or ffi.C
  5. ffi.cdef [[
  6. typedef enum {
  7. GLFW_CURSOR = 0x00033001,
  8. GLFW_CURSOR_NORMAL = 0x00034001,
  9. GLFW_CURSOR_HIDDEN = 0x00034002,
  10. GLFW_CURSOR_DISABLED = 0x00034003
  11. } Constants;
  12. typedef struct GLFWwindow GLFWwindow;
  13. typedef void(*GLFWmousebuttonfun)(GLFWwindow*, int, int, int);
  14. typedef void(*GLFWcursorposfun)(GLFWwindow*, double, double);
  15. typedef void(*GLFWscrollfun)(GLFWwindow*, double, double);
  16. GLFWwindow* glfwGetCurrentContext(void);
  17. void glfwGetInputMode(GLFWwindow* window, int mode);
  18. void glfwSetInputMode(GLFWwindow* window, int mode, int value);
  19. void glfwGetCursorPos(GLFWwindow* window, double* x, double* y);
  20. void glfwSetCursorPos(GLFWwindow* window, double x, double y);
  21. int glfwGetMouseButton(GLFWwindow* window, int button);
  22. void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
  23. GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun callback);
  24. GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun callback);
  25. GLFWcursorposfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback);
  26. ]]
  27. local window = C.glfwGetCurrentContext()
  28. local mouse = {}
  29. -- Lovr uses framebuffer scale for everything, but glfw uses window scale for events.
  30. -- It is necessary to convert between the two at all boundaries.
  31. function mouse.getScale()
  32. local x, _ = ffi.new('int[1]'), ffi.new('int[1]')
  33. C.glfwGetWindowSize(window, x, _)
  34. return lovr.graphics.getWidth()/x[0]
  35. end
  36. function mouse.getX()
  37. local x = ffi.new('double[1]')
  38. C.glfwGetCursorPos(window, x, nil)
  39. return x[0] * mouse.getScale()
  40. end
  41. function mouse.getY()
  42. local y = ffi.new('double[1]')
  43. C.glfwGetCursorPos(window, nil, y)
  44. return y[0] * mouse.getScale()
  45. end
  46. function mouse.getPosition()
  47. local x, y = ffi.new('double[1]'), ffi.new('double[1]')
  48. local scale = mouse.getScale()
  49. C.glfwGetCursorPos(window, x, y)
  50. return x[0] * scale, y[0] * scale
  51. end
  52. function mouse.setX(x)
  53. local y = mouse.getY()
  54. local scale = mouse.getScale()
  55. C.glfwSetCursorPos(window, x/scale, y/scale)
  56. end
  57. function mouse.setY(y)
  58. local x = mouse.getX()
  59. C.glfwSetCursorPos(window, x/scale, y/scale)
  60. end
  61. function mouse.setPosition(x, y)
  62. C.glfwSetCursorPos(window, x/scale, y/scale)
  63. end
  64. function mouse.isDown(button, ...)
  65. if not button then return false end
  66. return C.glfwGetMouseButton(window, button - 1) > 0 or mouse.isDown(...)
  67. end
  68. function mouse.getRelativeMode()
  69. return C.glfwGetInputMode(window, C.GLFW_CURSOR) == C.GLFW_CURSOR_DISABLED
  70. end
  71. function mouse.setRelativeMode(enable)
  72. C.glfwSetInputMode(window, C.GLFW_CURSOR, enable and C.GLFW_CURSOR_DISABLED or C.GLFW_CURSOR_NORMAL)
  73. end
  74. C.glfwSetMouseButtonCallback(window, function(target, button, action, mods)
  75. if target == window then
  76. local x, y = mouse.getPosition()
  77. lovr.event.push(action > 0 and 'mousepressed' or 'mousereleased', x, y, button + 1, false)
  78. end
  79. end)
  80. local px, py = mouse.getPosition()
  81. C.glfwSetCursorPosCallback(window, function(target, x, y)
  82. if target == window then
  83. local scale = mouse.getScale()
  84. x = x * scale
  85. y = y * scale
  86. lovr.event.push('mousemoved', x, y, x - px, y - py, false)
  87. px, py = x, y
  88. end
  89. end)
  90. C.glfwSetScrollCallback(window, function(target, x, y)
  91. if target == window then
  92. local scale = mouse.getScale()
  93. lovr.event.push('wheelmoved', x*scale, y*scale)
  94. end
  95. end)
  96. return mouse