diff --git a/example/addons/tiltfive/T5Manager.gd b/example/addons/tiltfive/T5Manager.gd index d85b797..9c910e8 100644 --- a/example/addons/tiltfive/T5Manager.gd +++ b/example/addons/tiltfive/T5Manager.gd @@ -6,20 +6,33 @@ class_name T5Manager extends Node ## ## This should be persistent. -signal glasses_available(glasses_id : String) -signal glasses_reserved(glasses_id : String) -signal glasses_dropped(glasses_id : String) +signal glasses_scene_was_added(glasses : T5GlassesBase) +signal glasses_scene_will_be_removed(glasses : T5GlassesBase) const xr_origin_node := ^"Origin" const xr_camera_node := ^"Origin/Camera" -const wand_node_list := [^"Origin/Wand_1", ^"Origin/Wand_2", ^"Origin/Wand_3", ^"Origin/Wand_4"] +const wand_node_list := [^"Origin/Wand_1", ^"Origin/Wand_2"] var tilt_five_xr_interface: TiltFiveXRInterface -@export var automatically_start : bool = true +@export_range(1, 4) var max_local_players : int = 1 @export var glasses_scene : PackedScene = preload("res://addons/tiltfive/scenes/T5GlassesBase.tscn") -var reserved_glasses: Dictionary +# State of a set of glasses. +class GlassesState: + var available := false + var attempting_to_reserve := false + var reserved := false + var glasses_scene : T5GlassesBase + + func can_attempt_to_reserve(): + return available and (not attempting_to_reserve) and (not reserved) + +# Dictionary maps glasses_id -> GlassesState +var glasses_dict: Dictionary + +# tracks number of local players allocated glasses +var num_local_players := 0 # We'll add our glasses scenes as children of this node var glasses_node: Node3D @@ -48,26 +61,20 @@ func _ready(): if not tilt_five_xr_interface: return - if automatically_start and !tilt_five_xr_interface.is_initialized(): + if !tilt_five_xr_interface.is_initialized(): tilt_five_xr_interface.initialize() -func start_service() -> bool: - if not tilt_five_xr_interface: - return false - - return tilt_five_xr_interface.initialize() - func has_reserved_glasses() -> bool: - for glasses in reserved_glasses: - if reserved_glasses[glasses]: + for glasses_state in glasses_dict: + if glasses_state.reserved: return true return false func reserve_glasses(glasses_id : StringName, display_name := "") -> void: - if not reserved_glasses.has(glasses_id): + if not glasses_dict[glasses_id].available: print_verbose("Warning: Tilt Five glasses id ", glasses_id, " does not exist") return - if reserved_glasses[glasses_id]: + if glasses_dict[glasses_id].reserved: print_verbose("Warning: Tilt Five glasses ", glasses_id, " already reserved") return if display_name.length() == 0: @@ -80,7 +87,7 @@ func start_display(glasses_id : StringName, viewport : SubViewport): var t5_camera := viewport.get_node_or_null(xr_camera_node) as T5Camera3D if t5_camera: t5_camera.tracker = "/user/%s/head" % glasses_id - for idx in 4: + for idx in wand_node_list.size(): var controller = viewport.get_node_or_null(wand_node_list[idx]) as T5Controller3D if controller: controller.tracker = "/user/%s/wand_%d" % [glasses_id, idx + 1] @@ -88,54 +95,66 @@ func start_display(glasses_id : StringName, viewport : SubViewport): func node_name_from_glasses_id(glasses_id: String) -> String: return "Glasses_" + glasses_id.replace("-", "_") +func _allocate_glasses_to_players(): + if not glasses_scene: + return + for glasses_id in glasses_dict: + var glasses_state = glasses_dict[glasses_id] as GlassesState + if num_local_players >= max_local_players: + break + if glasses_state.can_attempt_to_reserve(): + glasses_state.attempting_to_reserve = true + reserve_glasses(glasses_id) + num_local_players += 1 + func on_glasses_event(glasses_id, event_num): + var glasses_state = glasses_dict.get(glasses_id) as GlassesState + if not glasses_state: + glasses_state = GlassesState.new() + glasses_dict[glasses_id] = glasses_state + match event_num: TiltFiveXRInterface.E_AVAILABLE: print_verbose(glasses_id, " E_AVAILABLE") - if not reserved_glasses.has(glasses_id): - reserved_glasses[glasses_id] = false - - # If we're managing our glasses scene, reserve our glasses - if glasses_scene: - reserve_glasses(glasses_id) - - # Let others who are interested know - glasses_available.emit(glasses_id) + glasses_state.available = true + _allocate_glasses_to_players() TiltFiveXRInterface.E_UNAVAILABLE: print_verbose(glasses_id, " E_UNAVAILABLE") - - # Let others who are interested know - reserved_glasses.erase(glasses_id) + glasses_state.available = false + if glasses_state.attempting_to_reserve: + glasses_state.attempting_to_reserve = false + num_local_players -= 1 + _allocate_glasses_to_players() TiltFiveXRInterface.E_RESERVED: print_verbose(glasses_id, " E_RESERVED") + glasses_state.reserved = true + glasses_state.attempting_to_reserve = false - reserved_glasses[glasses_id] = true - - # If we're managing our glasses scene, instance our scene + # instance our scene if glasses_scene: - var gview = glasses_scene.instantiate() + var gview : T5GlassesBase = glasses_scene.instantiate() + gview.glasses_id = glasses_id + glasses_state.glasses_scene = gview gview.name = node_name_from_glasses_id(glasses_id) glasses_node.add_child(gview) start_display(glasses_id, gview) - - # Let others who are interested know - glasses_reserved.emit(glasses_id) + glasses_scene_was_added.emit(gview) TiltFiveXRInterface.E_DROPPED: print_verbose(glasses_id, " E_DROPPED") + glasses_state.reserved = false - var node_name = node_name_from_glasses_id(glasses_id) - var gview = glasses_node.get_node_or_null(node_name) + var gview = glasses_state.glasses_scene if gview: + glasses_scene_will_be_removed.emit(gview) + glasses_state.glasses_scene = null tilt_five_xr_interface.stop_display(glasses_id) glasses_node.remove_child(gview) gview.queue_free() - - if reserved_glasses.get(glasses_id, false): - reserved_glasses[glasses_id] = false - glasses_dropped.emit(glasses_id) + num_local_players -= 1 + _allocate_glasses_to_players() TiltFiveXRInterface.E_TRACKING: var gbt = tilt_five_xr_interface.get_gameboard_type(glasses_id) diff --git a/example/addons/tiltfive/scenes/T5GlassesBase.gd b/example/addons/tiltfive/scenes/T5GlassesBase.gd index 9726117..4804d01 100644 --- a/example/addons/tiltfive/scenes/T5GlassesBase.gd +++ b/example/addons/tiltfive/scenes/T5GlassesBase.gd @@ -1,7 +1,9 @@ -extends SubViewport +class_name T5GlassesBase extends SubViewport @onready var wand = $Origin/Wand_1 +var glasses_id : String + func _process(_delta): if wand: var wand_pose : XRPose = wand.get_pose() diff --git a/example/addons/tiltfive/scenes/T5GlassesBase.tscn b/example/addons/tiltfive/scenes/T5GlassesBase.tscn index 2fff38b..1ef95b5 100644 --- a/example/addons/tiltfive/scenes/T5GlassesBase.tscn +++ b/example/addons/tiltfive/scenes/T5GlassesBase.tscn @@ -1,11 +1,11 @@ [gd_scene load_steps=2 format=3 uid="uid://je0clrdu7o76"] -[ext_resource type="Script" path="res://addons/tiltfive/scenes/T5GlassesBase.gd" id="1_ra3f6"] +[ext_resource type="Script" path="res://addons/tiltfive/scenes/T5GlassesBase.gd" id="1_qmxa3"] [node name="T5GlassesBase" type="SubViewport"] size = Vector2i(2, 2) render_target_update_mode = 0 -script = ExtResource("1_ra3f6") +script = ExtResource("1_qmxa3") [node name="Origin" type="T5Origin3D" parent="."] diff --git a/example/main.gd b/example/main.gd index ea4a90d..880e6ec 100644 --- a/example/main.gd +++ b/example/main.gd @@ -1,2 +1,7 @@ extends Node3D +func _on_t5_manager_glasses_scene_was_added(glasses): + print("Scene ", glasses.name, " added") + +func _on_t5_manager_glasses_scene_will_be_removed(glasses): + print("Scene ", glasses.name, " removed") diff --git a/example/main.tscn b/example/main.tscn index 2cfdf95..910bb38 100644 --- a/example/main.tscn +++ b/example/main.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=17 format=3 uid="uid://ckbe6draoen0x"] -[ext_resource type="Script" path="res://main.gd" id="1_ptcg0"] +[ext_resource type="Script" path="res://main.gd" id="1_xvgge"] [ext_resource type="Script" path="res://addons/tiltfive/T5Manager.gd" id="2_dibvp"] [ext_resource type="Script" path="res://addons/tiltfive/scenes/helpers/SelectableBody.gd" id="3_jespo"] [ext_resource type="PackedScene" uid="uid://dl3mv76qkuscf" path="res://T5Glasses.tscn" id="3_xx6p7"] @@ -35,7 +35,7 @@ albedo_color = Color(0.862745, 0, 0.0235294, 1) albedo_color = Color(0.741176, 0, 0.686275, 1) [node name="Main" type="Node3D"] -script = ExtResource("1_ptcg0") +script = ExtResource("1_xvgge") [node name="T5Manager" type="Node" parent="."] script = ExtResource("2_dibvp") @@ -100,3 +100,6 @@ surface_material_override/0 = SubResource("StandardMaterial3D_qrhlq") [node name="SpectatorCam" type="Camera3D" parent="."] transform = Transform3D(0.670983, -0.138786, 0.728368, 0, 0.982326, 0.187176, -0.741472, -0.125592, 0.659125, 14.0459, 4.9572, 12.9908) cull_mask = 3 + +[connection signal="glasses_scene_was_added" from="T5Manager" to="." method="_on_t5_manager_glasses_scene_was_added"] +[connection signal="glasses_scene_will_be_removed" from="T5Manager" to="." method="_on_t5_manager_glasses_scene_will_be_removed"]