109 lines
3.4 KiB
GDScript
109 lines
3.4 KiB
GDScript
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()
|