Map in helm station
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=14 format=3 uid="uid://didt2nsdtbmra"]
|
||||
[gd_scene load_steps=17 format=3 uid="uid://didt2nsdtbmra"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://6co67nfy8ngb" path="res://scenes/ship/builder/module.gd" id="1_nqe0s"]
|
||||
[ext_resource type="PackedScene" uid="uid://bho8x10x4oab7" path="res://scenes/ship/builder/pieces/hullplate.tscn" id="2_foqop"]
|
||||
@ -10,9 +10,12 @@
|
||||
[ext_resource type="Resource" uid="uid://c4wyouanvf86c" path="res://scenes/ship/computer/panels/button_panel.tres" id="7_vmx8o"]
|
||||
[ext_resource type="Resource" uid="uid://57y6igb07e10" path="res://scenes/ship/computer/panels/readout_screen.tres" id="8_83bu1"]
|
||||
[ext_resource type="Resource" uid="uid://dcyr6utrk376h" path="res://scenes/ship/computer/panels/throttle_lever.tres" id="9_ixntg"]
|
||||
[ext_resource type="Resource" uid="uid://dl7g67mtqkfx2" path="res://scenes/ship/computer/panels/sensor_panel.tres" id="9_xwy4s"]
|
||||
[ext_resource type="Resource" uid="uid://bx7wgunvy5hfa" path="res://scenes/ship/computer/shards/helm_ship_status.tres" id="11_83bu1"]
|
||||
[ext_resource type="PackedScene" uid="uid://c0bb77rmyatr0" path="res://scenes/ship/components/hardware/thruster.tscn" id="12_vmx8o"]
|
||||
[ext_resource type="Resource" uid="uid://g4ho63f30vjm" path="res://scenes/ship/computer/shards/nav_selection_databank.tres" id="12_wkxbw"]
|
||||
[ext_resource type="PackedScene" uid="uid://dvpy3urgtm62n" path="res://scenes/ship/components/hardware/spawner.tscn" id="13_83bu1"]
|
||||
[ext_resource type="Resource" uid="uid://b0suy3sxjwhtv" path="res://scenes/ship/computer/shards/sensor_databank.tres" id="13_xwy4s"]
|
||||
|
||||
[node name="Module" type="Node2D"]
|
||||
script = ExtResource("1_nqe0s")
|
||||
@ -95,8 +98,8 @@ mass = 1.0
|
||||
|
||||
[node name="Station" parent="." instance=ExtResource("5_nqe0s")]
|
||||
position = Vector2(0, -10)
|
||||
panels = Array[ExtResource("6_oqcn4")]([ExtResource("7_vmx8o"), ExtResource("8_83bu1"), ExtResource("9_ixntg")])
|
||||
installed_databanks = Array[ExtResource("6_ft4kn")]([ExtResource("7_dmrms"), ExtResource("11_83bu1")])
|
||||
panels = Array[ExtResource("6_oqcn4")]([ExtResource("7_vmx8o"), ExtResource("8_83bu1"), ExtResource("9_ixntg"), ExtResource("9_xwy4s")])
|
||||
installed_databanks = Array[ExtResource("6_ft4kn")]([ExtResource("7_dmrms"), ExtResource("11_83bu1"), ExtResource("12_wkxbw"), ExtResource("13_xwy4s"), null])
|
||||
|
||||
[node name="Thruster" parent="." instance=ExtResource("12_vmx8o")]
|
||||
position = Vector2(-95, -130)
|
||||
@ -120,6 +123,7 @@ main_thruster = false
|
||||
|
||||
[node name="MainEngine" parent="." instance=ExtResource("12_vmx8o")]
|
||||
position = Vector2(0, 195)
|
||||
max_thrust = 10.0
|
||||
|
||||
[node name="Spawner" parent="." instance=ExtResource("13_83bu1")]
|
||||
position = Vector2(0, 27)
|
||||
|
||||
@ -112,6 +112,8 @@ func _connect_internals(panel_instances: Array, shard_instances: Array):
|
||||
var lever_panel
|
||||
var button_panel
|
||||
var readout_screen
|
||||
var map_panel
|
||||
var sensor_shard: SensorSystemShard
|
||||
var helm_shard: HelmLogicShard
|
||||
var status_shard: ShipStatusShard
|
||||
|
||||
@ -123,15 +125,20 @@ func _connect_internals(panel_instances: Array, shard_instances: Array):
|
||||
if panel is ReadoutScreenUI:
|
||||
print("Panel is ReadoutScreen: %s" % panel)
|
||||
readout_screen = panel
|
||||
if panel is SensorPanel: # Look for the new map panel class
|
||||
map_panel = panel
|
||||
|
||||
for shard in shard_instances:
|
||||
print(shard)
|
||||
if shard is HelmLogicShard:
|
||||
helm_shard = shard
|
||||
|
||||
if shard is ShipStatusShard:
|
||||
print("Shard is Ship Status Shard: %s" % shard)
|
||||
|
||||
status_shard = shard
|
||||
|
||||
if shard is SensorSystemShard: # Look for the new sensor shard class
|
||||
sensor_shard = shard
|
||||
|
||||
|
||||
if lever_panel and helm_shard:
|
||||
lever_panel.lever_value_changed.connect(helm_shard.set_throttle_input)
|
||||
@ -149,3 +156,9 @@ func _connect_internals(panel_instances: Array, shard_instances: Array):
|
||||
print("Wired: Status Shard -> Readout Screen")
|
||||
|
||||
status_shard.connect("status_updated", readout_screen.update_display)
|
||||
|
||||
if map_panel and sensor_shard:
|
||||
# Connect the shard's "sensor_feed_updated" signal (blue wire)
|
||||
# to the map's "update_sensor_feed" socket.
|
||||
sensor_shard.connect("sensor_feed_updated", map_panel.update_sensor_feed)
|
||||
print("Wired: Sensor Shard -> Map Panel (Sensor Feed)")
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
extends PanelContainer
|
||||
extends BoxContainer
|
||||
|
||||
## This UI provides one "socket": a function to update its text.
|
||||
class_name ReadoutScreenUI
|
||||
@ -10,4 +10,3 @@ class_name ReadoutScreenUI
|
||||
func update_display(text: String):
|
||||
if display:
|
||||
display.text = text
|
||||
self.reset_size()
|
||||
|
||||
@ -2,16 +2,17 @@
|
||||
|
||||
[ext_resource type="Script" uid="uid://laeom8fvlfkf" path="res://scenes/ship/computer/UI/readout_screen_panel.gd" id="1_w2pab"]
|
||||
|
||||
[node name="DisplayText" type="PanelContainer"]
|
||||
[node name="DisplayText" type="VBoxContainer"]
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_right = 1.0
|
||||
offset_right = 553.0
|
||||
grow_vertical = 0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1_w2pab")
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
bbcode_enabled = true
|
||||
fit_content = true
|
||||
|
||||
200
scenes/ship/computer/UI/sensor_panel.gd
Normal file
200
scenes/ship/computer/UI/sensor_panel.gd
Normal file
@ -0,0 +1,200 @@
|
||||
# space_simulation/scripts/map_controller.gd
|
||||
class_name SensorPanel
|
||||
extends Control
|
||||
|
||||
signal body_selected_for_planning(body: RigidBody2D)
|
||||
|
||||
@export var map_icon_scene: PackedScene
|
||||
|
||||
const LABEL_CULLING_PIXEL_THRESHOLD = 65.0
|
||||
const ICON_CULLING_PIXEL_THRESHOLD = 40.0
|
||||
|
||||
var map_scale: float = 0.001
|
||||
var map_offset: Vector2 = Vector2.ZERO
|
||||
var focal_body: RigidBody2D
|
||||
|
||||
var icon_map: Dictionary = {}
|
||||
|
||||
var followed_body: RigidBody2D = null
|
||||
var map_tween: Tween
|
||||
|
||||
# The starting point for our lerp animation.
|
||||
var follow_start_offset: Vector2
|
||||
# The progress of the follow animation (0.0 to 1.0), animated by a tween.
|
||||
var follow_progress: float = 0.0:
|
||||
set(value):
|
||||
follow_progress = value
|
||||
# We must redraw every time the progress changes.
|
||||
queue_redraw()
|
||||
|
||||
# This is now the primary input for the map. It receives the "sensor feed".
|
||||
func update_sensor_feed(all_bodies: Array):
|
||||
# This function replaces the old _populate_map logic.
|
||||
# We'll check which bodies are new and which have been removed.
|
||||
var bodies_in_feed = all_bodies.duplicate()
|
||||
focal_body = bodies_in_feed[0]
|
||||
# Remove icons for bodies that are no longer in the feed
|
||||
for body in icon_map.keys():
|
||||
if not body in bodies_in_feed:
|
||||
if is_instance_valid(icon_map[body]):
|
||||
icon_map[body].queue_free()
|
||||
icon_map.erase(body)
|
||||
|
||||
# Add icons for new bodies
|
||||
for body in bodies_in_feed:
|
||||
if not body in icon_map:
|
||||
var icon = map_icon_scene.instantiate() as MapIcon
|
||||
add_child(icon)
|
||||
icon.initialize(body)
|
||||
icon_map[body] = icon
|
||||
icon.selected.connect(_on_map_icon_selected)
|
||||
icon.follow_requested.connect(_on_follow_requested)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
_update_icon_positions()
|
||||
|
||||
func _draw() -> void:
|
||||
var map_center = get_rect().size / 2.0
|
||||
|
||||
var system_data = GameManager.get_system_data()
|
||||
if system_data and system_data.belts:
|
||||
for belt in system_data.belts:
|
||||
var radius = belt.centered_radius * map_scale
|
||||
draw_circle(map_center + map_offset, radius, Color(Color.WHITE, 0.1), false)
|
||||
|
||||
for body in icon_map:
|
||||
if body is Asteroid: continue
|
||||
var icon = icon_map[body]
|
||||
if not icon.visible: continue
|
||||
|
||||
var path_points = []
|
||||
if body is CelestialBody: path_points = OrbitalMechanics._calculate_relative_orbital_path(body)
|
||||
elif body is OrbitalBody2D: path_points = OrbitalMechanics._calculate_n_body_orbital_path(body)
|
||||
else: continue
|
||||
var scaled_path_points = PackedVector2Array()
|
||||
|
||||
for point in path_points:
|
||||
# Ensure path is drawn relative to the main focal body (the star)
|
||||
var path_world_pos = point + focal_body.global_position
|
||||
var relative_pos = path_world_pos - focal_body.global_position
|
||||
var scaled_pos = (relative_pos * map_scale) + map_offset + map_center
|
||||
scaled_path_points.append(scaled_pos)
|
||||
|
||||
if scaled_path_points.size() > 1:
|
||||
draw_polyline(scaled_path_points, Color(Color.WHITE, 0.2), 1.0, true)
|
||||
|
||||
func _populate_map():
|
||||
for child in get_children():
|
||||
child.queue_free()
|
||||
icon_map.clear()
|
||||
|
||||
var all_bodies = GameManager.get_all_trackable_bodies()
|
||||
for body in all_bodies:
|
||||
if not is_instance_valid(body): continue
|
||||
var icon = map_icon_scene.instantiate() as MapIcon
|
||||
add_child(icon)
|
||||
icon.initialize(body)
|
||||
icon_map[body] = icon
|
||||
icon.selected.connect(_on_map_icon_selected)
|
||||
icon.follow_requested.connect(_on_follow_requested)
|
||||
|
||||
func _update_icon_positions():
|
||||
if not is_instance_valid(focal_body): return
|
||||
|
||||
var map_center = get_rect().size / 2.0
|
||||
|
||||
# --- MODIFIED: Continuous follow logic ---
|
||||
if is_instance_valid(followed_body):
|
||||
# Calculate the ideal offset to center the followed body.
|
||||
var relative_target_pos = followed_body.global_position - focal_body.global_position
|
||||
var target_offset = -relative_target_pos * map_scale
|
||||
|
||||
# During the initial pan, interpolate from the start to the target.
|
||||
# When follow_progress reaches 1.0, this just becomes target_offset.
|
||||
map_offset = follow_start_offset.lerp(target_offset, follow_progress)
|
||||
|
||||
# It will now use the dynamically updated map_offset.
|
||||
var icon_data_for_frame = []
|
||||
for body in icon_map:
|
||||
var icon = icon_map[body]
|
||||
|
||||
icon.visible = true
|
||||
icon.name_label.visible = true
|
||||
|
||||
var relative_pos = body.global_position - focal_body.global_position
|
||||
var final_screen_pos = (relative_pos * map_scale) + map_offset + map_center
|
||||
|
||||
icon_data_for_frame.append({
|
||||
"screen_pos": final_screen_pos,
|
||||
"body": body,
|
||||
"icon": icon
|
||||
})
|
||||
|
||||
icon.position = final_screen_pos - (icon.size / 2)
|
||||
|
||||
for i in range(icon_data_for_frame.size()):
|
||||
var data_a = icon_data_for_frame[i]
|
||||
|
||||
if not data_a.icon.visible:
|
||||
continue
|
||||
|
||||
for j in range(i + 1, icon_data_for_frame.size()):
|
||||
var data_b = icon_data_for_frame[j]
|
||||
if not data_b.icon.visible: continue
|
||||
|
||||
var distance = data_a.screen_pos.distance_to(data_b.screen_pos)
|
||||
|
||||
if distance < ICON_CULLING_PIXEL_THRESHOLD:
|
||||
if data_a.body.mass > data_b.body.mass:
|
||||
data_b.icon.visible = false
|
||||
else:
|
||||
data_a.icon.visible = false
|
||||
elif distance < LABEL_CULLING_PIXEL_THRESHOLD:
|
||||
if data_a.body.mass > data_b.body.mass:
|
||||
data_b.icon.name_label.visible = false
|
||||
else:
|
||||
data_a.icon.name_label.visible = false
|
||||
|
||||
# Request a redraw at the end of the update
|
||||
queue_redraw()
|
||||
|
||||
func _gui_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_WHEEL_UP or event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||
var zoom_factor = 1.25 if event.button_index == MOUSE_BUTTON_WHEEL_UP else 1 / 1.25
|
||||
var mouse_pos = get_local_mouse_position()
|
||||
var map_center = get_rect().size / 2.0
|
||||
|
||||
var point_under_mouse_world = (mouse_pos - map_center - map_offset) / map_scale
|
||||
map_scale *= zoom_factor
|
||||
var point_under_mouse_new_screen = (point_under_mouse_world * map_scale) + map_center + map_offset
|
||||
map_offset += mouse_pos - point_under_mouse_new_screen
|
||||
|
||||
if event is InputEventMouseMotion and event.button_mask & MOUSE_BUTTON_MASK_LEFT:
|
||||
# --- MODIFIED: Break the lock and reset progress ---
|
||||
if is_instance_valid(followed_body):
|
||||
print("Map lock disengaged by manual pan.")
|
||||
followed_body = null
|
||||
follow_progress = 0.0 # Reset progress
|
||||
if map_tween:
|
||||
map_tween.kill()
|
||||
|
||||
map_offset += event.relative
|
||||
|
||||
func _on_map_icon_selected(body: RigidBody2D):
|
||||
emit_signal("body_selected_for_planning", body)
|
||||
|
||||
func _on_follow_requested(body: RigidBody2D):
|
||||
print("Map view locking on to: ", body.name)
|
||||
follow_progress = 0.0
|
||||
followed_body = body
|
||||
|
||||
if map_tween:
|
||||
map_tween.kill()
|
||||
|
||||
# Store the offset at the exact moment the follow begins.
|
||||
follow_start_offset = map_offset
|
||||
|
||||
# --- REVISED: We now tween the 'follow_progress' property instead of 'map_offset' ---
|
||||
map_tween = create_tween().set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN_OUT)
|
||||
map_tween.tween_property(self, "follow_progress", 1.0, 1.5)
|
||||
1
scenes/ship/computer/UI/sensor_panel.gd.uid
Normal file
1
scenes/ship/computer/UI/sensor_panel.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bat1cxo15fnl7
|
||||
20
scenes/ship/computer/UI/sensor_panel.tscn
Normal file
20
scenes/ship/computer/UI/sensor_panel.tscn
Normal file
@ -0,0 +1,20 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://rd1c22nsru8y"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bat1cxo15fnl7" path="res://scenes/ship/computer/UI/sensor_panel.gd" id="1_5yxry"]
|
||||
[ext_resource type="PackedScene" uid="uid://c2imrmgjthfdm" path="res://scenes/UI/MapIcon.tscn" id="2_kvnmq"]
|
||||
|
||||
[node name="SensorPanel" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -350.0
|
||||
offset_top = -180.0
|
||||
offset_right = 350.0
|
||||
offset_bottom = 180.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_5yxry")
|
||||
map_icon_scene = ExtResource("2_kvnmq")
|
||||
9
scenes/ship/computer/panels/sensor_panel.tres
Normal file
9
scenes/ship/computer/panels/sensor_panel.tres
Normal file
@ -0,0 +1,9 @@
|
||||
[gd_resource type="Resource" script_class="ControlPanel" load_steps=3 format=3 uid="uid://dl7g67mtqkfx2"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cskf26i7vnxug" path="res://scenes/ship/computer/control_panel.gd" id="1_f0h3m"]
|
||||
[ext_resource type="PackedScene" uid="uid://rd1c22nsru8y" path="res://scenes/ship/computer/UI/sensor_panel.tscn" id="2_kyhrs"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_f0h3m")
|
||||
ui_scene = ExtResource("2_kyhrs")
|
||||
metadata/_custom_type_script = "uid://cskf26i7vnxug"
|
||||
12
scenes/ship/computer/shards/nav_selection_databank.gd
Normal file
12
scenes/ship/computer/shards/nav_selection_databank.gd
Normal file
@ -0,0 +1,12 @@
|
||||
extends Node
|
||||
|
||||
class_name NavLogicShard
|
||||
|
||||
# --- INPUT SOCKETS ---
|
||||
# This function will be connected to the map's "body_selected_for_planning" signal.
|
||||
func on_body_selected(body: Node2D):
|
||||
if not is_instance_valid(body): return
|
||||
|
||||
print("NAV SHARD: Target selected - ", body.name)
|
||||
# Later, this is where we would enable maneuver calculation buttons
|
||||
# and feed this target data to other datashards.
|
||||
@ -0,0 +1 @@
|
||||
uid://t12etsdx2h38
|
||||
9
scenes/ship/computer/shards/nav_selection_databank.tres
Normal file
9
scenes/ship/computer/shards/nav_selection_databank.tres
Normal file
@ -0,0 +1,9 @@
|
||||
[gd_resource type="Resource" script_class="Databank" load_steps=3 format=3 uid="uid://g4ho63f30vjm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://osk1l75vlikn" path="res://scenes/ship/computer/databank.gd" id="1_d0eru"]
|
||||
[ext_resource type="Script" uid="uid://t12etsdx2h38" path="res://scenes/ship/computer/shards/nav_selection_databank.gd" id="1_mt7ap"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_d0eru")
|
||||
logic_script = ExtResource("1_mt7ap")
|
||||
metadata/_custom_type_script = "uid://osk1l75vlikn"
|
||||
12
scenes/ship/computer/shards/sensor_databank.gd
Normal file
12
scenes/ship/computer/shards/sensor_databank.gd
Normal file
@ -0,0 +1,12 @@
|
||||
extends Node
|
||||
|
||||
class_name SensorSystemShard
|
||||
|
||||
## This shard emits all trackable bodies as a "sensor feed" every frame.
|
||||
signal sensor_feed_updated(bodies: Array)
|
||||
|
||||
func _physics_process(delta):
|
||||
# In a more advanced game, this shard might have its own power requirements
|
||||
# or could be affected by radiation, etc. For now, it just gets all bodies.
|
||||
var all_bodies = GameManager.get_all_trackable_bodies()
|
||||
sensor_feed_updated.emit(all_bodies)
|
||||
1
scenes/ship/computer/shards/sensor_databank.gd.uid
Normal file
1
scenes/ship/computer/shards/sensor_databank.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://diu2tgusi3vmt
|
||||
9
scenes/ship/computer/shards/sensor_databank.tres
Normal file
9
scenes/ship/computer/shards/sensor_databank.tres
Normal file
@ -0,0 +1,9 @@
|
||||
[gd_resource type="Resource" script_class="Databank" load_steps=3 format=3 uid="uid://b0suy3sxjwhtv"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://osk1l75vlikn" path="res://scenes/ship/computer/databank.gd" id="1_nbqt3"]
|
||||
[ext_resource type="Script" uid="uid://diu2tgusi3vmt" path="res://scenes/ship/computer/shards/sensor_databank.gd" id="1_uxkgc"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_nbqt3")
|
||||
logic_script = ExtResource("1_uxkgc")
|
||||
metadata/_custom_type_script = "uid://osk1l75vlikn"
|
||||
@ -1,5 +1,4 @@
|
||||
# space_simulation/scripts/map_controller.gd
|
||||
|
||||
class_name MapController
|
||||
extends Control
|
||||
|
||||
|
||||
Reference in New Issue
Block a user