Render of inputs to databanks
This commit is contained in:
@ -1,29 +1,31 @@
|
||||
[gd_scene load_steps=18 format=3 uid="uid://didt2nsdtbmra"]
|
||||
[gd_scene load_steps=20 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"]
|
||||
[ext_resource type="PackedScene" uid="uid://d3hitk62fice4" path="res://scenes/ship/builder/pieces/bulkhead.tscn" id="4_dmrms"]
|
||||
[ext_resource type="PackedScene" uid="uid://2n42nstcj1n0" path="res://scenes/ship/components/hardware/system_station.tscn" id="5_nqe0s"]
|
||||
[ext_resource type="Script" uid="uid://osk1l75vlikn" path="res://scenes/ship/computer/databank.gd" id="6_ft4kn"]
|
||||
[ext_resource type="Resource" uid="uid://dghg3pbws42yu" path="res://scenes/ship/computer/shards/helm_logic_databank.tres" id="7_dmrms"]
|
||||
[ext_resource type="Script" uid="uid://diu2tgusi3vmt" path="res://scenes/ship/computer/shards/sensor_databank.gd" id="9_ixntg"]
|
||||
[ext_resource type="PackedScene" uid="uid://dt1t2n7dewucw" path="res://scenes/ship/computer/UI/button_panel.tscn" id="10_px2ne"]
|
||||
[ext_resource type="Resource" uid="uid://bx7wgunvy5hfa" path="res://scenes/ship/computer/shards/helm_ship_status.tres" id="11_83bu1"]
|
||||
[ext_resource type="Script" uid="uid://cfbyqvnvf3hna" path="res://scenes/ship/computer/shards/helm_logic_databank.gd" id="10_wkxbw"]
|
||||
[ext_resource type="PackedScene" uid="uid://cdbqjkgsj02or" path="res://scenes/ship/computer/UI/readout_screen_panel.tscn" id="11_erhv3"]
|
||||
[ext_resource type="Script" uid="uid://t12etsdx2h38" path="res://scenes/ship/computer/shards/nav_selection_databank.gd" id="11_xwy4s"]
|
||||
[ext_resource type="Script" uid="uid://ceqdi6jobefnc" path="res://scenes/ship/computer/shards/helm_autopilot_databank.gd" id="12_4epkn"]
|
||||
[ext_resource type="PackedScene" uid="uid://rd1c22nsru8y" path="res://scenes/ship/computer/UI/sensor_panel.tscn" id="12_q1rtr"]
|
||||
[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="PackedScene" uid="uid://pq55j75t3fda" path="res://scenes/ship/computer/UI/throttle_lever_panel.tscn" id="13_rsa1x"]
|
||||
[ext_resource type="Resource" uid="uid://dwhpjwuobcqdu" path="res://scenes/ship/computer/shards/helm_autopilot_databank.tres" id="13_xfp3q"]
|
||||
[ext_resource type="Resource" uid="uid://b0suy3sxjwhtv" path="res://scenes/ship/computer/shards/sensor_databank.tres" id="13_xwy4s"]
|
||||
[ext_resource type="Resource" uid="uid://6jj1jd14cdlt" path="res://scenes/ship/computer/shards/nav_hohman_planner.tres" id="15_fll2s"]
|
||||
[ext_resource type="Script" uid="uid://ctgl5kxyagw0f" path="res://scenes/ship/computer/shards/helm_ship_status.gd" id="13_wkxbw"]
|
||||
[ext_resource type="Script" uid="uid://ghluwjd5c5ul" path="res://scenes/ship/computer/shards/nav_brachistochrone_planner.gd" id="14_xwy4s"]
|
||||
[ext_resource type="Script" uid="uid://bghu5lhcbcfmh" path="res://scenes/ship/computer/shards/nav_hohman_planner.gd" id="15_fll2s"]
|
||||
[ext_resource type="Script" uid="uid://dsbn7ushwqrko" path="res://scenes/ship/computer/shards/nav_intercept_solver.gd" id="16_vufgi"]
|
||||
[ext_resource type="Script" uid="uid://0f6v6iu3o5qo" path="res://scenes/ship/computer/shards/nav_projection_shard.gd" id="17_34v0b"]
|
||||
|
||||
[node name="Module" type="Node2D"]
|
||||
physics_interpolation_mode = 2
|
||||
script = ExtResource("1_nqe0s")
|
||||
physics_mode = 1
|
||||
mass = 2.0
|
||||
inertia = 0.5
|
||||
mass = 1.0
|
||||
inertia = 0.0
|
||||
metadata/_custom_type_script = "uid://0isnsk356que"
|
||||
|
||||
[node name="Hullplate" parent="." instance=ExtResource("2_foqop")]
|
||||
@ -106,7 +108,7 @@ base_mass = 0.0
|
||||
[node name="Station" parent="." instance=ExtResource("5_nqe0s")]
|
||||
position = Vector2(0, -10)
|
||||
panel_scenes = Array[PackedScene]([ExtResource("11_erhv3"), ExtResource("11_erhv3"), ExtResource("12_q1rtr"), ExtResource("10_px2ne"), ExtResource("13_rsa1x")])
|
||||
installed_databanks = Array[ExtResource("6_ft4kn")]([ExtResource("11_83bu1"), ExtResource("7_dmrms"), ExtResource("13_xfp3q"), ExtResource("12_wkxbw"), ExtResource("15_fll2s"), ExtResource("13_xwy4s")])
|
||||
databank_installations = Array[Script]([ExtResource("10_wkxbw"), ExtResource("12_4epkn"), ExtResource("13_wkxbw"), ExtResource("9_ixntg"), ExtResource("11_xwy4s"), ExtResource("14_xwy4s"), ExtResource("15_fll2s"), ExtResource("16_vufgi"), ExtResource("17_34v0b")])
|
||||
physics_mode = 2
|
||||
|
||||
[node name="Thruster" parent="." instance=ExtResource("12_vmx8o")]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
@tool
|
||||
class_name SystemStation
|
||||
extends Component
|
||||
|
||||
@ -8,6 +7,7 @@ signal occupancy_changed(is_occupied: bool)
|
||||
var UiWindowScene = preload("res://scenes/UI/ui_window.tscn")
|
||||
|
||||
@export var panel_scenes: Array[PackedScene]
|
||||
@export var databank_installations: Array[Script]
|
||||
@export var installed_databanks: Array[Databank]
|
||||
|
||||
@onready var panel_frame: PanelFrame = $PanelFrame
|
||||
@ -17,7 +17,7 @@ var wiring_schematic: WiringSchematic
|
||||
|
||||
# --- State ---
|
||||
var occupants: Array[PilotBall] = []
|
||||
var active_shard_instances: Array[Node] = []
|
||||
var active_shard_instances: Array[Databank] = []
|
||||
var persistent_panel_instances: Array[BasePanel] = []
|
||||
var occupant_panel_map: Dictionary = {}
|
||||
|
||||
@ -30,17 +30,29 @@ func _ready():
|
||||
if not is_instance_valid(root_module):
|
||||
push_error("Station could not find its root module!")
|
||||
return
|
||||
|
||||
for shard_resource in installed_databanks:
|
||||
if not shard_resource or not shard_resource.logic_script: continue
|
||||
|
||||
for DatabankScript in databank_installations:
|
||||
if not DatabankScript: continue
|
||||
var installed_databank = DatabankScript.new()
|
||||
if installed_databank is not Databank:
|
||||
installed_databank.queue_free()
|
||||
continue
|
||||
|
||||
add_child(installed_databank)
|
||||
active_shard_instances.append(installed_databank)
|
||||
if installed_databank.has_method("initialize"):
|
||||
installed_databank.initialize(root_module)
|
||||
|
||||
# for shard_resource in installed_databanks:
|
||||
# if not shard_resource or not shard_resource.logic_script: continue
|
||||
|
||||
var shard_instance = Node.new()
|
||||
shard_instance.set_script(shard_resource.logic_script)
|
||||
add_child(shard_instance) # Add as a permanent child
|
||||
active_shard_instances.append(shard_instance)
|
||||
# var shard_instance = Node.new()
|
||||
# shard_instance.set_script(shard_resource.logic_script)
|
||||
# add_child(shard_instance) # Add as a permanent child
|
||||
# active_shard_instances.append(shard_instance)
|
||||
|
||||
if shard_instance.has_method("initialize"):
|
||||
shard_instance.initialize(root_module)
|
||||
# if shard_instance.has_method("initialize"):
|
||||
# shard_instance.initialize(root_module)
|
||||
|
||||
_connect_internals([], active_shard_instances)
|
||||
|
||||
@ -107,11 +119,9 @@ func launch_interfaces_for_occupant(character: PilotBall):
|
||||
ui_window.close_requested.connect(close_interface)
|
||||
ui_window.title = "Helm"
|
||||
|
||||
# TODO: Add button to switch to wiring mode
|
||||
|
||||
var frame: PanelFrame = PanelFrame.new()
|
||||
frame.build(panel_scenes, self)
|
||||
|
||||
frame.databanks = active_shard_instances
|
||||
ui_window.set_content(frame)
|
||||
|
||||
ui_window.flip_button_pressed.connect(frame.toggle_wiring_mode)
|
||||
@ -206,15 +216,15 @@ func _connect_internals(panel_instances: Array, shard_instances: Array):
|
||||
if map_panel and nav_selection_shard:
|
||||
# Connect the shard's "sensor_feed_updated" signal (blue wire)
|
||||
# to the map's "update_sensor_feed" socket.
|
||||
map_panel.connect("body_selected_for_planning", nav_selection_shard.on_body_selected)
|
||||
map_panel.connect("body_selected_for_planning", nav_selection_shard.body_selected)
|
||||
print("Wired: Sensor Shard -> Map Panel (Sensor Feed)")
|
||||
|
||||
if nav_selection_shard and hohman_planner_shard:
|
||||
nav_selection_shard.target_selected.connect(hohman_planner_shard.on_target_updated)
|
||||
nav_selection_shard.target_selected.connect(hohman_planner_shard.target_updated)
|
||||
print("Wired: Nav Selection -> Maneuver Planner")
|
||||
|
||||
if hohman_planner_shard and autopilot_shard:
|
||||
hohman_planner_shard.maneuver_calculated.connect(autopilot_shard.on_maneuver_received)
|
||||
hohman_planner_shard.maneuver_calculated.connect(autopilot_shard.maneuver_received)
|
||||
print("Wired: Maneuver Planner -> Autopilot")
|
||||
|
||||
if autopilot_shard and helm_shard:
|
||||
|
||||
@ -6,6 +6,8 @@ signal body_selected_for_planning(body: OrbitalBody2D)
|
||||
|
||||
@export var map_icon_scene: PackedScene
|
||||
|
||||
@onready var map_canvas: Control = %MapCanvas
|
||||
|
||||
const LABEL_CULLING_PIXEL_THRESHOLD = 65.0
|
||||
const ICON_CULLING_PIXEL_THRESHOLD = 40.0
|
||||
|
||||
@ -27,6 +29,13 @@ var follow_progress: float = 0.0:
|
||||
# We must redraw every time the progress changes.
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func get_output_sockets():
|
||||
return ["body_selected_for_planning"]
|
||||
|
||||
func get_input_sockets():
|
||||
return ["update_sensor_feed"]
|
||||
|
||||
# This is now the primary input for the map. It receives the "sensor feed".
|
||||
func update_sensor_feed(all_bodies: Array[OrbitalBody2D]):
|
||||
# This function replaces the old _populate_map logic.
|
||||
@ -45,7 +54,7 @@ func update_sensor_feed(all_bodies: Array[OrbitalBody2D]):
|
||||
for body in bodies_in_feed:
|
||||
if not body in icon_map:
|
||||
var icon = map_icon_scene.instantiate() as MapIcon
|
||||
add_child(icon)
|
||||
map_canvas.add_child(icon)
|
||||
icon.initialize(body)
|
||||
icon_map[body] = icon
|
||||
icon.selected.connect(_on_map_icon_selected)
|
||||
@ -102,9 +111,10 @@ func draw_projected_orbits(bodies_to_project: Array[OrbitalBody2D]):
|
||||
func _update_icon_positions():
|
||||
if not is_instance_valid(focal_body): return
|
||||
|
||||
var map_center = get_rect().size / 2.0
|
||||
var map_center = map_canvas.get_rect().size / 2.0
|
||||
|
||||
# --- MODIFIED: Continuous follow logic ---
|
||||
# TODO: Follow logic broke when map_canvas was introduced
|
||||
# --- 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
|
||||
@ -163,8 +173,8 @@ 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 mouse_pos = map_canvas.get_local_mouse_position()
|
||||
var map_center = map_canvas.get_rect().size / 2.0
|
||||
|
||||
var point_under_mouse_world = (mouse_pos - map_center - map_offset) / map_scale
|
||||
map_scale *= zoom_factor
|
||||
|
||||
@ -7,7 +7,14 @@
|
||||
clip_contents = true
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
mouse_filter = 1
|
||||
script = ExtResource("1_5yxry")
|
||||
map_icon_scene = ExtResource("2_kvnmq")
|
||||
grid_width = 6
|
||||
grid_height = 4
|
||||
|
||||
[node name="MapCanvas" type="Control" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
@tool
|
||||
class_name Databank
|
||||
extends Resource
|
||||
extends Node
|
||||
|
||||
## The script containing the logic for this shard.
|
||||
@export var logic_script: Script
|
||||
var root_module: Module
|
||||
|
||||
# --- Initialization ---
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Dictionary:
|
||||
return {}
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return []
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_signals() -> Dictionary:
|
||||
return {}
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return []
|
||||
|
||||
@ -15,6 +15,9 @@ var start_socket: Socket
|
||||
var end_socket: Socket
|
||||
var wiring_mode: bool = false
|
||||
|
||||
var databanks: Array[Databank]
|
||||
var databanks_container: GridContainer
|
||||
|
||||
# --- NO CHANGE HERE ---
|
||||
# This getter is a nice way to access only the BasePanel children.
|
||||
var installed_panels: Array[BasePanel]:
|
||||
@ -83,9 +86,14 @@ func build(panel_scenes: Array[PackedScene], station: SystemStation):
|
||||
func _sort_children():
|
||||
#print("PanelFrame Sorting children")
|
||||
for child in get_children():
|
||||
if child == databanks_container:
|
||||
print("Databanks container found %s" % child)
|
||||
fit_child_in_rect(child, Rect2(Vector2(0, rows * Constants.UI_GRID_SIZE), child.size))
|
||||
continue
|
||||
# Skip any nodes that aren't a BasePanel.
|
||||
if not child is BasePanel:
|
||||
continue
|
||||
|
||||
|
||||
var panel := child as BasePanel
|
||||
|
||||
@ -102,7 +110,6 @@ func _sort_children():
|
||||
fit_child_in_rect(panel, Rect2(start_pos, panel_size))
|
||||
|
||||
# TODO: Expose grid to install panels
|
||||
# TODO: Determine if
|
||||
|
||||
func toggle_wiring_mode():
|
||||
wiring_mode = !wiring_mode
|
||||
@ -110,16 +117,74 @@ func toggle_wiring_mode():
|
||||
for panel in installed_panels:
|
||||
panel.set_wiring_mode(wiring_mode)
|
||||
|
||||
if wiring_mode:
|
||||
_build_databanks(databanks)
|
||||
pass
|
||||
|
||||
if is_instance_valid(databanks_container):
|
||||
if wiring_mode: databanks_container.show()
|
||||
else: databanks_container.hide()
|
||||
|
||||
class InstalledDatabank:
|
||||
extends Control
|
||||
|
||||
var databank_ref: Databank
|
||||
var all_sockets: Array[Socket] = []
|
||||
var SocketScene: PackedScene = preload("res://scenes/ship/computer/wiring/socket.tscn")
|
||||
var inputs_container: VBoxContainer
|
||||
var outputs_container: VBoxContainer
|
||||
|
||||
func _populate_sockets():
|
||||
all_sockets.clear()
|
||||
|
||||
if not is_instance_valid(inputs_container):
|
||||
inputs_container = VBoxContainer.new()
|
||||
add_child(inputs_container)
|
||||
|
||||
if not is_instance_valid(outputs_container):
|
||||
outputs_container = VBoxContainer.new()
|
||||
add_child(outputs_container)
|
||||
|
||||
# Populate Input Sockets
|
||||
for socket_name in databank_ref.get_input_sockets():
|
||||
var socket = SocketScene.instantiate()
|
||||
inputs_container.add_child(socket)
|
||||
socket.initialize(socket_name, Socket.SocketType.INPUT)
|
||||
all_sockets.append(socket)
|
||||
|
||||
# Populate Output Sockets
|
||||
for socket_name in databank_ref.get_output_sockets():
|
||||
var socket = SocketScene.instantiate()
|
||||
outputs_container.add_child(socket)
|
||||
socket.initialize(socket_name, Socket.SocketType.OUTPUT)
|
||||
all_sockets.append(socket)
|
||||
|
||||
func _build_databanks(dbs_to_install: Array[Databank]):
|
||||
if not is_instance_valid(databanks_container):
|
||||
databanks_container = GridContainer.new()
|
||||
databanks_container.columns = columns
|
||||
databanks_container.add_theme_constant_override("h_separation", Constants.UI_GRID_SIZE * 3)
|
||||
databanks_container.add_theme_constant_override("v_separation", Constants.UI_GRID_SIZE + 16)
|
||||
add_child(databanks_container)
|
||||
|
||||
var installed_databanks = databanks_container.get_children()
|
||||
|
||||
for to_install in dbs_to_install:
|
||||
if installed_databanks.any(func(existing_db): return existing_db.databank_ref == to_install):
|
||||
continue
|
||||
|
||||
var installed_databank = InstalledDatabank.new()
|
||||
installed_databank.databank_ref = to_install
|
||||
databanks_container.add_child(installed_databank)
|
||||
installed_databank._populate_sockets()
|
||||
|
||||
func _gui_input(event: InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
# --- Start or End a Wire ---
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.is_pressed():
|
||||
print("foo")
|
||||
|
||||
var socket = _get_socket_at_pos(event.position)
|
||||
print(socket)
|
||||
if socket:
|
||||
current_state = WiringState.DRAGGING_WIRE
|
||||
if not start_socket:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# scenes/ship/computer/shards/autopilot_databank.gd
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name AutopilotShard
|
||||
|
||||
signal execution_state_changed(is_executing: bool, status: String)
|
||||
@ -9,8 +9,13 @@ signal request_rotation(r: float)
|
||||
signal request_rotation_thrust(r: float)
|
||||
signal request_main_engine_thrust(t: float)
|
||||
|
||||
# --- References ---
|
||||
var root_module: Module
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["maneuver_received", "execute_plan", "set_thruster_calibration"]
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["execution_state_changed", "fmt_out", "request_attitude_hold", "request_rotation", "request_rotation_thrust", "request_main_engine_thrust"]
|
||||
|
||||
# --- State ---
|
||||
enum State { IDLE, WAITING_FOR_WINDOW, EXECUTING_BURN }
|
||||
@ -22,9 +27,6 @@ var is_executing: bool = false
|
||||
var status: String = ""
|
||||
var current_timer: SceneTreeTimer
|
||||
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
|
||||
func _process(delta):
|
||||
var fmt = ""
|
||||
var state_name = State.keys()[current_state]
|
||||
@ -39,7 +41,7 @@ func _process(delta):
|
||||
|
||||
|
||||
# INPUT SOCKET: Connected to the ManeuverPlanner's "maneuver_calculated" signal.
|
||||
func on_maneuver_received(plan: Array[DataTypes.ImpulsiveBurnPlan]):
|
||||
func maneuver_received(plan: Array[DataTypes.ImpulsiveBurnPlan]):
|
||||
current_plan = plan
|
||||
print("AUTOPILOT: Maneuver plan received.")
|
||||
status = "Plan Received.\nPress Execute."
|
||||
|
||||
@ -1,20 +1,26 @@
|
||||
extends Node
|
||||
|
||||
extends Databank
|
||||
class_name HelmLogicShard
|
||||
|
||||
# --- References ---
|
||||
var root_module: Module
|
||||
var thrusters: Array[Thruster] = []
|
||||
@onready var thrusters: Array[Thruster] = []
|
||||
|
||||
# --- PD Controller Constants ---
|
||||
@export var HOLD_KP: float = 8000.0 # Proportional gain
|
||||
@export var HOLD_KD: float = 1200.0 # Derivative gain
|
||||
|
||||
var target_rotation_rad: float = 0.0
|
||||
@onready var target_rotation_rad: float = 0.0
|
||||
var attitude_hold_enabled: bool = false
|
||||
|
||||
var thruster_calibration_data: DataTypes.ThrusterCalibration
|
||||
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["shutdown_rcs", "calibrate_rcs_performance", "set_throttle_input", "set_rotation_input", "set_desired_rotation", "set_attitude_hold"]
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["thruster_calibrated"]
|
||||
|
||||
# The Station calls this after instantiating the shard.
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
@ -28,7 +34,6 @@ func initialize(ship_root: Module):
|
||||
# Default to holding the initial attitude.
|
||||
target_rotation_rad = root_module.rotation
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not is_instance_valid(root_module): return
|
||||
|
||||
@ -81,7 +86,6 @@ func set_attitude_hold(hold: bool):
|
||||
# --- LOGIC (Migrated from ThrusterController.gd) ---
|
||||
|
||||
func _perform_manual_hold():
|
||||
|
||||
var error = shortest_angle_between(root_module.rotation, target_rotation_rad)
|
||||
if abs(error) > 0.001:
|
||||
var desired_torque = (error * HOLD_KP) - (root_module.angular_velocity * HOLD_KD)
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
extends Node
|
||||
extends Databank
|
||||
|
||||
class_name ShipStatusShard
|
||||
|
||||
## This shard emits a signal with the formatted ship status text.
|
||||
signal status_updated(text: String)
|
||||
|
||||
var root_module: Module
|
||||
|
||||
# Called by the Station when it's created.
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return []
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["status_updated"]
|
||||
|
||||
func _physics_process(delta):
|
||||
if not is_instance_valid(root_module):
|
||||
return
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
# space_simulation/scenes/ship/computer/shards/nav_brachistochrone_planner.gd
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name BrachistochronePlannerShard
|
||||
|
||||
## Emitted when a maneuver plan has been successfully calculated.
|
||||
signal maneuver_calculated(plan: Array[DataTypes.ImpulsiveBurnPlan])
|
||||
|
||||
# --- References ---
|
||||
var root_module: Module
|
||||
var target_body: OrbitalBody2D = null
|
||||
|
||||
# --- Initialization ---
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["target_updated", "calculate_hohmann_transfer"]
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["maneuver_calculated"]
|
||||
|
||||
# INPUT SOCKET: Connected to the NavSelectionShard's "target_selected" signal.
|
||||
func on_target_updated(new_target: OrbitalBody2D):
|
||||
func target_updated(new_target: OrbitalBody2D):
|
||||
print("BRACHISTOCHRONE PLANNER: Target received %s." % new_target.name)
|
||||
target_body = new_target
|
||||
|
||||
|
||||
@ -1,23 +1,27 @@
|
||||
# scenes/ship/computer/shards/maneuver_planner_databank.gd
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name HohmanPlannerShard
|
||||
|
||||
## Emitted when a maneuver plan has been successfully calculated.
|
||||
signal maneuver_calculated(plan: Array[DataTypes.ImpulsiveBurnPlan])
|
||||
|
||||
# --- References ---
|
||||
var root_module: Module
|
||||
var selection_shard: NavSelectionShard
|
||||
var target_body: OrbitalBody2D = null
|
||||
|
||||
# --- Configurations ---
|
||||
var boost_factor: float = 1.0
|
||||
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["target_updated", "calculate_hohmann_transfer"]
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["maneuver_calculated"]
|
||||
|
||||
# INPUT SOCKET: Connected to the NavSelectionShard's "target_selected" signal.
|
||||
func on_target_updated(new_target: OrbitalBody2D):
|
||||
func target_updated(new_target: OrbitalBody2D):
|
||||
print("MANEUVER PLANNER: Target recieved %s." % new_target)
|
||||
target_body = new_target
|
||||
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
# space_simulation/scenes/ship/computer/shards/nav_intercept_solver.gd
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name InterceptSolverShard
|
||||
|
||||
signal solution_found(plan: Array[DataTypes.ImpulsiveBurnPlan])
|
||||
signal solution_impossible
|
||||
|
||||
var root_module: Module
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["project_n_body_paths"]
|
||||
|
||||
func initialize(ship_root: Module):
|
||||
self.root_module = ship_root
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["solution_found", "solution_impossible"]
|
||||
|
||||
# INPUT SOCKET: Planners will call this with a projected path.
|
||||
func solve_rendezvous_plan(
|
||||
|
||||
@ -1,10 +1,18 @@
|
||||
# space_simulation/scenes/ship/computer/shards/nav_path_projection.gd
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name PathProjectionShard
|
||||
|
||||
## Emitted after a requested path has been calculated.
|
||||
signal projected_system_bus(paths: Array[DataTypes.PathPoint])
|
||||
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["project_n_body_paths"]
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["projected_system_bus"]
|
||||
|
||||
## Projects the future paths of an array of bodies interacting with each other.
|
||||
## Returns a dictionary mapping each body to its calculated PackedVector2Array path.
|
||||
func project_n_body_paths(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# scenes/ship/computer/shards/nav_selection_databank.gd
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name NavSelectionShard
|
||||
|
||||
## Emitted whenever a new navigation target is selected from the map.
|
||||
@ -7,8 +7,16 @@ signal target_selected(body: OrbitalBody2D)
|
||||
|
||||
var selected_body: OrbitalBody2D = null
|
||||
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return ["body_selected"]
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["target_selected"]
|
||||
|
||||
# INPUT SOCKET: This function is connected to the SensorPanel's "body_selected" signal.
|
||||
func on_body_selected(body: OrbitalBody2D):
|
||||
func body_selected(body: OrbitalBody2D):
|
||||
if is_instance_valid(body) and body != selected_body:
|
||||
print("NAV SELECTION: New target acquired - ", body.name)
|
||||
selected_body = body
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
extends Node
|
||||
extends Databank
|
||||
class_name SensorSystemShard
|
||||
|
||||
signal sensor_feed_updated(bodies: Array[OrbitalBody2D])
|
||||
@ -7,6 +7,14 @@ signal sensor_feed_updated(bodies: Array[OrbitalBody2D])
|
||||
@export var projection_steps: int = 500
|
||||
@export var time_per_step: float = 60.0 # Project at 1-minute intervals
|
||||
|
||||
## Describes the functions this shard needs as input.
|
||||
func get_input_sockets() -> Array[String]:
|
||||
return []
|
||||
|
||||
## Describes the signals this shard can output.
|
||||
func get_output_sockets() -> Array[String]:
|
||||
return ["sensor_feed_updated"]
|
||||
|
||||
# We use _process instead of _physics_process to avoid slowing down the physics thread.
|
||||
# This calculation can happen on a separate frame if needed.
|
||||
func _process(_delta: float):
|
||||
|
||||
@ -18,7 +18,8 @@ var socket_type: SocketType
|
||||
func initialize(s_name: String, s_type: SocketType):
|
||||
socket_name = s_name
|
||||
socket_type = s_type
|
||||
label.text = socket_name
|
||||
|
||||
icon.tooltip_text = socket_name
|
||||
|
||||
if socket_type == SocketType.INPUT:
|
||||
icon.color = Color.DODGER_BLUE
|
||||
|
||||
@ -34,13 +34,13 @@ func _ready():
|
||||
|
||||
# --- PUBLIC FORCE APPLICATION METHODS ---
|
||||
# This method is called by a component (like Thruster) at its global position.
|
||||
func apply_force(force: Vector2, position: Vector2 = self.global_position):
|
||||
func apply_force(force: Vector2, pos: Vector2 = self.global_position):
|
||||
# This is the force routing logic.
|
||||
match physics_mode:
|
||||
PhysicsMode.INDEPENDENT:
|
||||
_add_forces(force, position)
|
||||
_add_forces(force, pos)
|
||||
PhysicsMode.COMPOSITE:
|
||||
_add_forces(force, position)
|
||||
_add_forces(force, pos)
|
||||
## If we are the root, accumulate the force and calculate torque on the total body.
|
||||
#accumulated_force += force
|
||||
#
|
||||
@ -56,7 +56,7 @@ func apply_force(force: Vector2, position: Vector2 = self.global_position):
|
||||
if p is OrbitalBody2D:
|
||||
# Recursively call the parent's apply_force method.
|
||||
# This sends the force (and its original global position) up the chain.
|
||||
p.apply_force(force, position)
|
||||
p.apply_force(force, pos)
|
||||
return # Stop at the first OrbitalBody2D parent
|
||||
p = p.get_parent()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user