start_vr.gd 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. extends Node3D
  2. signal focus_lost
  3. signal focus_gained
  4. signal pose_recentered
  5. @export var maximum_refresh_rate : int = 90
  6. var xr_interface : OpenXRInterface
  7. var xr_is_focussed = false
  8. # Called when the node enters the scene tree for the first time.
  9. func _ready():
  10. xr_interface = XRServer.find_interface("OpenXR")
  11. if xr_interface and xr_interface.is_initialized():
  12. print("OpenXR instantiated successfully.")
  13. var vp : Viewport = get_viewport()
  14. # Enable XR on our viewport
  15. vp.use_xr = true
  16. # Make sure v-sync is off, v-sync is handled by OpenXR
  17. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
  18. # Connect the OpenXR events
  19. xr_interface.connect("session_begun", _on_openxr_session_begun)
  20. xr_interface.connect("session_visible", _on_openxr_visible_state)
  21. xr_interface.connect("session_focussed", _on_openxr_focused_state)
  22. xr_interface.connect("session_stopping", _on_openxr_stopping)
  23. xr_interface.connect("pose_recentered", _on_openxr_pose_recentered)
  24. else:
  25. # We couldn't start OpenXR.
  26. print("OpenXR not instantiated!")
  27. get_tree().quit()
  28. # Handle OpenXR session ready
  29. func _on_openxr_session_begun() -> void:
  30. # Get the reported refresh rate
  31. var current_refresh_rate = xr_interface.get_display_refresh_rate()
  32. if current_refresh_rate > 0:
  33. print("OpenXR: Refresh rate reported as ", str(current_refresh_rate))
  34. else:
  35. print("OpenXR: No refresh rate given by XR runtime")
  36. # See if we have a better refresh rate available
  37. var new_rate = current_refresh_rate
  38. var available_rates : Array = xr_interface.get_available_display_refresh_rates()
  39. if available_rates.size() == 0:
  40. print("OpenXR: Target does not support refresh rate extension")
  41. elif available_rates.size() == 1:
  42. # Only one available, so use it
  43. new_rate = available_rates[0]
  44. else:
  45. for rate in available_rates:
  46. if rate > new_rate and rate <= maximum_refresh_rate:
  47. new_rate = rate
  48. # Did we find a better rate?
  49. if current_refresh_rate != new_rate:
  50. print("OpenXR: Setting refresh rate to ", str(new_rate))
  51. xr_interface.set_display_refresh_rate(new_rate)
  52. current_refresh_rate = new_rate
  53. # Now match our physics rate
  54. Engine.physics_ticks_per_second = current_refresh_rate
  55. # Handle OpenXR visible state
  56. func _on_openxr_visible_state() -> void:
  57. # We always pass this state at startup,
  58. # but the second time we get this it means our player took off their headset
  59. if xr_is_focussed:
  60. print("OpenXR lost focus")
  61. xr_is_focussed = false
  62. # pause our game
  63. process_mode = Node.PROCESS_MODE_DISABLED
  64. emit_signal("focus_lost")
  65. # Handle OpenXR focused state
  66. func _on_openxr_focused_state() -> void:
  67. print("OpenXR gained focus")
  68. xr_is_focussed = true
  69. # unpause our game
  70. process_mode = Node.PROCESS_MODE_INHERIT
  71. emit_signal("focus_gained")
  72. # Handle OpenXR stopping state
  73. func _on_openxr_stopping() -> void:
  74. # Our session is being stopped.
  75. print("OpenXR is stopping")
  76. # Handle OpenXR pose recentered signal
  77. func _on_openxr_pose_recentered() -> void:
  78. # User recentered view, we have to react to this by recentering the view.
  79. # This is game implementation dependent.
  80. emit_signal("pose_recentered")