|
| 1 | +extends Node3D |
| 2 | + |
| 3 | +var webxr_interface: XRInterface |
| 4 | +var vr_supported: bool = false |
| 5 | + |
| 6 | + |
| 7 | +func _ready() -> void: |
| 8 | + $CanvasLayer/EnterVRButton.pressed.connect(self._on_enter_vr_button_pressed) |
| 9 | + |
| 10 | + webxr_interface = XRServer.find_interface("WebXR") |
| 11 | + if webxr_interface: |
| 12 | + # WebXR uses a lot of asynchronous callbacks, so we connect to various |
| 13 | + # signals in order to receive them. |
| 14 | + webxr_interface.session_supported.connect(self._webxr_session_supported) |
| 15 | + webxr_interface.session_started.connect(self._webxr_session_started) |
| 16 | + webxr_interface.session_ended.connect(self._webxr_session_ended) |
| 17 | + webxr_interface.session_failed.connect(self._webxr_session_failed) |
| 18 | + |
| 19 | + webxr_interface.select.connect(self._webxr_on_select) |
| 20 | + webxr_interface.selectstart.connect(self._webxr_on_select_start) |
| 21 | + webxr_interface.selectend.connect(self._webxr_on_select_end) |
| 22 | + |
| 23 | + webxr_interface.squeeze.connect(self._webxr_on_squeeze) |
| 24 | + webxr_interface.squeezestart.connect(self._webxr_on_squeeze_start) |
| 25 | + webxr_interface.squeezeend.connect(self._webxr_on_squeeze_end) |
| 26 | + |
| 27 | + # This returns immediately - our _webxr_session_supported() method |
| 28 | + # (which we connected to the "session_supported" signal above) will |
| 29 | + # be called sometime later to let us know if it's supported or not. |
| 30 | + webxr_interface.is_session_supported("immersive-vr") |
| 31 | + |
| 32 | + $XROrigin3D/LeftController.button_pressed.connect(self._on_left_controller_button_pressed) |
| 33 | + $XROrigin3D/LeftController.button_released.connect(self._on_left_controller_button_released) |
| 34 | + |
| 35 | + |
| 36 | +func _webxr_session_supported(session_mode: String, supported: bool) -> void: |
| 37 | + if session_mode == 'immersive-vr': |
| 38 | + vr_supported = supported |
| 39 | + |
| 40 | + |
| 41 | +func _on_enter_vr_button_pressed() -> void: |
| 42 | + if not vr_supported: |
| 43 | + OS.alert("Your browser doesn't support VR") |
| 44 | + return |
| 45 | + |
| 46 | + # We want an immersive VR session, as opposed to AR ('immersive-ar') or a |
| 47 | + # simple 3DoF viewer ('viewer'). |
| 48 | + webxr_interface.session_mode = 'immersive-vr' |
| 49 | + # 'bounded-floor' is room scale, 'local-floor' is a standing or sitting |
| 50 | + # experience (it puts you 1.6m above the ground if you have 3DoF headset), |
| 51 | + # whereas as 'local' puts you down at the XROrigin3D. |
| 52 | + # This list means it'll first try to request 'bounded-floor', then |
| 53 | + # fallback on 'local-floor' and ultimately 'local', if nothing else is |
| 54 | + # supported. |
| 55 | + webxr_interface.requested_reference_space_types = 'bounded-floor, local-floor, local' |
| 56 | + # In order to use 'local-floor' or 'bounded-floor' we must also |
| 57 | + # mark the features as required or optional. |
| 58 | + webxr_interface.required_features = 'local-floor' |
| 59 | + webxr_interface.optional_features = 'bounded-floor' |
| 60 | + |
| 61 | + # This will return false if we're unable to even request the session, |
| 62 | + # however, it can still fail asynchronously later in the process, so we |
| 63 | + # only know if it's really succeeded or failed when our |
| 64 | + # _webxr_session_started() or _webxr_session_failed() methods are called. |
| 65 | + if not webxr_interface.initialize(): |
| 66 | + OS.alert("Failed to initialize WebXR") |
| 67 | + return |
| 68 | + |
| 69 | + |
| 70 | +func _webxr_session_started() -> void: |
| 71 | + $CanvasLayer.visible = false |
| 72 | + # This tells Godot to start rendering to the headset. |
| 73 | + get_viewport().use_xr = true |
| 74 | + # This will be the reference space type you ultimately got, out of the |
| 75 | + # types that you requested above. This is useful if you want the game to |
| 76 | + # work a little differently in 'bounded-floor' versus 'local-floor'. |
| 77 | + print ("Reference space type: " + webxr_interface.reference_space_type) |
| 78 | + # This will be the list of features that were successfully enabled |
| 79 | + # (except on browsers that don't support this property). |
| 80 | + print("Enabled features: ", webxr_interface.enabled_features) |
| 81 | + |
| 82 | + |
| 83 | +func _webxr_session_ended() -> void: |
| 84 | + $CanvasLayer.visible = true |
| 85 | + # If the user exits immersive mode, then we tell Godot to render to the web |
| 86 | + # page again. |
| 87 | + get_viewport().use_xr = false |
| 88 | + |
| 89 | + |
| 90 | +func _webxr_session_failed(message: String) -> void: |
| 91 | + OS.alert("Failed to initialize: " + message) |
| 92 | + |
| 93 | + |
| 94 | +func _on_left_controller_button_pressed(button: String) -> void: |
| 95 | + print ("Button pressed: " + button) |
| 96 | + |
| 97 | + |
| 98 | +func _on_left_controller_button_released(button: String) -> void: |
| 99 | + print ("Button release: " + button) |
| 100 | + |
| 101 | + |
| 102 | +func _process(_delta: float) -> void: |
| 103 | + var thumbstick_vector: Vector2 = $XROrigin3D/LeftController.get_vector2("thumbstick") |
| 104 | + if thumbstick_vector != Vector2.ZERO: |
| 105 | + print ("Left thumbstick position: " + str(thumbstick_vector)) |
| 106 | + |
| 107 | + |
| 108 | +func _webxr_on_select(input_source_id: int) -> void: |
| 109 | + print("Select: " + str(input_source_id)) |
| 110 | + |
| 111 | + var tracker: XRPositionalTracker = webxr_interface.get_input_source_tracker(input_source_id) |
| 112 | + var xform = tracker.get_pose('default').transform |
| 113 | + print (xform.origin) |
| 114 | + |
| 115 | + |
| 116 | +func _webxr_on_select_start(input_source_id: int) -> void: |
| 117 | + print("Select Start: " + str(input_source_id)) |
| 118 | + |
| 119 | + |
| 120 | +func _webxr_on_select_end(input_source_id: int) -> void: |
| 121 | + print("Select End: " + str(input_source_id)) |
| 122 | + |
| 123 | + |
| 124 | +func _webxr_on_squeeze(input_source_id: int) -> void: |
| 125 | + print("Squeeze: " + str(input_source_id)) |
| 126 | + |
| 127 | + |
| 128 | +func _webxr_on_squeeze_start(input_source_id: int) -> void: |
| 129 | + print("Squeeze Start: " + str(input_source_id)) |
| 130 | + |
| 131 | + |
| 132 | +func _webxr_on_squeeze_end(input_source_id: int) -> void: |
| 133 | + print("Squeeze End: " + str(input_source_id)) |
0 commit comments