75 lines
2.6 KiB
GDScript
75 lines
2.6 KiB
GDScript
@tool
|
|
extends PanelContainer
|
|
|
|
enum Connection { CONNECTED, DEGRADED, DISCONNECTED }
|
|
|
|
@export var downlink_capacity_gbps := 10.0
|
|
@export var uplink_capacity_gbps := 10.0
|
|
@export_range(0, 1) var warning_fraction := 0.8
|
|
@export_range(0, 1) var fault_fraction := 0.95
|
|
@export var loss_window_seconds := 10.0
|
|
@export var stale_after_seconds := 2.0
|
|
@export var link_icon: Texture2D:
|
|
set(value):
|
|
link_icon = value
|
|
if is_node_ready():
|
|
%LinkIcon.texture = value
|
|
|
|
var _received_ms := -1
|
|
var _state := Connection.CONNECTED
|
|
var _down := 0.0
|
|
var _up := 0.0
|
|
var _loss := 0.0
|
|
var _stale := false
|
|
|
|
func _ready() -> void:
|
|
%LinkIcon.texture = link_icon
|
|
theme_changed.connect(_update_icon)
|
|
_update_icon()
|
|
_refresh()
|
|
|
|
## Rates in Gbps; loss in percent over loss_window_seconds.
|
|
func set_telemetry(down: float, up: float, loss_percent: float, state: int = Connection.CONNECTED) -> bool:
|
|
if not is_finite(down) or not is_finite(up) or not is_finite(loss_percent) or down < 0 or up < 0 or loss_percent < 0 or loss_percent > 100 or state < 0 or state > 2:
|
|
return false
|
|
_down = down
|
|
_up = up
|
|
_loss = loss_percent
|
|
_state = state
|
|
_received_ms = Time.get_ticks_msec()
|
|
_refresh()
|
|
return true
|
|
|
|
func clear_telemetry() -> void:
|
|
_received_ms = -1
|
|
_refresh()
|
|
|
|
func _process(_delta: float) -> void:
|
|
var stale := _received_ms >= 0 and Time.get_ticks_msec() - _received_ms > stale_after_seconds * 1000
|
|
if stale != _stale:
|
|
_refresh()
|
|
|
|
func _refresh() -> void:
|
|
if not is_node_ready():
|
|
return
|
|
var missing := _received_ms < 0
|
|
_stale = not missing and Time.get_ticks_msec() - _received_ms > stale_after_seconds * 1000
|
|
var measured := not missing and _state != Connection.DISCONNECTED
|
|
%State.text = "NO TELEMETRY" if missing else ("STALE" if _stale else ["CONNECTED", "DEGRADED", "DISCONNECTED"][_state])
|
|
%State.theme_type_variation = "LinkMuted" if missing else ("LinkRateWarning" if _stale or _state == Connection.DEGRADED else ("LinkRateFault" if _state == Connection.DISCONNECTED else "Label"))
|
|
var gauges := [%Downlink, %Uplink]
|
|
for index in range(2):
|
|
gauges[index].capacity_gbps = maxf([downlink_capacity_gbps, uplink_capacity_gbps][index], 0.001)
|
|
gauges[index].warning_fraction = warning_fraction
|
|
gauges[index].fault_fraction = maxf(warning_fraction, fault_fraction)
|
|
gauges[index].rate_gbps = [_down, _up][index]
|
|
gauges[index].available = measured
|
|
gauges[index].refresh()
|
|
%LossValue.text = "%.2f%%" % _loss if measured else "—"
|
|
%LossWindow.text = "%.0f s window" % loss_window_seconds + (" · held" if _stale else "")
|
|
|
|
func _update_icon() -> void:
|
|
var tint := get_theme_color("status_icon", "SurfaceSide")
|
|
tint.a = 0.06
|
|
%LinkIcon.self_modulate = tint
|