main.lua 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. local function raycast(rayPos, rayDir, planePos, planeDir)
  2. local dot = rayDir:dot(planeDir)
  3. if math.abs(dot) < .001 then
  4. return nil
  5. else
  6. local distance = (planePos - rayPos):dot(planeDir) / dot
  7. if distance > 0 then
  8. return rayPos + rayDir * distance
  9. else
  10. return nil
  11. end
  12. end
  13. end
  14. local button = {
  15. text = 'Please click me',
  16. textSize = .1,
  17. count = 0,
  18. position = lovr.math.newVec3(0, 1, -3),
  19. width = 1.0,
  20. height = .4,
  21. hover = false,
  22. active = false
  23. }
  24. local tips = {}
  25. function lovr.update()
  26. button.hover, button.active = false, false
  27. for i, hand in ipairs(lovr.headset.getHands()) do
  28. tips[hand] = tips[hand] or lovr.math.newVec3()
  29. -- Ray info:
  30. local rayPosition = vec3(lovr.headset.getPosition(hand .. '/point'))
  31. local rayDirection = vec3(lovr.headset.getDirection(hand .. '/point'))
  32. -- Call the raycast helper function to get the intersection point of the ray and the button plane
  33. local hit = raycast(rayPosition, rayDirection, button.position, vec3(0, 0, 1))
  34. local inside = false
  35. if hit then
  36. local bx, by, bw, bh = button.position.x, button.position.y, button.width / 2, button.height / 2
  37. inside = (hit.x > bx - bw) and (hit.x < bx + bw) and (hit.y > by - bh) and (hit.y < by + bh)
  38. end
  39. -- If the ray intersects the plane, do a bounds test to make sure the x/y position of the hit
  40. -- is inside the button, then mark the button as hover/active based on the trigger state.
  41. if inside then
  42. if lovr.headset.isDown(hand, 'trigger') then
  43. button.active = true
  44. else
  45. button.hover = true
  46. end
  47. if lovr.headset.wasReleased(hand, 'trigger') then
  48. button.count = button.count + 1
  49. print('BOOP')
  50. end
  51. end
  52. -- Set the end position of the pointer. If the raycast produced a hit position then use that,
  53. -- otherwise extend the pointer's ray outwards by 50 meters and use it as the tip.
  54. tips[hand]:set(inside and hit or (rayPosition + rayDirection * 50))
  55. end
  56. end
  57. function lovr.draw(pass)
  58. -- Button background
  59. if button.active then
  60. pass:setColor(.4, .4, .4)
  61. elseif button.hover then
  62. pass:setColor(.2, .2, .2)
  63. else
  64. pass:setColor(.1, .1, .1)
  65. end
  66. pass:plane(button.position, button.width, button.height)
  67. -- Button text (add a small amount to the z to put the text slightly in front of button)
  68. pass:setColor(1, 1, 1)
  69. pass:text(button.text, button.position + vec3(0, 0, .001), button.textSize)
  70. pass:text('Count: ' .. button.count, button.position + vec3(0, .5, 0), .1)
  71. -- Pointers
  72. for hand, tip in pairs(tips) do
  73. local position = vec3(lovr.headset.getPosition(hand))
  74. pass:setColor(1, 1, 1)
  75. pass:sphere(position, .01)
  76. if button.active then
  77. pass:setColor(0, 1, 0)
  78. else
  79. pass:setColor(1, 0, 0)
  80. end
  81. pass:line(position, tip)
  82. end
  83. end