# annoying you have to @tool to successfully extend the XR tool classes, # which pollutes the the methods with editor only checks, oh well. @tool extends XRToolsSceneBase func scene_loaded(user_data = null): super.scene_loaded(user_data) _reset_manipulators() var targets: Array[Target] = [] func _ready(): if Engine.is_editor_hint(): return # reset the world scale to 1.0 XRServer.world_scale = 1.0 # for editor testing when scene is directly loaded _reset_manipulators() var target_nodes = get_tree().get_nodes_in_group("targets") for target_node in target_nodes: if target_node is Target: targets.append(target_node) func _reset_manipulators(): # reset the manipulators (the loaded scene has them in the final position) # Get all manipulators in the scene var manipulators = get_tree().get_nodes_in_group("manipulators") # Calculate spacing between manipulators var total_width = manipulators.size() - 1 var start_x = -total_width / 2.0 # Position each manipulator in a line for i in range(manipulators.size()): var manipulator = manipulators[i] var x_pos = start_x + i manipulator.transform.origin = Vector3(x_pos, 1.0, -1.0) manipulator.transform.basis = Basis.IDENTITY # Reset the attractor sphere radius var attractor = manipulator.get_node("VisualAttractorSphere") if attractor: attractor.radius = 0.5 # Puzzle completion parameters @export var completion_threshold := 0.8 # Target occupancy threshold @export var completion_time := 3.0 # Time all targets must be above threshold var _completion_timer := 0.0 var _puzzle_complete := false signal puzzle_completed() func _process(delta: float) -> void: if Engine.is_editor_hint(): return check_puzzle_completion(delta) func check_puzzle_completion(delta: float) -> void: if _puzzle_complete: return # Check if all targets are above threshold var all_above_threshold = true for target in targets: if target._current_occupancy < completion_threshold: all_above_threshold = false break # Update completion timer if all_above_threshold: _completion_timer += delta if _completion_timer >= completion_time: _puzzle_complete = true puzzle_completed.emit() else: _completion_timer = 0.0