spaceship/ui/ScannerGuidance.gd

78 lines
2.9 KiB
GDScript3
Raw Normal View History

class_name ScannerGuidance
extends Control
const PLANET_DEFINITIONS = preload("res://planets/PlanetDefinitions.gd")
const EDGE_MARGIN: float = 34.0
@onready var indicator: Control = $Indicator
@onready var target_label: Label = $TargetLabel
var fleet: Node2D
func _ready() -> void:
fleet = get_tree().get_first_node_in_group("player_fleet") as Node2D
visible = false
func _process(_delta: float) -> void:
var target: Dictionary = GameState.active_scanner_target()
if target.is_empty() or GameState.intro_active or _modal_is_open():
visible = false
return
if fleet == null or not is_instance_valid(fleet):
fleet = get_tree().get_first_node_in_group("player_fleet") as Node2D
if fleet == null:
visible = false
return
visible = true
var target_world := Vector2(target.world_position)
var viewport_size: Vector2 = get_viewport_rect().size
var screen_position: Vector2 = get_viewport().get_canvas_transform() * target_world
var safe_margin: Vector2 = Vector2.ONE * EDGE_MARGIN + indicator.size * 0.5
var safe_rect := Rect2(safe_margin, viewport_size - safe_margin * 2.0)
var at: Vector2 = screen_position if safe_rect.has_point(screen_position) \
else edge_position(viewport_size, screen_position - viewport_size * 0.5)
indicator.position = at - indicator.size * 0.5
var toward_target: Vector2 = target_world - fleet.get_centroid()
if toward_target.length_squared() > 0.01:
indicator.rotation = toward_target.angle() + PI / 2.0
var definition: Resource = PLANET_DEFINITIONS.get_definition(
String(target.definition_id))
if definition != null:
indicator.glow_color = definition.map_color
indicator.queue_redraw()
var sectors: float = toward_target.length() / WorldGen.CHUNK_SIZE
target_label.text = "%s · %.1f SECTORS" % [
String(target.get("name", "SCANNER TARGET")).to_upper(), sectors]
_place_label(at, viewport_size)
func edge_position(viewport_size: Vector2, direction: Vector2) -> Vector2:
var center: Vector2 = viewport_size * 0.5
if direction.length_squared() <= 0.01:
return center
var half: Vector2 = center - Vector2.ONE * EDGE_MARGIN - indicator.size * 0.5
var scale_to_edge: float = minf(half.x / maxf(absf(direction.x), 0.001),
half.y / maxf(absf(direction.y), 0.001))
return center + direction * scale_to_edge
func _place_label(indicator_center: Vector2, viewport_size: Vector2) -> void:
var toward_center: Vector2 = viewport_size * 0.5 - indicator_center
if toward_center.length_squared() < 0.01:
toward_center = Vector2.DOWN
var wanted: Vector2 = indicator_center + toward_center.normalized() * 105.0 \
- target_label.size * 0.5
target_label.position = Vector2(
clampf(wanted.x, EDGE_MARGIN, viewport_size.x - target_label.size.x - EDGE_MARGIN),
clampf(wanted.y, EDGE_MARGIN, viewport_size.y - target_label.size.y - EDGE_MARGIN))
func _modal_is_open() -> bool:
for menu in get_tree().get_nodes_in_group("modal_menus"):
if menu.is_visible_in_tree():
return true
return false