class_name CockpitPressureBulkhead extends Node3D const CockpitMaterialPalette = preload( "res://game/presentation/cockpit/cockpit_material_palette.gd" ) const CockpitMeshFactory = preload( "res://game/presentation/cockpit/cockpit_mesh_factory.gd" ) const PANEL_COUNT := 1 const FASTENER_COUNT := 16 const ANGULAR_STEPS := 64 const RADIAL_STEPS := 4 const INNER_RADIUS := 0.72 const OUTER_RADIUS := 1.11 var _materials: CockpitMaterialPalette var _panel_count := 0 func _ready() -> void: _materials = CockpitMaterialPalette.new() _hide_rectangular_whitebox() _style_existing_frame() _build_curved_panels() _build_outer_rib() _build_fasteners() func panel_count() -> int: return _panel_count func rectangular_whitebox_is_hidden() -> bool: for node_name: String in ["LeftBulkhead", "RightBulkhead", "TopBulkhead", "BottomBulkhead"]: var whitebox := get_parent().get_node_or_null(node_name) as MeshInstance3D if whitebox != null and whitebox.visible: return false return true func _hide_rectangular_whitebox() -> void: for node_name: String in ["LeftBulkhead", "RightBulkhead", "TopBulkhead", "BottomBulkhead"]: var whitebox := get_parent().get_node_or_null(node_name) as MeshInstance3D if whitebox != null: whitebox.visible = false func _style_existing_frame() -> void: var frame := get_parent().get_node_or_null("WindowFrame") as MeshInstance3D if frame != null: frame.material_override = _materials.brushed_steel for child: Node in get_parent().get_children(): if child is MeshInstance3D and child.name.begins_with("Bolt"): (child as MeshInstance3D).material_override = _materials.dark_steel func _build_curved_panels() -> void: var panel_angle := TAU / float(PANEL_COUNT) for panel_index in PANEL_COUNT: var start_angle := panel_index * panel_angle var end_angle := (panel_index + 1) * panel_angle var panel := MeshInstance3D.new() panel.name = "PressurePanel%02d" % (panel_index + 1) panel.mesh = _create_curved_panel_mesh(start_angle, end_angle) panel.material_override = _materials.overhead_steel panel.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_ON add_child(panel) _panel_count += 1 func _create_curved_panel_mesh(start_angle: float, end_angle: float) -> ArrayMesh: var surface := SurfaceTool.new() surface.begin(Mesh.PRIMITIVE_TRIANGLES) for angular_index in ANGULAR_STEPS: var angle_ratio_0 := float(angular_index) / float(ANGULAR_STEPS) var angle_ratio_1 := float(angular_index + 1) / float(ANGULAR_STEPS) var angle_0 := lerpf(start_angle, end_angle, angle_ratio_0) var angle_1 := lerpf(start_angle, end_angle, angle_ratio_1) for radial_index in RADIAL_STEPS: var radial_ratio_0 := float(radial_index) / float(RADIAL_STEPS) var radial_ratio_1 := float(radial_index + 1) / float(RADIAL_STEPS) _add_panel_quad( surface, angle_0, angle_1, angle_ratio_0, angle_ratio_1, radial_ratio_0, radial_ratio_1 ) surface.generate_normals() return surface.commit() func _add_panel_quad( surface: SurfaceTool, angle_0: float, angle_1: float, angle_ratio_0: float, angle_ratio_1: float, radial_ratio_0: float, radial_ratio_1: float ) -> void: _add_panel_vertex(surface, angle_0, angle_ratio_0, radial_ratio_0) _add_panel_vertex(surface, angle_1, angle_ratio_1, radial_ratio_0) _add_panel_vertex(surface, angle_0, angle_ratio_0, radial_ratio_1) _add_panel_vertex(surface, angle_0, angle_ratio_0, radial_ratio_1) _add_panel_vertex(surface, angle_1, angle_ratio_1, radial_ratio_0) _add_panel_vertex(surface, angle_1, angle_ratio_1, radial_ratio_1) func _add_panel_vertex( surface: SurfaceTool, angle: float, angle_ratio: float, radial_ratio: float ) -> void: var radius := lerpf(INNER_RADIUS, OUTER_RADIUS, radial_ratio) var convex_depth := sin(radial_ratio * PI) * 0.075 surface.set_uv(Vector2(angle_ratio, radial_ratio)) surface.add_vertex( Vector3(cos(angle) * radius, sin(angle) * radius, 0.045 + convex_depth) ) func _build_outer_rib() -> void: var rib := MeshInstance3D.new() rib.name = "OuterPressureRib" var torus := TorusMesh.new() torus.inner_radius = 1.055 torus.outer_radius = 1.125 torus.rings = 64 torus.ring_segments = 12 rib.mesh = torus rib.material_override = _materials.dark_steel rib.rotation_degrees.x = 90.0 rib.position.z = 0.025 add_child(rib) var inner_rib := MeshInstance3D.new() inner_rib.name = "InnerPressureRib" var inner_torus := TorusMesh.new() inner_torus.inner_radius = 0.695 inner_torus.outer_radius = 0.755 inner_torus.rings = 64 inner_torus.ring_segments = 12 inner_rib.mesh = inner_torus inner_rib.material_override = _materials.brushed_steel inner_rib.rotation_degrees.x = 90.0 inner_rib.position.z = 0.075 add_child(inner_rib) func _build_fasteners() -> void: for fastener_index in FASTENER_COUNT: var angle := (fastener_index + 0.5) * TAU / float(FASTENER_COUNT) CockpitMeshFactory.add_cylinder( "OuterFastener", self, Vector3(cos(angle) * 0.96, sin(angle) * 0.96, 0.105), 0.014, 0.018, _materials.brass, Vector3(90.0, 0.0, 0.0) )