From 9e2bf5787f92d76fd70abde055e7e00c030706d2 Mon Sep 17 00:00:00 2001 From: lucastucious Date: Tue, 29 Jul 2025 14:08:08 +0200 Subject: [PATCH] documentation and optimization --- core/scripts/player_selection_manager.gd | 40 ++++++----- dev/debug_tools.gd | 87 ++++++++++++++++-------- 2 files changed, 82 insertions(+), 45 deletions(-) diff --git a/core/scripts/player_selection_manager.gd b/core/scripts/player_selection_manager.gd index d9de36f..c2026ed 100644 --- a/core/scripts/player_selection_manager.gd +++ b/core/scripts/player_selection_manager.gd @@ -1,4 +1,5 @@ extends Control + class_name SelectionManager var draw_selection := false @@ -11,11 +12,8 @@ var perform_selection := false # Flag to trigger selection in _physics_process @onready var optimized_rect: bool = ProjectSettings.get_setting("game/interface/optimized_rectangle", false) @export var rect_style: StyleBoxFlat @onready var cam = get_viewport().get_camera_3d() -@onready var hovercontrol:Button = $"../Button" - - -func _ready() -> void: - if optimized_rect:return +@onready var hovercontrol: Button = $"../Button" +@onready var debug_mode = get_tree().debug_collisions_hint #ProjectSettings.get_setting("debug/collisions/show_mouse_trace", false) func _unhandled_input(e: InputEvent) -> void: @@ -24,7 +22,6 @@ func _unhandled_input(e: InputEvent) -> void: draw_selection = true drag_start = e.position else: - # When button is released draw_selection = false if drag_start.is_equal_approx(e.position): # Single click: set a zero-sized selection box @@ -35,10 +32,11 @@ func _unhandled_input(e: InputEvent) -> void: var x_min = min(drag_start.x, e.position.x) var y_min = min(drag_start.y, e.position.y) select_box = Rect2(x_min, y_min, - max(drag_start.x, e.position.x) - x_min, - max(drag_start.y, e.position.y) - y_min) + max(drag_start.x, e.position.x) - x_min, + max(drag_start.y, e.position.y) - y_min) + + perform_selection = true - perform_selection = true # Trigger selection in _physics_process queue_redraw() elif draw_selection and e is InputEventMouseMotion: # Update selection box for drawing during drag @@ -68,11 +66,11 @@ func check_hover(): hovercontrol.text = "" hovercontrol.queue_redraw() - pass +## Returns an array of entities selected by the player, using multiplayer-unique group names func get_selected() -> Array[Entity]: - var selected: Array[Node] = get_tree().get_nodes_in_group('selected-by-'+str(get_tree().get_multiplayer().get_unique_id())) + var selected: Array[Node] = get_tree().get_nodes_in_group('selected-by-' + str(get_tree().get_multiplayer().get_unique_id())) var selected_entity: Array[Entity] selected_entity.assign(selected) return selected_entity @@ -86,29 +84,38 @@ func check_raycast(mouse_pos: Vector2, collision_mask: int = 32768) -> Dictionar query.collide_with_areas = true query.collide_with_bodies = false var space_state = cam.get_world_3d().direct_space_state - #DebugTools.DrawLine(from,to,25.0) return space_state.intersect_ray(query) +## Deselects all currently selected entities func deselect_all() -> void: var selected = get_selected() - for entity:Entity in selected: + for entity: Entity in selected: entity.deselect() +## Updates selection state of entities based on single-click (raycast) or drag (box) selection [br] +## Iterate on every entities inside the [param selectable-entity] group func update_selected_units() -> void: + ## FIXME: Could be optimized if we store an array of visible entity by adding[br] + ## an [Area3D] child of the camera OR changing the group based on if the 3d model is loaded var units_array = get_tree().get_nodes_in_group("selectable-entity") var raycast = {} # Only perform raycast if it's a single click (zero-sized select_box) if select_box.size == Vector2.ZERO: - raycast = check_raycast(select_box.position,) - if raycast and raycast.collider: + raycast = check_raycast(select_box.position) + if raycast.is_empty(): + deselect_all() + return + if raycast.collider: + if debug_mode: + DebugTools.DrawCube(raycast.position,0.02,3.0,Color()) + # select entity under mouse # maybe can be extracted from hover instead? var entity = raycast.collider.get_parent() deselect_all() entity.select() - # BUG: Deselect previous selection return for entity: Entity in units_array: # TODO: Optimize by searching only in spawned chunks @@ -119,6 +126,7 @@ func update_selected_units() -> void: entity.deselect() +## Draws the selection rectangle during drag or selection, using optimized or styled rendering func _draw() -> void: if not (draw_selection or perform_selection):return if select_box and rect_style: diff --git a/dev/debug_tools.gd b/dev/debug_tools.gd index bcc9c84..dadf534 100644 --- a/dev/debug_tools.gd +++ b/dev/debug_tools.gd @@ -1,4 +1,5 @@ extends Control +## A utility node for drawing 3D debug visuals (lines, rays, cubes) in screen space. @export var MouseOverlay: Node @onready var Cam = get_viewport().get_camera_3d() @@ -7,36 +8,52 @@ extends Control func _ready() -> void: if !OS.is_debug_build(): self.queue_free() + return + + # Ensure the node processes and draws even when the game is paused. + process_mode = Node.PROCESS_MODE_ALWAYS + # Ensure the node is visible and set to draw in screen space. + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) +## A class representing a single debug line with start/end points, color, and duration. class Line: var Start:Vector3 var End:Vector3 var LineColor:Color - var time + var time:float - func _init(Start:Vector3, End:Vector3, LineColor, time): - self.Start = Start - self.End = End - self.LineColor = LineColor - self.time = time +## Constructor for DebugLine. [br] +## [param _start] Starting point in 3D space.[br] +## [param _end] Ending point in 3D space.[br] +## [param _color] Color of the line.[br] +## [param _time] Duration the line persists (seconds). + func _init(_Start:Vector3, _End:Vector3, _LineColor:Color, _time:float): + self.Start = _Start + self.End = _End + self.LineColor = _LineColor + self.time = _time +## Array storing all active debug lines. var Lines = [] +## Flag to track if a line was removed, triggering a redraw. var RemovedLine = false func _process(delta): for i in range(len(Lines)): Lines[i].time -= delta - + # Trigger a redraw if lines exist or a line was removed. if (len(Lines) > 0 || RemovedLine): queue_redraw() #Calls _draw RemovedLine = false func _draw(): - + # Exit early if no lines to draw or camera is not available. + if Lines.is_empty() or not Cam: + return for i in range(len(Lines)): if Lines[i].Start.length() == 0:return var ScreenPointStart = Cam.unproject_position(Lines[i].Start) @@ -61,57 +78,69 @@ func _draw(): i -= 1 -## start point, end point, color, time (optional) -func DrawLine(Start, End, time = 0.0, LineColor = Color(1.0, 0.0, 0.0, 1.0)): +## Draws a line between two 3D points. [br] +## [param start] Starting point in 3D space.[br] +## [param end] Ending point in 3D space.[br] +## [param time] Duration the line persists (seconds, default: 0.0 for one frame).[br] +## [param color] Color of the line (default: red, fully opaque). +func DrawLine(Start, End, time := 0.0, LineColor := Color(1.0, 0.0, 0.0, 1.0)): Lines.append(Line.new(Start, End, LineColor, time)) -## start point, velocity (direction and magnitude), color, time (optional) -func DrawRay(Start, Ray, time = 0.0, LineColor = Color(1.0, 0.0, 0.0, 1.0)): +## Draws a ray from a starting point in a given direction.[br] +## [param start] Starting point in 3D space.[br] +## [param ray] Direction and magnitude of the ray (Vector3).[br] +## [param time] Duration the ray persists (seconds, default: 0.0 for one frame).[br] +## [param color] Color of the ray (default: red, fully opaque). +func DrawRay(Start, Ray, time := 0.0, LineColor := Color(1.0, 0.0, 0.0, 1.0)): Lines.append(Line.new(Start, Start + Ray, LineColor, time)) -## start point, half extents (float), color, time (optional) -func DrawCube(Center, HalfExtents, time = 0.0, LineColor = Color(1.0, 0.0, 0.0, 1.0)): +## Draws a wireframe cube in 3D space.[br] +## [param center] Center point of the cube in 3D space.[br] +## [param half_extents] Half the width of the cube (default: 0.1).[br] +## [param time] Duration the cube persists (seconds, default: 0.0 for one frame).[br] +## [param color] Color of the cube's edges (default: red, fully opaque). +func DrawCube(Center, HalfExtents := 0.1, time := 0.0, LineColor := Color(1.0, 0.0, 0.0, 1.0)): #Start at the 'top left' var LinePointStart = Center LinePointStart.x -= HalfExtents LinePointStart.y += HalfExtents LinePointStart.z -= HalfExtents - #Draw top square + # Draw top square (four edges). var LinePointEnd = LinePointStart + Vector3(0, 0, HalfExtents * 2.0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); LinePointStart = LinePointEnd LinePointEnd = LinePointStart + Vector3(HalfExtents * 2.0, 0, 0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); LinePointStart = LinePointEnd LinePointEnd = LinePointStart + Vector3(0, 0, -HalfExtents * 2.0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); LinePointStart = LinePointEnd LinePointEnd = LinePointStart + Vector3(-HalfExtents * 2.0, 0, 0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); - #Draw bottom square + # Draw bottom square (four edges). LinePointStart = LinePointEnd + Vector3(0, -HalfExtents * 2.0, 0) LinePointEnd = LinePointStart + Vector3(0, 0, HalfExtents * 2.0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); LinePointStart = LinePointEnd LinePointEnd = LinePointStart + Vector3(HalfExtents * 2.0, 0, 0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); LinePointStart = LinePointEnd LinePointEnd = LinePointStart + Vector3(0, 0, -HalfExtents * 2.0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); LinePointStart = LinePointEnd LinePointEnd = LinePointStart + Vector3(-HalfExtents * 2.0, 0, 0) - DrawLine(LinePointStart, LinePointEnd, LineColor, time); + DrawLine(LinePointStart, LinePointEnd, time, LineColor); - #Draw vertical lines + # Draw vertical lines (four edges connecting top and bottom squares). LinePointStart = LinePointEnd - DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), LineColor, time) + DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0),time, LineColor) LinePointStart += Vector3(0, 0, HalfExtents * 2.0) - DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), LineColor, time) + DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), time, LineColor) LinePointStart += Vector3(HalfExtents * 2.0, 0, 0) - DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), LineColor, time) + DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), time, LineColor) LinePointStart += Vector3(0, 0, -HalfExtents * 2.0) - DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), LineColor, time) + DrawRay(LinePointStart, Vector3(0, HalfExtents * 2.0, 0), time, LineColor)