Implement production vertical slice foundation

This commit is contained in:
chindit committed 2026-10-02 15:27:48 +02:00
1 parent 9d4a89f355
commit a18e82eb44
104 files changed
+10595 -268

No files matched your search

@@ -0,0 +1,82 @@
class_name CockpitCameraController
extends Node3D
const CameraLookCommand = preload(
"res://game/application/vehicle/camera_look_command.gd"
)
const VehicleTelemetry = preload("res://game/application/dive/vehicle_telemetry.gd")
@export var minimum_pitch_radians := -0.30
@export var maximum_pitch_radians := 0.20
@export var maximum_yaw_radians := deg_to_rad(30.0)
@export var feedback_response := 4.5
@export var maximum_feedback_pitch_radians := deg_to_rad(18.0)
@export var maximum_feedback_roll_radians := deg_to_rad(16.0) * 0.55
var _look_yaw := 0.0
var _look_pitch := -0.04
var _feedback_pitch := 0.0
var _feedback_roll := 0.0
var _target_feedback_pitch := 0.0
var _target_feedback_roll := 0.0
func apply_look(command: CameraLookCommand) -> void:
if command == null or not command.validation_error().is_empty():
return
if command.recenter_requested:
_look_yaw = 0.0
_look_pitch = -0.04
else:
_look_yaw = clampf(
_look_yaw + command.yaw_delta_radians,
-maximum_yaw_radians,
maximum_yaw_radians
)
_look_pitch = clampf(
_look_pitch + command.pitch_delta_radians,
minimum_pitch_radians,
maximum_pitch_radians
)
_apply_rotation()
func present_telemetry(telemetry: VehicleTelemetry) -> void:
if telemetry == null:
return
_target_feedback_pitch = (
-telemetry.vertical_effort * maximum_feedback_pitch_radians
)
_target_feedback_roll = (
-telemetry.steering_effort * maximum_feedback_roll_radians
)
func look_yaw_radians() -> float:
return _look_yaw
func look_pitch_radians() -> float:
return _look_pitch
func _process(delta: float) -> void:
_feedback_pitch = lerpf(
_feedback_pitch,
_target_feedback_pitch,
1.0 - exp(-feedback_response * delta)
)
_feedback_roll = lerpf(
_feedback_roll,
_target_feedback_roll,
1.0 - exp(-feedback_response * delta)
)
_apply_rotation()
func _apply_rotation() -> void:
rotation = Vector3(
_look_pitch + _feedback_pitch,
_look_yaw,
_feedback_roll
)
@@ -0,0 +1,12 @@
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://game/presentation/cockpit/cockpit_camera_controller.gd" id="1_camera"]
[node name="CockpitCameraRig" type="Node3D"]
position = Vector3(0, 0.52, -0.48)
script = ExtResource("1_camera")
[node name="Camera" type="Camera3D" parent="."]
current = true
fov = 82.0
near = 0.05
+61
View File
@@ -0,0 +1,61 @@
class_name CockpitHud
extends Control
const DiveUpdate = preload("res://game/domain/dive/dive_update.gd")
const DiveAlertLevel = preload("res://game/domain/dive/dive_alert_level.gd")
const DiveTerminalReason = preload("res://game/domain/dive/dive_terminal_reason.gd")
const VehicleTelemetry = preload("res://game/application/dive/vehicle_telemetry.gd")
@onready var _alert_panel: PanelContainer = %AlertPanel
@onready var _alert_label: Label = %AlertLabel
@onready var _ejection_panel: PanelContainer = %EjectionPanel
@onready var _ejection_label: Label = %EjectionLabel
@onready var _terminal_panel: PanelContainer = %TerminalPanel
@onready var _terminal_label: Label = %TerminalLabel
func present(update: DiveUpdate, telemetry: VehicleTelemetry) -> void:
if update == null or update.snapshot == null or telemetry == null:
return
var snapshot = update.snapshot
_alert_panel.visible = snapshot.alerts.maximum != DiveAlertLevel.Value.NORMAL
_alert_label.text = "ALERTE · %s" % _alert_text(snapshot.alerts.maximum)
_ejection_panel.visible = snapshot.ejection.held_seconds > 0.0
_ejection_label.text = "ÉJECTION %.0f %%" % (snapshot.ejection.ratio * 100.0)
_terminal_panel.visible = snapshot.is_terminal()
if snapshot.is_terminal():
_terminal_label.text = "%s\nÉchap pour ouvrir le menu de pause." % [
_terminal_text(snapshot.terminal_reason)
]
func alert_overlay_visible() -> bool:
return _alert_panel.visible
func _alert_text(level: DiveAlertLevel.Value) -> String:
match level:
DiveAlertLevel.Value.NORMAL:
return tr("NORMAL")
DiveAlertLevel.Value.ATTENTION:
return tr("ATTENTION")
DiveAlertLevel.Value.RETURN:
return tr("RETOUR")
DiveAlertLevel.Value.CRITICAL:
return tr("CRITIQUE")
DiveAlertLevel.Value.FAILURE:
return tr("DÉFAILLANCE")
return tr("INCONNU")
func _terminal_text(reason: DiveTerminalReason.Value) -> String:
match reason:
DiveTerminalReason.Value.VOLUNTARY_EJECTION:
return tr("ÉJECTION DÉCLENCHÉE")
DiveTerminalReason.Value.OXYGEN_DEPLETED:
return tr("OXYGÈNE ÉPUISÉ")
DiveTerminalReason.Value.HULL_DESTROYED:
return tr("COQUE DÉTRUITE")
DiveTerminalReason.Value.RETURNED:
return tr("RETOUR TERMINÉ")
return tr("PLONGÉE TERMINÉE")
+109
View File
@@ -0,0 +1,109 @@
[gd_scene load_steps=4 format=3]
[ext_resource type="Script" path="res://game/presentation/cockpit/cockpit_hud.gd" id="1_hud"]
[sub_resource type="StyleBoxFlat" id="AlertStyle"]
bg_color = Color(0.14, 0.075, 0.02, 0.92)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(1, 0.75, 0.2, 1)
content_margin_left = 22.0
content_margin_top = 10.0
content_margin_right = 22.0
content_margin_bottom = 10.0
[sub_resource type="StyleBoxFlat" id="DangerStyle"]
bg_color = Color(0.16, 0.025, 0.018, 0.94)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(1, 0.42, 0.31, 1)
content_margin_left = 24.0
content_margin_top = 12.0
content_margin_right = 24.0
content_margin_bottom = 12.0
[node name="CockpitHud" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("1_hud")
[node name="AlertPanel" type="PanelContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_left = 590.0
offset_top = 26.0
offset_right = -590.0
offset_bottom = 78.0
grow_horizontal = 2
theme_override_styles/panel = SubResource("AlertStyle")
[node name="AlertLabel" type="Label" parent="AlertPanel"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.82, 0.42, 1)
theme_override_font_sizes/font_size = 20
text = "ALERTE · ATTENTION"
horizontal_alignment = 1
[node name="EjectionPanel" type="PanelContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -190.0
offset_top = -94.0
offset_right = 190.0
offset_bottom = -36.0
grow_horizontal = 2
grow_vertical = 0
theme_override_styles/panel = SubResource("DangerStyle")
[node name="EjectionLabel" type="Label" parent="EjectionPanel"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.48, 0.38, 1)
theme_override_font_sizes/font_size = 20
text = "ÉJECTION —"
horizontal_alignment = 1
[node name="TerminalPanel" type="PanelContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -280.0
offset_top = -82.0
offset_right = 280.0
offset_bottom = 82.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("DangerStyle")
[node name="TerminalLabel" type="Label" parent="TerminalPanel"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.74, 0.68, 1)
theme_override_font_sizes/font_size = 24
text = "PLONGÉE TERMINÉE"
horizontal_alignment = 1
vertical_alignment = 1
@@ -0,0 +1,118 @@
class_name CockpitInstrumentPanel
extends Node3D
const DiveUpdate = preload("res://game/domain/dive/dive_update.gd")
const DiveAlertLevel = preload("res://game/domain/dive/dive_alert_level.gd")
const ReturnEstimate = preload("res://game/domain/dive/return_estimate.gd")
const VehicleTelemetry = preload("res://game/application/dive/vehicle_telemetry.gd")
const COLOR_NORMAL := Color(0.45, 0.89, 0.90, 1.0)
const COLOR_ATTENTION := Color(1.0, 0.75, 0.20, 1.0)
const COLOR_CRITICAL := Color(1.0, 0.42, 0.31, 1.0)
@onready var _resources_label: Label3D = %ResourcesLabel
@onready var _navigation_label: Label3D = %NavigationLabel
@onready var _integrity_label: Label3D = %IntegrityLabel
@onready var _return_label: Label3D = %ReturnLabel
@onready var _status_label: Label3D = %StatusLabel
func present(update: DiveUpdate, telemetry: VehicleTelemetry) -> void:
if update == null or update.snapshot == null or telemetry == null:
return
var snapshot = update.snapshot
_resources_label.text = (
"BATTERIE\n%.1f / %.1f kWh · %.0f %%\n%.0f kW\n\nOXYGÈNE\n%.1f / %.1f L · %.0f %%\n%.1f L/min"
% [
snapshot.battery.remaining_kwh,
snapshot.battery.maximum_kwh,
snapshot.battery.ratio * 100.0,
snapshot.battery.current_power_kw,
snapshot.oxygen.remaining_l,
snapshot.oxygen.maximum_l,
snapshot.oxygen.ratio * 100.0,
snapshot.oxygen.consumption_l_per_min,
]
)
_navigation_label.text = (
"PROFONDEUR\n%.1f m\nMAX. CONSEILLÉ %.1f m\n\nVITESSE\n%.2f m/s"
% [
snapshot.depth.current_m,
snapshot.depth.certified_m,
telemetry.world_linear_velocity_mps.length(),
]
)
_integrity_label.text = (
"COQUE\n%.1f / %.1f · %.0f %%\n\nPRESSION\n%.2f / %.2f bar"
% [
snapshot.hull.current_integrity,
snapshot.hull.maximum_integrity,
snapshot.hull.ratio * 100.0,
snapshot.hull.exterior_pressure_bar,
snapshot.hull.certified_pressure_bar,
]
)
_return_label.text = _return_text(snapshot.return_estimate)
_status_label.text = "SYSTÈMES · %s" % _alert_text(snapshot.alerts.maximum)
_resources_label.modulate = _alert_color(
maxi(snapshot.alerts.battery, snapshot.alerts.oxygen)
)
_integrity_label.modulate = _alert_color(
maxi(snapshot.alerts.hull, snapshot.alerts.depth)
)
_status_label.modulate = _alert_color(snapshot.alerts.maximum)
func resources_text() -> String:
return _resources_label.text
func navigation_text() -> String:
return _navigation_label.text
func integrity_text() -> String:
return _integrity_label.text
func return_text() -> String:
return _return_label.text
func _return_text(estimate: ReturnEstimate) -> String:
match estimate.status:
ReturnEstimate.Status.SAFE:
return "RETOUR %.1f kWh · MARGE %.1f kWh" % [
estimate.required_kwh,
estimate.margin_kwh,
]
ReturnEstimate.Status.TIGHT:
return "RETOUR SERRÉ · MARGE %.1f kWh" % estimate.margin_kwh
ReturnEstimate.Status.INSUFFICIENT:
return "RETOUR INSUFFISANT · MANQUE %.1f kWh" % absf(
estimate.margin_kwh
)
return "RETOUR · INCONNU"
func _alert_text(level: DiveAlertLevel.Value) -> String:
match level:
DiveAlertLevel.Value.NORMAL:
return "NORMAL"
DiveAlertLevel.Value.ATTENTION:
return "ATTENTION"
DiveAlertLevel.Value.RETURN:
return "RETOUR"
DiveAlertLevel.Value.CRITICAL:
return "CRITIQUE"
DiveAlertLevel.Value.FAILURE:
return "DÉFAILLANCE"
return "INCONNU"
func _alert_color(level: DiveAlertLevel.Value) -> Color:
if level >= DiveAlertLevel.Value.CRITICAL:
return COLOR_CRITICAL
if level >= DiveAlertLevel.Value.ATTENTION:
return COLOR_ATTENTION
return COLOR_NORMAL
@@ -0,0 +1,450 @@
[gd_scene load_steps=19 format=3]
[ext_resource type="Script" path="res://game/presentation/cockpit/cockpit_instrument_panel.gd" id="1_instruments"]
[sub_resource type="StandardMaterial3D" id="SteelMaterial"]
albedo_color = Color(0.095, 0.12, 0.12, 1)
metallic = 0.82
roughness = 0.34
[sub_resource type="StandardMaterial3D" id="PaintedMaterial"]
albedo_color = Color(0.085, 0.185, 0.19, 1)
metallic = 0.58
roughness = 0.48
[sub_resource type="StandardMaterial3D" id="BrassMaterial"]
albedo_color = Color(0.36, 0.24, 0.075, 1)
metallic = 0.78
roughness = 0.31
[sub_resource type="StandardMaterial3D" id="RubberMaterial"]
albedo_color = Color(0.018, 0.024, 0.025, 1)
roughness = 0.88
[sub_resource type="StandardMaterial3D" id="GlassMaterial"]
transparency = 1
shading_mode = 0
albedo_color = Color(0.12, 0.42, 0.47, 0.09)
metallic = 0.12
roughness = 0.08
cull_mode = 2
[sub_resource type="StandardMaterial3D" id="ScreenMaterial"]
albedo_color = Color(0.006, 0.025, 0.028, 1)
metallic = 0.15
roughness = 0.22
emission_enabled = true
emission = Color(0.008, 0.07, 0.075, 1)
emission_energy_multiplier = 1.7
[sub_resource type="StandardMaterial3D" id="CyanMaterial"]
shading_mode = 0
albedo_color = Color(0.2, 0.78, 0.82, 1)
emission_enabled = true
emission = Color(0.12, 0.72, 0.76, 1)
emission_energy_multiplier = 3.2
[sub_resource type="StandardMaterial3D" id="AmberMaterial"]
shading_mode = 0
albedo_color = Color(0.95, 0.52, 0.08, 1)
emission_enabled = true
emission = Color(0.95, 0.33, 0.02, 1)
emission_energy_multiplier = 2.6
[sub_resource type="StandardMaterial3D" id="RedMaterial"]
shading_mode = 0
albedo_color = Color(0.82, 0.08, 0.045, 1)
emission_enabled = true
emission = Color(0.92, 0.055, 0.025, 1)
emission_energy_multiplier = 2.8
[sub_resource type="BoxMesh" id="UnitBoxMesh"]
size = Vector3(1, 1, 1)
[sub_resource type="TorusMesh" id="PortholeTorusMesh"]
inner_radius = 0.56
outer_radius = 0.71
rings = 48
ring_segments = 16
[sub_resource type="CylinderMesh" id="GlassCylinderMesh"]
top_radius = 0.56
bottom_radius = 0.56
height = 0.012
radial_segments = 64
[sub_resource type="CylinderMesh" id="BoltMesh"]
top_radius = 0.026
bottom_radius = 0.026
height = 0.045
radial_segments = 12
[sub_resource type="QuadMesh" id="ScreenQuadMesh"]
size = Vector2(1, 1)
[sub_resource type="CylinderMesh" id="LeverMesh"]
top_radius = 0.018
bottom_radius = 0.023
height = 0.24
radial_segments = 12
[sub_resource type="SphereMesh" id="KnobMesh"]
radius = 0.046
height = 0.092
radial_segments = 16
rings = 8
[sub_resource type="CylinderMesh" id="DialMesh"]
top_radius = 0.105
bottom_radius = 0.105
height = 0.035
radial_segments = 32
[node name="CockpitInterior" type="Node3D"]
script = ExtResource("1_instruments")
[node name="CabinShell" type="Node3D" parent="."]
[node name="LeftWall" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(-1.03, 0.24, -0.15)
scale = Vector3(0.16, 1.82, 2.7)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("PaintedMaterial")
[node name="RightWall" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(1.03, 0.24, -0.15)
scale = Vector3(0.16, 1.82, 2.7)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("PaintedMaterial")
[node name="Ceiling" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(0, 1.22, -0.2)
scale = Vector3(2.15, 0.16, 2.6)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("SteelMaterial")
[node name="Floor" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(0, -0.7, -0.1)
scale = Vector3(2.05, 0.18, 2.5)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("RubberMaterial")
[node name="RearBulkhead" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(0, 0.22, 1.08)
scale = Vector3(2.08, 1.75, 0.16)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("SteelMaterial")
[node name="LeftRib" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(-0.88, 0.26, -0.45)
scale = Vector3(0.11, 1.75, 0.18)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("BrassMaterial")
[node name="RightRib" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(0.88, 0.26, -0.45)
scale = Vector3(0.11, 1.75, 0.18)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("BrassMaterial")
[node name="CeilingRib" type="MeshInstance3D" parent="CabinShell"]
position = Vector3(0, 1.05, -0.45)
scale = Vector3(1.82, 0.1, 0.18)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("BrassMaterial")
[node name="PortholeAssembly" type="Node3D" parent="."]
position = Vector3(0, 0.47, -1.32)
[node name="LeftBulkhead" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(-0.94, 0, 0)
scale = Vector3(0.6, 1.82, 0.2)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("SteelMaterial")
[node name="RightBulkhead" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0.94, 0, 0)
scale = Vector3(0.6, 1.82, 0.2)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("SteelMaterial")
[node name="TopBulkhead" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0, 0.91, 0)
scale = Vector3(1.55, 0.52, 0.2)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("SteelMaterial")
[node name="BottomBulkhead" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0, -0.91, 0)
scale = Vector3(1.55, 0.52, 0.2)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("SteelMaterial")
[node name="WindowFrame" type="MeshInstance3D" parent="PortholeAssembly"]
unique_name_in_owner = true
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("PortholeTorusMesh")
material_override = SubResource("BrassMaterial")
[node name="RubberSeal" type="MeshInstance3D" parent="PortholeAssembly"]
scale = Vector3(0.91, 0.91, 0.91)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("PortholeTorusMesh")
material_override = SubResource("RubberMaterial")
[node name="WindowGlass" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0, 0, -0.01)
rotation_degrees = Vector3(90, 0, 0)
cast_shadow = 0
mesh = SubResource("GlassCylinderMesh")
material_override = SubResource("GlassMaterial")
[node name="BoltTop" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0, 0.665, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltBottom" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0, -0.665, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltLeft" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(-0.665, 0, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltRight" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0.665, 0, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltUpperLeft" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(-0.47, 0.47, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltUpperRight" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0.47, 0.47, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltLowerLeft" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(-0.47, -0.47, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="BoltLowerRight" type="MeshInstance3D" parent="PortholeAssembly"]
position = Vector3(0.47, -0.47, 0.1)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("BoltMesh")
material_override = SubResource("SteelMaterial")
[node name="Dashboard" type="Node3D" parent="."]
unique_name_in_owner = true
position = Vector3(0, 0.05, -1.22)
rotation_degrees = Vector3(-12, 0, 0)
[node name="MainPanel" type="MeshInstance3D" parent="Dashboard"]
scale = Vector3(1.56, 0.44, 0.14)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("PaintedMaterial")
[node name="ResourcesFrame" type="MeshInstance3D" parent="Dashboard"]
position = Vector3(-0.5, 0.03, 0.088)
scale = Vector3(0.45, 0.31, 0.025)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("BrassMaterial")
[node name="ResourcesScreen" type="MeshInstance3D" parent="Dashboard"]
position = Vector3(-0.5, 0.03, 0.102)
scale = Vector3(0.41, 0.27, 1)
mesh = SubResource("ScreenQuadMesh")
material_override = SubResource("ScreenMaterial")
[node name="ResourcesLabel" type="Label3D" parent="Dashboard"]
unique_name_in_owner = true
position = Vector3(-0.5, 0.03, 0.108)
pixel_size = 0.00115
font_size = 20
outline_size = 2
text = "BATTERIE\n— / — kWh\n— kW\n\nOXYGÈNE\n— / — L\n— L/min"
modulate = Color(0.45, 0.89, 0.9, 1)
[node name="NavigationFrame" type="MeshInstance3D" parent="Dashboard"]
position = Vector3(0, 0.03, 0.088)
scale = Vector3(0.4, 0.31, 0.025)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("BrassMaterial")
[node name="NavigationScreen" type="MeshInstance3D" parent="Dashboard"]
position = Vector3(0, 0.03, 0.102)
scale = Vector3(0.36, 0.27, 1)
mesh = SubResource("ScreenQuadMesh")
material_override = SubResource("ScreenMaterial")
[node name="NavigationLabel" type="Label3D" parent="Dashboard"]
unique_name_in_owner = true
position = Vector3(0, 0.03, 0.108)
pixel_size = 0.00115
font_size = 20
outline_size = 2
text = "PROFONDEUR\n— m\nMAX. — m\n\nVITESSE\n— m/s"
modulate = Color(0.45, 0.89, 0.9, 1)
[node name="IntegrityFrame" type="MeshInstance3D" parent="Dashboard"]
position = Vector3(0.5, 0.03, 0.088)
scale = Vector3(0.45, 0.31, 0.025)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("BrassMaterial")
[node name="IntegrityScreen" type="MeshInstance3D" parent="Dashboard"]
position = Vector3(0.5, 0.03, 0.102)
scale = Vector3(0.41, 0.27, 1)
mesh = SubResource("ScreenQuadMesh")
material_override = SubResource("ScreenMaterial")
[node name="IntegrityLabel" type="Label3D" parent="Dashboard"]
unique_name_in_owner = true
position = Vector3(0.5, 0.03, 0.108)
pixel_size = 0.00115
font_size = 20
outline_size = 2
text = "COQUE\n— / —\n\nPRESSION\n— / — bar"
modulate = Color(0.45, 0.89, 0.9, 1)
[node name="ReturnLabel" type="Label3D" parent="Dashboard"]
unique_name_in_owner = true
position = Vector3(0.32, 0.205, 0.108)
pixel_size = 0.00082
font_size = 15
outline_size = 2
text = "RETOUR · INCONNU"
modulate = Color(1, 0.75, 0.2, 1)
[node name="StatusLabel" type="Label3D" parent="Dashboard"]
unique_name_in_owner = true
position = Vector3(-0.34, 0.205, 0.108)
pixel_size = 0.00082
font_size = 15
outline_size = 2
text = "SYSTÈMES · NORMAL"
modulate = Color(0.45, 0.89, 0.9, 1)
[node name="LeftConsole" type="MeshInstance3D" parent="."]
position = Vector3(-0.82, -0.23, -1.19)
rotation_degrees = Vector3(-8, 18, 4)
scale = Vector3(0.32, 0.16, 0.56)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("PaintedMaterial")
[node name="RightConsole" type="MeshInstance3D" parent="."]
position = Vector3(0.82, -0.23, -1.19)
rotation_degrees = Vector3(-8, -18, -4)
scale = Vector3(0.32, 0.16, 0.56)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("PaintedMaterial")
[node name="ThrottleLever" type="MeshInstance3D" parent="."]
position = Vector3(-0.79, -0.06, -1.13)
rotation_degrees = Vector3(18, 0, -10)
scale = Vector3(0.72, 0.72, 0.72)
mesh = SubResource("LeverMesh")
material_override = SubResource("SteelMaterial")
[node name="ThrottleKnob" type="MeshInstance3D" parent="."]
position = Vector3(-0.81, 0.025, -1.1)
scale = Vector3(0.72, 0.72, 0.72)
mesh = SubResource("KnobMesh")
material_override = SubResource("BrassMaterial")
[node name="VerticalLever" type="MeshInstance3D" parent="."]
position = Vector3(0.79, -0.06, -1.13)
rotation_degrees = Vector3(18, 0, 10)
scale = Vector3(0.72, 0.72, 0.72)
mesh = SubResource("LeverMesh")
material_override = SubResource("SteelMaterial")
[node name="VerticalKnob" type="MeshInstance3D" parent="."]
position = Vector3(0.81, 0.025, -1.1)
scale = Vector3(0.72, 0.72, 0.72)
mesh = SubResource("KnobMesh")
material_override = SubResource("BrassMaterial")
[node name="SonarMonitor" type="Node3D" parent="."]
position = Vector3(0.72, 0.4, -1.24)
rotation_degrees = Vector3(-5, -22, -2)
[node name="Housing" type="MeshInstance3D" parent="SonarMonitor"]
scale = Vector3(0.32, 0.24, 0.08)
mesh = SubResource("UnitBoxMesh")
material_override = SubResource("RubberMaterial")
[node name="SonarScreen" type="MeshInstance3D" parent="SonarMonitor"]
unique_name_in_owner = true
position = Vector3(0, 0.025, 0.06)
scale = Vector3(0.265, 0.165, 1)
mesh = SubResource("ScreenQuadMesh")
material_override = SubResource("ScreenMaterial")
[node name="SonarPlaceholder" type="Label3D" parent="SonarMonitor"]
position = Vector3(0, 0.025, 0.068)
pixel_size = 0.0009
font_size = 16
outline_size = 2
text = "SONAR\nMODULE EN ATTENTE"
modulate = Color(0.34, 0.6, 0.6, 1)
[node name="EmergencyDial" type="MeshInstance3D" parent="."]
position = Vector3(-0.6, 0.39, -1.15)
scale = Vector3(0.38, 0.38, 0.38)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("DialMesh")
material_override = SubResource("RedMaterial")
[node name="EmergencyLabel" type="Label3D" parent="."]
position = Vector3(-0.6, 0.3, -1.125)
pixel_size = 0.0009
font_size = 15
outline_size = 2
text = "ÉJECTION · X"
modulate = Color(1, 0.48, 0.38, 1)
[node name="CyanIndicator" type="MeshInstance3D" parent="."]
position = Vector3(-0.15, 0.305, -1.11)
scale = Vector3(0.25, 0.25, 0.25)
mesh = SubResource("KnobMesh")
material_override = SubResource("CyanMaterial")
[node name="AmberIndicator" type="MeshInstance3D" parent="."]
position = Vector3(0, 0.305, -1.11)
scale = Vector3(0.25, 0.25, 0.25)
mesh = SubResource("KnobMesh")
material_override = SubResource("AmberMaterial")
[node name="RedIndicator" type="MeshInstance3D" parent="."]
position = Vector3(0.15, 0.305, -1.11)
scale = Vector3(0.25, 0.25, 0.25)
mesh = SubResource("KnobMesh")
material_override = SubResource("RedMaterial")
[node name="CabinLight" type="OmniLight3D" parent="."]
position = Vector3(0, 0.92, -0.28)
light_color = Color(0.42, 0.75, 0.74, 1)
light_energy = 2.2
shadow_enabled = true
omni_range = 3.3
[node name="PanelLight" type="OmniLight3D" parent="."]
position = Vector3(0, 0.18, -0.63)
light_color = Color(0.23, 0.72, 0.76, 1)
light_energy = 0.8
shadow_enabled = false
omni_range = 1.35