Validate POC A and POC B foundations
This commit is contained in:
1 parent
44fd4b4b43
commit
c38e09a663
47 files changed
+4990
-35
No files matched your search
@@ -0,0 +1,251 @@
|
||||
class_name SonarHud
|
||||
extends CanvasLayer
|
||||
|
||||
const SonarModelScript = preload("res://src/sonar_model.gd")
|
||||
const SonarReliefRendererScript = preload("res://src/sonar_relief_renderer.gd")
|
||||
|
||||
signal expanded_changed(is_expanded: bool)
|
||||
|
||||
var _renderer: SubViewport
|
||||
var _telemetry_label: Label
|
||||
var _compact_panel: PanelContainer
|
||||
var _compact_status: Label
|
||||
var _expanded_overlay: ColorRect
|
||||
var _expanded_status: Label
|
||||
var _help_label: Label
|
||||
var _expanded := false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
layer = 2
|
||||
_renderer = SonarReliefRendererScript.new()
|
||||
_renderer.name = "SonarReliefRenderer"
|
||||
add_child(_renderer)
|
||||
_build_hud()
|
||||
|
||||
|
||||
func update_telemetry(snapshot: Dictionary) -> void:
|
||||
_telemetry_label.text = "PROFONDEUR %.1f m\nVITESSE %.1f m/s\nPROPULSION %d%%" % [
|
||||
float(snapshot.get("depth", 0.0)),
|
||||
float(snapshot.get("speed", 0.0)),
|
||||
int(round(float(snapshot.get("battery", 0.0)))),
|
||||
]
|
||||
|
||||
|
||||
func update_sonar_pose(new_transform: Transform3D) -> void:
|
||||
_renderer.update_submarine_pose(new_transform)
|
||||
|
||||
|
||||
func show_ping_started(_max_range: float) -> void:
|
||||
_renderer.start_scan()
|
||||
_set_status(
|
||||
"SCAN 0% • PREMIERS RETOURS EN ATTENTE",
|
||||
Color("9cf7f2"),
|
||||
"SCAN 0%"
|
||||
)
|
||||
|
||||
|
||||
func show_ping_progress(
|
||||
current_cells: Array[Dictionary],
|
||||
previous_cells: Array[Dictionary],
|
||||
_max_range: float,
|
||||
progress: float
|
||||
) -> void:
|
||||
_renderer.update_scan(current_cells, previous_cells, progress)
|
||||
var metal_detected := _metal_cell_count(current_cells) > 0
|
||||
var color := Color("ffad52") if metal_detected else Color("9cf7f2")
|
||||
var suffix := " • ANOMALIE" if metal_detected else ""
|
||||
var status := "SCAN %d%%%s" % [int(round(progress * 100.0)), suffix]
|
||||
_set_status(status, color, status)
|
||||
|
||||
|
||||
func show_ping_results(
|
||||
current_cells: Array[Dictionary],
|
||||
_previous_cells: Array[Dictionary],
|
||||
_max_range: float
|
||||
) -> void:
|
||||
_renderer.finish_scan(current_cells)
|
||||
var metal_count := _metal_cell_count(current_cells)
|
||||
var status := "SCAN TERMINÉ • RELIEF RECONSTRUIT"
|
||||
var color := Color("9cf7f2")
|
||||
if metal_count > 0:
|
||||
status += " • ANOMALIE ORANGE"
|
||||
color = Color("ffad52")
|
||||
_set_status(
|
||||
status,
|
||||
color,
|
||||
"SCAN TERMINÉ • ANOMALIE" if metal_count > 0 else "SCAN TERMINÉ"
|
||||
)
|
||||
|
||||
|
||||
func toggle_expanded() -> void:
|
||||
set_expanded(not _expanded)
|
||||
|
||||
|
||||
func set_expanded(is_expanded: bool) -> void:
|
||||
if _expanded == is_expanded:
|
||||
return
|
||||
_expanded = is_expanded
|
||||
_expanded_overlay.visible = is_expanded
|
||||
_compact_panel.visible = not is_expanded
|
||||
_help_label.visible = not is_expanded
|
||||
expanded_changed.emit(is_expanded)
|
||||
|
||||
|
||||
func is_expanded() -> bool:
|
||||
return _expanded
|
||||
|
||||
|
||||
func relief_renderer() -> SubViewport:
|
||||
return _renderer
|
||||
|
||||
|
||||
func _set_status(text: String, color: Color, compact_text: String = "") -> void:
|
||||
_compact_status.text = text if compact_text.is_empty() else compact_text
|
||||
_compact_status.modulate = color
|
||||
_expanded_status.text = text
|
||||
_expanded_status.modulate = color
|
||||
|
||||
|
||||
func _metal_cell_count(cells: Array[Dictionary]) -> int:
|
||||
var count := 0
|
||||
for cell: Dictionary in cells:
|
||||
if int(cell["material"]) == SonarModelScript.MaterialCategory.METAL:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
func _build_hud() -> void:
|
||||
var root := Control.new()
|
||||
root.name = "SonarHudRoot"
|
||||
root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
add_child(root)
|
||||
|
||||
var objective := Label.new()
|
||||
objective.set_anchors_preset(Control.PRESET_CENTER_TOP)
|
||||
objective.position = Vector2(-390.0, 24.0)
|
||||
objective.size = Vector2(780.0, 38.0)
|
||||
objective.text = "LISEZ LE RELIEF • FRANCHISSEZ L'OUVERTURE • IDENTIFIEZ L'ANOMALIE"
|
||||
objective.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
objective.add_theme_font_size_override("font_size", 18)
|
||||
root.add_child(objective)
|
||||
|
||||
var telemetry_panel := PanelContainer.new()
|
||||
telemetry_panel.position = Vector2(22.0, 82.0)
|
||||
telemetry_panel.size = Vector2(280.0, 118.0)
|
||||
root.add_child(telemetry_panel)
|
||||
_telemetry_label = Label.new()
|
||||
_telemetry_label.text = "PROFONDEUR\nVITESSE\nPROPULSION"
|
||||
_telemetry_label.add_theme_font_size_override("font_size", 16)
|
||||
telemetry_panel.add_child(_telemetry_label)
|
||||
|
||||
var instruction_panel := PanelContainer.new()
|
||||
instruction_panel.position = Vector2(22.0, 214.0)
|
||||
instruction_panel.size = Vector2(294.0, 112.0)
|
||||
root.add_child(instruction_panel)
|
||||
var instruction := Label.new()
|
||||
instruction.text = (
|
||||
"F ÉMETTRE UN SCAN MANUEL\n"
|
||||
+ "Le relief apparaît du proche au lointain.\n"
|
||||
+ "L'orange signale un retour anormal."
|
||||
)
|
||||
instruction.modulate = Color(0.78, 0.94, 0.95, 0.94)
|
||||
instruction_panel.add_child(instruction)
|
||||
|
||||
_compact_panel = PanelContainer.new()
|
||||
_compact_panel.set_anchors_preset(Control.PRESET_TOP_RIGHT)
|
||||
_compact_panel.position = Vector2(-342.0, 82.0)
|
||||
_compact_panel.size = Vector2(320.0, 276.0)
|
||||
root.add_child(_compact_panel)
|
||||
var compact_box := VBoxContainer.new()
|
||||
compact_box.add_theme_constant_override("separation", 6)
|
||||
_compact_panel.add_child(compact_box)
|
||||
var compact_title := Label.new()
|
||||
compact_title.text = "SONAR BATHYMÉTRIQUE • AGRANDIR"
|
||||
compact_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
compact_title.add_theme_font_size_override("font_size", 14)
|
||||
compact_box.add_child(compact_title)
|
||||
var compact_view := _make_sonar_texture_rect(Vector2(298.0, 190.0))
|
||||
compact_view.tooltip_text = "Cliquez pour ouvrir le grand écran sonar"
|
||||
compact_view.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
compact_view.gui_input.connect(_on_compact_view_input)
|
||||
compact_box.add_child(compact_view)
|
||||
_compact_status = Label.new()
|
||||
_compact_status.text = "F • LANCER LE PREMIER SCAN"
|
||||
_compact_status.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
compact_box.add_child(_compact_status)
|
||||
var compact_reference := Label.new()
|
||||
compact_reference.text = "PORTÉE 95 M • SOUS-MARIN EN BAS • CAP VERS LE HAUT"
|
||||
compact_reference.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
compact_reference.modulate = Color(0.62, 0.82, 0.84, 0.86)
|
||||
compact_reference.add_theme_font_size_override("font_size", 11)
|
||||
compact_box.add_child(compact_reference)
|
||||
|
||||
_expanded_overlay = ColorRect.new()
|
||||
_expanded_overlay.name = "ExpandedSonarOverlay"
|
||||
_expanded_overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
_expanded_overlay.color = Color(0.0, 0.015, 0.02, 0.96)
|
||||
_expanded_overlay.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
_expanded_overlay.visible = false
|
||||
root.add_child(_expanded_overlay)
|
||||
|
||||
var expanded_panel := PanelContainer.new()
|
||||
expanded_panel.position = Vector2(110.0, 34.0)
|
||||
expanded_panel.size = Vector2(1060.0, 652.0)
|
||||
_expanded_overlay.add_child(expanded_panel)
|
||||
var expanded_box := VBoxContainer.new()
|
||||
expanded_box.add_theme_constant_override("separation", 7)
|
||||
expanded_panel.add_child(expanded_box)
|
||||
var expanded_title := Label.new()
|
||||
expanded_title.text = "SONAR BATHYMÉTRIQUE • PORTÉE 95 M • CAP VERS LE HAUT"
|
||||
expanded_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
expanded_title.add_theme_font_size_override("font_size", 19)
|
||||
expanded_box.add_child(expanded_title)
|
||||
var expanded_view := _make_sonar_texture_rect(Vector2(1038.0, 556.0))
|
||||
expanded_box.add_child(expanded_view)
|
||||
_expanded_status = Label.new()
|
||||
_expanded_status.text = "F • LANCER LE PREMIER SCAN"
|
||||
_expanded_status.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_expanded_status.add_theme_font_size_override("font_size", 16)
|
||||
expanded_box.add_child(_expanded_status)
|
||||
var legend := Label.new()
|
||||
legend.text = "BLEU PROFOND • VERT/JAUNE HAUTEUR • ORANGE CAISSE/ANOMALIE • NOIR INCONNU"
|
||||
legend.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
legend.modulate = Color(0.68, 0.88, 0.90, 0.90)
|
||||
expanded_box.add_child(legend)
|
||||
|
||||
var close_button := Button.new()
|
||||
close_button.position = Vector2(1044.0, 46.0)
|
||||
close_button.size = Vector2(108.0, 36.0)
|
||||
close_button.text = "FERMER ×"
|
||||
close_button.pressed.connect(func() -> void: set_expanded(false))
|
||||
_expanded_overlay.add_child(close_button)
|
||||
|
||||
_help_label = Label.new()
|
||||
_help_label.set_anchors_preset(Control.PRESET_BOTTOM_WIDE)
|
||||
_help_label.offset_left = 20.0
|
||||
_help_label.offset_top = -42.0
|
||||
_help_label.offset_right = -20.0
|
||||
_help_label.offset_bottom = -12.0
|
||||
_help_label.text = "F scanner • Tab agrandir/fermer • W/S propulsion • A/D gouvernail • Espace/Ctrl profondeur • Échap souris"
|
||||
_help_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_help_label.modulate = Color(0.75, 0.90, 0.94, 0.9)
|
||||
root.add_child(_help_label)
|
||||
|
||||
|
||||
func _make_sonar_texture_rect(minimum_size: Vector2) -> TextureRect:
|
||||
var view := TextureRect.new()
|
||||
view.custom_minimum_size = minimum_size
|
||||
view.texture = _renderer.get_texture()
|
||||
view.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
view.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
return view
|
||||
|
||||
|
||||
func _on_compact_view_input(event: InputEvent) -> void:
|
||||
if (
|
||||
event is InputEventMouseButton
|
||||
and event.button_index == MOUSE_BUTTON_LEFT
|
||||
and event.pressed
|
||||
):
|
||||
set_expanded(true)
|
||||
Reference in new issue
Block a user