extends Control class_name DotPatternGenerator # Dot pattern settings const DOT_SPACING = 30 const DOT_SIZE = 2 const DOT_COLOR = Color(0.3, 0.3, 0.3, 0.5) const PATH_DOT_COLOR = Color(0.4, 0.4, 0.6, 0.8) const PATH_DOT_SIZE = 3 const HIGHLIGHT_RADIUS = 150 # For path highlights var map_screen = null var highlight_dots = false func _init(highlight: bool = false): highlight_dots = highlight # Don't process input mouse_filter = Control.MOUSE_FILTER_IGNORE func _ready(): # Apply the pattern generate_dots() # Find map screen if we're highlighting paths if highlight_dots: map_screen = find_map_screen() func find_map_screen(): var parent = get_parent() while parent != null: if parent is MapScreen: return parent parent = parent.get_parent() return null func generate_dots(): # Clear existing dots for child in get_children(): child.queue_free() # Get the size of this control var control_size = size # Calculate how many dots we need var cols = int(control_size.x / DOT_SPACING) + 1 var rows = int(control_size.y / DOT_SPACING) + 1 # Create dots for i in range(rows): for j in range(cols): var dot_position = Vector2(j * DOT_SPACING, i * DOT_SPACING) var on_path = false # If highlighting, check if dot is near a path if highlight_dots and map_screen != null: on_path = is_near_path(dot_position) # Create the dot with appropriate style var dot = ColorRect.new() dot.size = Vector2(DOT_SIZE, DOT_SIZE) if not on_path else Vector2(PATH_DOT_SIZE, PATH_DOT_SIZE) dot.color = DOT_COLOR if not on_path else PATH_DOT_COLOR dot.position = dot_position - (dot.size / 2) add_child(dot) func is_near_path(position: Vector2) -> bool: # If no map screen, can't check paths if map_screen == null: return false # Get connections from map screen for line in map_screen.connection_lines: if line.get_point_count() < 2: continue # Check distance to line segment var start = line.get_point_position(0) var end = line.get_point_position(1) # Adjust for potential offset in the map container start += map_screen.map_container.position end += map_screen.map_container.position # Check if point is near the line var distance = distance_to_line_segment(position, start, end) if distance < HIGHLIGHT_RADIUS: return true return false # Calculate distance from point to line segment func distance_to_line_segment(point: Vector2, line_start: Vector2, line_end: Vector2) -> float: var line_vec = line_end - line_start var point_vec = point - line_start var line_length_squared = line_vec.length_squared() if line_length_squared == 0: return point_vec.length() # Line segment is a point # Calculate projection of point onto line var t = max(0, min(1, point_vec.dot(line_vec) / line_length_squared)) var projection = line_start + t * line_vec # Return distance from point to projection return (point - projection).length() # Call this when the map changes to update dot highlights func update_dots(): if highlight_dots and map_screen != null: generate_dots()