Render bathymetric sonar surface
This commit is contained in:
1 parent
fdebbafeae
commit
b6f6b53a70
7 files changed
+305
-135
No files matched your search
@@ -19,7 +19,7 @@ const ProductionInputAdapter = preload(
|
||||
"res://game/infrastructure/input/production_input_adapter.gd"
|
||||
)
|
||||
|
||||
const TEST_COUNT := 69
|
||||
const TEST_COUNT := 78
|
||||
|
||||
var _failures: Array[String] = []
|
||||
|
||||
@@ -125,6 +125,28 @@ func _test_vehicle_slice(composition: VerticalSliceRoot) -> void:
|
||||
_expect(instruments.get_node("%WindowFrame") is MeshInstance3D, "cockpit has a physical porthole frame")
|
||||
_expect(instruments.get_node("%Dashboard") is Node3D, "cockpit has a physical dashboard")
|
||||
_expect(instruments.get_node("%SonarScreen") is MeshInstance3D, "cockpit reserves a physical sonar display")
|
||||
var sonar_monitor := instruments.get_node("SonarMonitor") as Node3D
|
||||
var sonar_screen := instruments.get_node("%SonarScreen") as MeshInstance3D
|
||||
var sonar_housing := instruments.get_node("SonarMonitor/Housing") as MeshInstance3D
|
||||
var cockpit_camera := camera.get_node("Camera") as Camera3D
|
||||
var electrical_bank := detailing.get_node("SideEquipment/ElectricalBank") as Node3D
|
||||
_expect(sonar_monitor.position.x > 0.5, "cockpit sonar is mounted on the right side")
|
||||
_expect(
|
||||
_sonar_screen_faces_camera(sonar_screen, cockpit_camera),
|
||||
"right-side sonar display faces the pilot"
|
||||
)
|
||||
_expect(
|
||||
_sonar_screen_is_ahead_of_bank(sonar_screen, electrical_bank),
|
||||
"right-side electrical equipment does not hide the sonar display"
|
||||
)
|
||||
_expect(
|
||||
_sonar_screen_clears_housing(sonar_screen, sonar_housing),
|
||||
"sonar texture clears its housing without depth overlap"
|
||||
)
|
||||
_expect(
|
||||
instruments.find_children("SonarReferenceTrace", "MeshInstance3D", true).is_empty(),
|
||||
"cockpit sonar does not invent a decorative profile"
|
||||
)
|
||||
_expect(detailing.pressure_hull_rib_count() >= 6, "cockpit exposes reinforced pressure-hull structure")
|
||||
_expect(detailing.pipe_segment_count() >= 13, "cockpit exposes a complete life-support pipe run")
|
||||
_expect(absf(detailing.battery_needle_degrees()) > 100.0, "analog battery gauge follows the dive snapshot")
|
||||
@@ -148,6 +170,7 @@ func _test_vehicle_slice(composition: VerticalSliceRoot) -> void:
|
||||
instruments.sonar_texture() == sonar_display.sonar_texture(),
|
||||
"physical and expanded sonar views share one texture"
|
||||
)
|
||||
_expect(sonar_display.idle_prompt_visible(), "idle sonar explains how to emit a scan")
|
||||
|
||||
adapter.sonar_scan_requested.emit()
|
||||
var first_scan = sonar_service.current_scan()
|
||||
@@ -155,9 +178,12 @@ func _test_vehicle_slice(composition: VerticalSliceRoot) -> void:
|
||||
_expect(first_scan.samples.observed_count() > 1000, "reference acquisition captures dense bathymetry")
|
||||
_expect(first_scan.contacts.size() >= 1, "metal calibration target becomes a distinct contact")
|
||||
_expect("RELEVÉ EN COURS" in sonar_display.status_text(), "sonar display reports progressive reveal")
|
||||
for frame in 8:
|
||||
_expect(not sonar_display.idle_prompt_visible(), "sonar data replaces the idle instruction")
|
||||
for frame in 18:
|
||||
await physics_frame
|
||||
_expect(sonar_display.built_row_count() > 0, "renderer reveals near rows incrementally")
|
||||
_expect(sonar_display.built_triangle_count() >= 90, "sonar renders a dense relief surface, not a line")
|
||||
_expect(sonar_display.built_grid_segment_count() > 0, "sonar overlays a perspective grid on the relief")
|
||||
adapter.sonar_view_toggle_requested.emit()
|
||||
_expect(sonar_display.is_expanded(), "sonar can expand without pausing the dive")
|
||||
adapter.sonar_view_toggle_requested.emit()
|
||||
@@ -276,6 +302,47 @@ func _pressed_key(keycode: Key) -> InputEventKey:
|
||||
return event
|
||||
|
||||
|
||||
func _sonar_screen_faces_camera(
|
||||
sonar_screen: MeshInstance3D,
|
||||
cockpit_camera: Camera3D
|
||||
) -> bool:
|
||||
if sonar_screen == null or cockpit_camera == null:
|
||||
return false
|
||||
var direction_to_camera := (
|
||||
cockpit_camera.global_position - sonar_screen.global_position
|
||||
).normalized()
|
||||
return sonar_screen.global_basis.z.normalized().dot(direction_to_camera) > 0.85
|
||||
|
||||
|
||||
func _sonar_screen_is_ahead_of_bank(
|
||||
sonar_screen: MeshInstance3D,
|
||||
electrical_bank: Node3D
|
||||
) -> bool:
|
||||
if sonar_screen == null or electrical_bank == null:
|
||||
return false
|
||||
for child: Node in electrical_bank.get_children():
|
||||
if child is MeshInstance3D and child.name.begins_with("JunctionBox"):
|
||||
if sonar_screen.global_position.z <= (child as MeshInstance3D).global_position.z:
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func _sonar_screen_clears_housing(
|
||||
sonar_screen: MeshInstance3D,
|
||||
sonar_housing: MeshInstance3D
|
||||
) -> bool:
|
||||
if sonar_screen == null or sonar_housing == null:
|
||||
return false
|
||||
var housing_box := sonar_housing.mesh as BoxMesh
|
||||
if housing_box == null:
|
||||
return false
|
||||
var housing_front_z := (
|
||||
sonar_housing.position.z
|
||||
+ housing_box.size.z * sonar_housing.scale.z * 0.5
|
||||
)
|
||||
return sonar_screen.position.z >= housing_front_z + 0.005
|
||||
|
||||
|
||||
func _binding_for(adapter: ProductionInputAdapter, action_id: StringName) -> String:
|
||||
for binding in adapter.binding_snapshots():
|
||||
if binding.action_id == action_id:
|
||||
|
||||
Reference in new issue
Block a user