class_name OverheadChargeSegments extends Node2D @export var charge_component_path: NodePath = ^"../ChargeComponent" @export var segment_count := 3 @export var segment_size := Vector2(42.0, 12.0) @export var segment_gap := 5.0 @export var border_width := 2.0 @export var background_color := Color(0.04, 0.055, 0.07, 0.86) @export var fill_color := Color(0.25, 0.88, 1.0, 0.96) @export var ready_fill_color := Color(1.0, 0.72, 0.18, 1.0) @export var border_color := Color(0.88, 0.96, 1.0, 0.9) @export var inactive_linger_seconds := 0.22 var _current := 0.0 var _maximum := 1.0 var _is_charge_ready := false var _active := false var _visual_linger_remaining := 0.0 @onready var _charge_component: Node = get_node_or_null(charge_component_path) func _ready() -> void: segment_count = maxi(1, segment_count) z_index = max(z_index, 96) visible = false if _charge_component != null and _charge_component.has_signal("charge_changed"): if not _charge_component.is_connected("charge_changed", _on_charge_changed): _charge_component.connect("charge_changed", _on_charge_changed) func active() -> bool: return _active func current_progress_segments() -> float: if not _active and _visual_linger_remaining <= 0.0: return 0.0 if _is_charge_ready: return float(segment_count) if _maximum <= float(segment_count - 1) + 0.1: return clampf(_current + 1.0, 0.0, float(segment_count)) return clampf((_current / maxf(0.001, _maximum)) * float(segment_count), 0.0, float(segment_count)) func _on_charge_changed(current: float, maximum: float, ready: bool, active: bool) -> void: var was_showing := _active or _visual_linger_remaining > 0.0 if active: _current = maxf(0.0, current) _maximum = maxf(0.001, maximum) _is_charge_ready = ready _visual_linger_remaining = 0.0 modulate.a = 1.0 visible = true else: if was_showing and inactive_linger_seconds > 0.0: _visual_linger_remaining = inactive_linger_seconds visible = true else: _visual_linger_remaining = 0.0 modulate.a = 1.0 visible = false _active = active queue_redraw() func _process(delta: float) -> void: if _visual_linger_remaining <= 0.0: return _visual_linger_remaining = maxf(0.0, _visual_linger_remaining - delta) modulate.a = clampf(_visual_linger_remaining / maxf(0.001, inactive_linger_seconds), 0.0, 1.0) if _visual_linger_remaining <= 0.0: visible = false modulate.a = 1.0 queue_redraw() func _draw() -> void: if not _active and _visual_linger_remaining <= 0.0: return var safe_count := maxi(1, segment_count) var total_width := segment_size.x * float(safe_count) + segment_gap * float(maxi(0, safe_count - 1)) var origin := Vector2(-total_width * 0.5, 0.0) var progress := current_progress_segments() var plate_rect := Rect2(origin - Vector2(5.0, 4.0), Vector2(total_width + 10.0, segment_size.y + 8.0)) draw_rect(plate_rect, Color(0.0, 0.0, 0.0, 0.68), true) draw_rect(plate_rect, Color(0.9, 0.96, 1.0, 0.42), false, 1.0) for index: int in range(safe_count): var rect := Rect2(origin + Vector2(float(index) * (segment_size.x + segment_gap), 0.0), segment_size) draw_rect(rect, background_color, true) var fill_ratio := clampf(progress - float(index), 0.0, 1.0) if fill_ratio > 0.0: var fill_rect := Rect2(rect.position + Vector2(border_width, border_width), Vector2(maxf(0.0, (segment_size.x - border_width * 2.0) * fill_ratio), maxf(0.0, segment_size.y - border_width * 2.0))) draw_rect(fill_rect, ready_fill_color if _is_charge_ready else fill_color, true) draw_rect(rect, border_color, false, border_width)