From 0bb00735b2d55db931328e0e118c79ebdfd2c4ca Mon Sep 17 00:00:00 2001 From: JonShard Date: Mon, 17 Aug 2026 11:04:49 +0200 Subject: [PATCH] Add VRSpectatorCamera so the server viewport follows VR head --- Scenes/multiPlayer.tscn | 12 +++++++--- test/vr_spectator_camera.gd | 40 +++++++++++++++++++++++++++++++++ test/vr_spectator_camera.gd.uid | 1 + test/vr_spectator_camera.tscn | 6 +++++ 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test/vr_spectator_camera.gd create mode 100644 test/vr_spectator_camera.gd.uid create mode 100644 test/vr_spectator_camera.tscn diff --git a/Scenes/multiPlayer.tscn b/Scenes/multiPlayer.tscn index d46d4d7..d7f0b93 100644 --- a/Scenes/multiPlayer.tscn +++ b/Scenes/multiPlayer.tscn @@ -6,9 +6,9 @@ [ext_resource type="Sky" uid="uid://c1abtpwhdm2d5" path="res://textures/sky/NightSkyHDRI009_16K.tres" id="5_c3xgf"] [ext_resource type="Script" uid="uid://fyd2rjramhbb" path="res://prefabs/kitchen_instantiator.gd" id="6_pw2j5"] [ext_resource type="PackedScene" uid="uid://damrxtlt7uswf" path="res://content/station_layouts/small_line.tscn" id="7_0sjqq"] -[ext_resource type="PackedScene" uid="uid://j7caslh27nor" path="res://stations/Hob_old.tscn" id="8_0sjqq"] [ext_resource type="PackedScene" uid="uid://dm70ynyuw1a5u" path="res://prefabs/day_controller.tscn" id="9_5wx0o"] [ext_resource type="PackedScene" uid="uid://bnwb7imcotkod" path="res://prefabs/build_mode_controller.tscn" id="10_464r1"] +[ext_resource type="Script" uid="uid://c4y0yigqv7355" path="res://test/vr_spectator_camera.gd" id="11_5wx0o"] [ext_resource type="PackedScene" uid="uid://dxe05wp60jg3l" path="res://scenes/queue_controller.tscn" id="11_de1dy"] [ext_resource type="Script" uid="uid://biu4qr3nr1eny" path="res://test/mp_test_driver.gd" id="99_mptst"] @@ -31,6 +31,9 @@ sdfgi_enabled = true [sub_resource type="BoxShape3D" id="BoxShape3D_arao0"] size = Vector3(15, 20, 0.1) +[sub_resource type="Resource" id="Resource_464r1"] +metadata/__load_path__ = "res://stations/Hob_old.tscn" + [node name="Main" type="Node3D" unique_id=1312265607 node_paths=PackedStringArray("items_spawner", "players_spawner")] script = ExtResource("1_kdan8") items_spawner = NodePath("ItemsSpawner") @@ -63,7 +66,7 @@ environment = SubResource("Environment_bvwq1") spawn_path = NodePath("../WorldContent") [node name="PlayersSpawner" type="MultiplayerSpawner" parent="." unique_id=106645565] -_spawnable_scenes = PackedStringArray("res://Player/net_player.tscn") +_spawnable_scenes = PackedStringArray("uid://c58ns7csdahjy") spawn_path = NodePath("../Players") [node name="StaticBody3D" type="StaticBody3D" parent="." unique_id=4404969] @@ -91,7 +94,7 @@ script = ExtResource("99_mptst") transform = Transform3D(1, 0, -1.7484555e-07, 0, 1, 0, 1.7484555e-07, 0, 1, 0, 0, -1.2) script = ExtResource("6_pw2j5") kitchen_scene = ExtResource("7_0sjqq") -hob_scene = ExtResource("8_0sjqq") +hob_scene = SubResource("Resource_464r1") [node name="DayController" parent="." unique_id=1418639156 instance=ExtResource("9_5wx0o")] @@ -99,3 +102,6 @@ hob_scene = ExtResource("8_0sjqq") [node name="QueueController" parent="." unique_id=326512876 instance=ExtResource("11_de1dy")] transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 7.2000003) + +[node name="Node3D" type="Node3D" parent="." unique_id=1675081068] +script = ExtResource("11_5wx0o") diff --git a/test/vr_spectator_camera.gd b/test/vr_spectator_camera.gd new file mode 100644 index 0000000..2e7225a --- /dev/null +++ b/test/vr_spectator_camera.gd @@ -0,0 +1,40 @@ +class_name VrSpectatorCamera +extends Node + +# Debug tool: on a non-VR client, follows a connected VR client's head so you can spectate it. + +@export var players_path: NodePath = ^"../Players" + +@onready var _players: Node = get_node_or_null(players_path) +var _camera: Camera3D + + +func _ready() -> void: + var xr_interface := XRServer.find_interface("OpenXR") + if xr_interface and xr_interface.is_initialized(): + SweetLogger.warning("{0} disabled - this instance is the VR client", [name]) + return + if not _players: + SweetLogger.warning("{0} could not resolve players_path {1}", [name, players_path]) + return + _camera = Camera3D.new() + add_child(_camera) + _camera.make_current() + + +func _process(_delta: float) -> void: + if not _camera: + return + var head := _find_remote_head() + if head: + _camera.global_transform = head.global_transform + + +# First connected player that isn't this local peer +func _find_remote_head() -> Node3D: + var my_id := multiplayer.get_unique_id() + for player in _players.get_children(): + if player.name == str(my_id): + continue + return player.get_node_or_null("Head") + return null diff --git a/test/vr_spectator_camera.gd.uid b/test/vr_spectator_camera.gd.uid new file mode 100644 index 0000000..2764771 --- /dev/null +++ b/test/vr_spectator_camera.gd.uid @@ -0,0 +1 @@ +uid://c4y0yigqv7355 diff --git a/test/vr_spectator_camera.tscn b/test/vr_spectator_camera.tscn new file mode 100644 index 0000000..d2e1b61 --- /dev/null +++ b/test/vr_spectator_camera.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://3i1xb74cfsh5"] + +[ext_resource type="Script" uid="uid://c4y0yigqv7355" path="res://test/vr_spectator_camera.gd" id="1_6xorv"] + +[node name="VRSpectatorCamera" type="Node" unique_id=310823561] +script = ExtResource("1_6xorv")