351 lines
9.1 KiB
GDScript
351 lines
9.1 KiB
GDScript
class_name CockpitDetailing
|
|
extends Node3D
|
|
|
|
const DiveUpdate = preload("res://game/domain/dive/dive_update.gd")
|
|
const DiveAlertLevel = preload("res://game/domain/dive/dive_alert_level.gd")
|
|
const VehicleTelemetry = preload("res://game/application/dive/vehicle_telemetry.gd")
|
|
const CockpitAnalogGauges = preload("res://game/presentation/cockpit/cockpit_analog_gauges.gd")
|
|
const CockpitDashboardDetailing = preload(
|
|
"res://game/presentation/cockpit/cockpit_dashboard_detailing.gd"
|
|
)
|
|
const CockpitMaterialPalette = preload("res://game/presentation/cockpit/cockpit_material_palette.gd")
|
|
const CockpitMeshFactory = preload("res://game/presentation/cockpit/cockpit_mesh_factory.gd")
|
|
|
|
var _materials: CockpitMaterialPalette
|
|
var _painted_steel: Material
|
|
var _dark_steel: Material
|
|
var _overhead_steel: Material
|
|
var _brass: Material
|
|
var _copper: Material
|
|
var _analog_gauges: CockpitAnalogGauges
|
|
var _dashboard_detailing: CockpitDashboardDetailing
|
|
var _warm_practical: OmniLight3D
|
|
var _emergency_light: OmniLight3D
|
|
|
|
|
|
func _ready() -> void:
|
|
_create_materials()
|
|
_apply_materials_to_existing_cockpit()
|
|
_build_pressure_hull_ribs()
|
|
_build_life_support_pipes()
|
|
_build_overhead_console()
|
|
_build_panel_hardware()
|
|
_build_dashboard_instrumentation()
|
|
_build_practical_lights()
|
|
|
|
|
|
func present(update: DiveUpdate, telemetry: VehicleTelemetry) -> void:
|
|
if update == null or update.snapshot == null or telemetry == null:
|
|
return
|
|
var snapshot = update.snapshot
|
|
_analog_gauges.present(
|
|
snapshot.battery.ratio,
|
|
clampf(
|
|
snapshot.hull.exterior_pressure_bar
|
|
/ maxf(snapshot.hull.certified_pressure_bar, 0.001),
|
|
0.0,
|
|
1.0
|
|
),
|
|
snapshot.alerts.maximum
|
|
)
|
|
var alert_level: DiveAlertLevel.Value = snapshot.alerts.maximum
|
|
_emergency_light.visible = alert_level >= DiveAlertLevel.Value.CRITICAL
|
|
_warm_practical.light_energy = (
|
|
0.28 if alert_level >= DiveAlertLevel.Value.CRITICAL else 0.72
|
|
)
|
|
|
|
|
|
func pressure_hull_rib_count() -> int:
|
|
var ribs := get_node_or_null("PressureHullRibs")
|
|
return 0 if ribs == null else ribs.get_child_count()
|
|
|
|
|
|
func pipe_segment_count() -> int:
|
|
var pipes := get_node_or_null("LifeSupportPipes")
|
|
return 0 if pipes == null else pipes.get_child_count()
|
|
|
|
|
|
func battery_needle_degrees() -> float:
|
|
return 0.0 if _analog_gauges == null else _analog_gauges.battery_needle_degrees()
|
|
|
|
|
|
func textures_are_loaded() -> bool:
|
|
return (
|
|
_materials != null
|
|
and _materials.overhead_steel.albedo_texture != null
|
|
and _materials.gauge_face.albedo_texture != null
|
|
)
|
|
|
|
|
|
func dashboard_control_count() -> int:
|
|
return 0 if _dashboard_detailing == null else _dashboard_detailing.control_count()
|
|
|
|
|
|
func gauges_are_dashboard_mounted() -> bool:
|
|
return _analog_gauges != null and _analog_gauges.get_parent() == get_parent().get_node("Dashboard")
|
|
|
|
|
|
func _create_materials() -> void:
|
|
_materials = CockpitMaterialPalette.new()
|
|
_painted_steel = _materials.painted_steel
|
|
_dark_steel = _materials.dark_steel
|
|
_overhead_steel = _materials.overhead_steel
|
|
_brass = _materials.brass
|
|
_copper = _materials.copper
|
|
|
|
|
|
func _apply_materials_to_existing_cockpit() -> void:
|
|
_apply_material_to_paths(
|
|
_painted_steel,
|
|
[
|
|
"CabinShell/LeftWall",
|
|
"CabinShell/RightWall",
|
|
"LeftConsole",
|
|
"RightConsole",
|
|
]
|
|
)
|
|
_apply_material_to_paths(
|
|
_dark_steel,
|
|
[
|
|
"CabinShell/RearBulkhead",
|
|
"PortholeAssembly/LeftBulkhead",
|
|
"PortholeAssembly/RightBulkhead",
|
|
"PortholeAssembly/BottomBulkhead",
|
|
"ThrottleLever",
|
|
"VerticalLever",
|
|
]
|
|
)
|
|
_apply_material_to_paths(
|
|
_overhead_steel,
|
|
[
|
|
"CabinShell/Ceiling",
|
|
"PortholeAssembly/TopBulkhead",
|
|
"Dashboard/MainPanel",
|
|
]
|
|
)
|
|
_apply_material_to_paths(
|
|
_brass,
|
|
[
|
|
"PortholeAssembly/WindowFrame",
|
|
"Dashboard/ResourcesFrame",
|
|
"Dashboard/NavigationFrame",
|
|
"Dashboard/IntegrityFrame",
|
|
"ThrottleKnob",
|
|
"VerticalKnob",
|
|
]
|
|
)
|
|
func _apply_material_to_paths(material: Material, paths: Array[String]) -> void:
|
|
var cockpit := get_parent()
|
|
for path: String in paths:
|
|
var mesh := cockpit.get_node_or_null(path) as MeshInstance3D
|
|
if mesh != null:
|
|
mesh.material_override = material
|
|
|
|
|
|
func _build_pressure_hull_ribs() -> void:
|
|
var root := Node3D.new()
|
|
root.name = "PressureHullRibs"
|
|
add_child(root)
|
|
for rib_index in 2:
|
|
var rib := MeshInstance3D.new()
|
|
rib.name = "CircularRib%d" % (rib_index + 1)
|
|
var torus := TorusMesh.new()
|
|
torus.inner_radius = 1.00
|
|
torus.outer_radius = 1.075
|
|
torus.rings = 48
|
|
torus.ring_segments = 10
|
|
rib.mesh = torus
|
|
rib.material_override = _dark_steel
|
|
rib.position = Vector3(0.0, 0.22, -0.90 + rib_index * 1.35)
|
|
rib.rotation_degrees.x = 90.0
|
|
root.add_child(rib)
|
|
|
|
for side: float in [-1.0, 1.0]:
|
|
CockpitMeshFactory.add_box(
|
|
"AngledShoulder",
|
|
root,
|
|
Vector3(side * 0.88, 0.84, -0.36),
|
|
Vector3(0.11, 0.62, 1.52),
|
|
_painted_steel,
|
|
Vector3(0.0, 0.0, side * -18.0)
|
|
)
|
|
CockpitMeshFactory.add_box(
|
|
"LowerStringer",
|
|
root,
|
|
Vector3(side * 0.91, -0.38, -0.18),
|
|
Vector3(0.10, 0.12, 1.70),
|
|
_dark_steel
|
|
)
|
|
|
|
|
|
func _build_life_support_pipes() -> void:
|
|
var root := Node3D.new()
|
|
root.name = "LifeSupportPipes"
|
|
add_child(root)
|
|
for side: float in [-1.0, 1.0]:
|
|
var x: float = side * 0.83
|
|
CockpitMeshFactory.add_cylinder(
|
|
"VerticalPipe",
|
|
root,
|
|
Vector3(x, 0.33, -1.12),
|
|
0.027,
|
|
1.18,
|
|
_copper
|
|
)
|
|
CockpitMeshFactory.add_cylinder(
|
|
"ReturnPipe",
|
|
root,
|
|
Vector3(side * 0.73, 0.47, -1.09),
|
|
0.019,
|
|
0.92,
|
|
_brass
|
|
)
|
|
for clamp_y: float in [-0.04, 0.35, 0.72]:
|
|
var clamp := MeshInstance3D.new()
|
|
clamp.name = "PipeClamp"
|
|
var torus := TorusMesh.new()
|
|
torus.inner_radius = 0.027
|
|
torus.outer_radius = 0.041
|
|
torus.rings = 16
|
|
torus.ring_segments = 6
|
|
clamp.mesh = torus
|
|
clamp.material_override = _dark_steel
|
|
clamp.position = Vector3(x, clamp_y, -1.12)
|
|
root.add_child(clamp)
|
|
CockpitMeshFactory.add_sphere(
|
|
"PipeJunction",
|
|
root,
|
|
Vector3(x, 0.91, -1.12),
|
|
0.052,
|
|
_copper
|
|
)
|
|
|
|
CockpitMeshFactory.add_cylinder(
|
|
"OverheadCrossPipe",
|
|
root,
|
|
Vector3(0.0, 0.93, -1.12),
|
|
0.031,
|
|
1.82,
|
|
_copper,
|
|
Vector3(0.0, 0.0, 90.0)
|
|
)
|
|
|
|
|
|
func _build_overhead_console() -> void:
|
|
var root := Node3D.new()
|
|
root.name = "OverheadConsole"
|
|
add_child(root)
|
|
CockpitMeshFactory.add_box(
|
|
"BreakerHousing",
|
|
root,
|
|
Vector3(0.0, 0.94, -1.06),
|
|
Vector3(0.30, 0.09, 0.12),
|
|
_overhead_steel,
|
|
Vector3(-8.0, 0.0, 0.0)
|
|
)
|
|
CockpitMeshFactory.add_box(
|
|
"WarmLightDiffuser",
|
|
root,
|
|
Vector3(0.0, 0.895, -0.985),
|
|
Vector3(0.13, 0.010, 0.026),
|
|
_materials.warm_emission,
|
|
Vector3(-8.0, 0.0, 0.0)
|
|
)
|
|
for guard_index in 5:
|
|
var guard_x := -0.05 + guard_index * 0.025
|
|
CockpitMeshFactory.add_box(
|
|
"LampGuard",
|
|
root,
|
|
Vector3(guard_x, 0.896, -0.968),
|
|
Vector3(0.005, 0.045, 0.008),
|
|
_dark_steel,
|
|
Vector3(-8.0, 0.0, 0.0)
|
|
)
|
|
for switch_index in 5:
|
|
var x := -0.10 + switch_index * 0.05
|
|
CockpitMeshFactory.add_cylinder(
|
|
"BreakerSwitch",
|
|
root,
|
|
Vector3(x, 0.965, -0.985),
|
|
0.004,
|
|
0.018,
|
|
_materials.rubber,
|
|
Vector3(90.0, 0.0, 0.0)
|
|
)
|
|
|
|
|
|
func _build_panel_hardware() -> void:
|
|
var root := Node3D.new()
|
|
root.name = "PanelHardware"
|
|
add_child(root)
|
|
for x: float in [-0.73, -0.49, -0.24, 0.24, 0.49, 0.73]:
|
|
for y: float in [-0.18, 0.22]:
|
|
CockpitMeshFactory.add_cylinder(
|
|
"PanelFastener",
|
|
root,
|
|
Vector3(x, y, -1.105),
|
|
0.014,
|
|
0.018,
|
|
_dark_steel,
|
|
Vector3(90.0, 0.0, 0.0)
|
|
)
|
|
|
|
for side: float in [-1.0, 1.0]:
|
|
CockpitMeshFactory.add_box(
|
|
"ServiceBox",
|
|
root,
|
|
Vector3(side * 0.89, 0.08, -1.10),
|
|
Vector3(0.18, 0.34, 0.19),
|
|
_painted_steel,
|
|
Vector3(0.0, side * -12.0, 0.0)
|
|
)
|
|
var label := Label3D.new()
|
|
label.name = "ServicePlate"
|
|
label.text = "O₂" if side < 0.0 else "ELEC"
|
|
label.font_size = 16
|
|
label.pixel_size = 0.0009
|
|
label.modulate = Color(0.72, 0.69, 0.56)
|
|
label.position = Vector3(side * 0.89, 0.10, -0.99)
|
|
root.add_child(label)
|
|
|
|
|
|
func _build_dashboard_instrumentation() -> void:
|
|
var dashboard := get_parent().get_node_or_null("Dashboard") as Node3D
|
|
if dashboard == null:
|
|
return
|
|
_dashboard_detailing = CockpitDashboardDetailing.new(_materials)
|
|
dashboard.add_child(_dashboard_detailing)
|
|
_dashboard_detailing.apply_screen_materials(dashboard)
|
|
_dashboard_detailing.hide_placeholder_indicators(get_parent())
|
|
_analog_gauges = CockpitAnalogGauges.new(_materials)
|
|
dashboard.add_child(_analog_gauges)
|
|
|
|
|
|
func _build_practical_lights() -> void:
|
|
_warm_practical = OmniLight3D.new()
|
|
_warm_practical.name = "WarmPracticalLight"
|
|
_warm_practical.position = Vector3(0.0, 0.82, -0.50)
|
|
_warm_practical.light_color = Color(1.0, 0.52, 0.22)
|
|
_warm_practical.light_energy = 0.58
|
|
_warm_practical.omni_range = 2.2
|
|
_warm_practical.shadow_enabled = false
|
|
add_child(_warm_practical)
|
|
|
|
var cool_fill := OmniLight3D.new()
|
|
cool_fill.name = "CoolRearFill"
|
|
cool_fill.position = Vector3(0.0, 0.42, 0.35)
|
|
cool_fill.light_color = Color(0.24, 0.46, 0.47)
|
|
cool_fill.light_energy = 0.48
|
|
cool_fill.omni_range = 3.0
|
|
cool_fill.shadow_enabled = false
|
|
add_child(cool_fill)
|
|
|
|
_emergency_light = OmniLight3D.new()
|
|
_emergency_light.name = "EmergencyLight"
|
|
_emergency_light.position = Vector3(-0.58, 0.44, -0.83)
|
|
_emergency_light.light_color = Color(1.0, 0.04, 0.015)
|
|
_emergency_light.light_energy = 1.4
|
|
_emergency_light.omni_range = 2.4
|
|
_emergency_light.visible = false
|
|
add_child(_emergency_light)
|