feat(game): restore in-system HUD with reactive station↔flight panel swap (U1)
Basic UI Shell: bring back the in-game flight HUD and station info panel, and implement the missing "station mode panel swap." Implementation: - New `in_system/hud.rs` with a reactive, idempotent `sync_hud_panels` system: it shows the station info panel while the player is `Docked` and the flight HUD while in `FlightState`, spawning/despawning only when the on-screen panel disagrees with the player's state. This replaces the old fragile event-driven spawn/despawn scattered through the transition systems. - Re-enabled the docked info panel (`ui.rs`) and flight HUD (`flight_ui.rs`), restructured both as small corner-anchored overlays with NO full-screen root so they only block camera orbit input when the cursor is directly over a panel (orbit_camera_control suppresses input over any UI node). - Made the docked panel info-only (actions live in the contextual action panel, which adapts to docked/flight modes). - Fixed the broken undock chain: `start_undocking`/`start_travel` now take a real `now_ms` (was hardcoded `0.0`, completing instantly) and a new `complete_operations` bridge maps `OperationCompletedEvent::Undocking` back to `UndockEvent` so `handle_undock` actually runs. - Wired `ActionType::Dock` to fire a `DockEvent` for a targeted station / habitable planet so the flight→docked swap is reachable too. - `handle_docking` now also clears Velocity/MoveTarget/SelectedTarget so the docked ship stops cleanly. - Fixed deprecated Bevy 0.16 APIs (single_mut, EventWriter::write, despawn) and removed now-dead code, dropping total warnings 183→137. Compiles clean (`cargo check`); no new warnings in touched files.
This commit is contained in:
@@ -8,11 +8,13 @@ mod actions;
|
||||
mod docked;
|
||||
mod flight;
|
||||
mod flight_ui;
|
||||
mod hud;
|
||||
mod operations;
|
||||
mod scene;
|
||||
mod target;
|
||||
mod ui;
|
||||
|
||||
use bevy::ecs::system::SystemParam;
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::state::AppState;
|
||||
@@ -22,7 +24,7 @@ pub use flight::{FlightState, FlightControlsPlugin};
|
||||
pub use scene::ActiveSystem;
|
||||
pub use target::{Targetable, TargetKind, SelectedTarget, TargetSelectionPlugin};
|
||||
pub use actions::{ContextualActionPlugin, ActionType, ActionTriggeredEvent, ActionUi};
|
||||
pub use operations::{TimedOperationPlugin, OperationKind, ActiveOperation};
|
||||
pub use operations::TimedOperationPlugin;
|
||||
|
||||
pub struct InSystemPlugin;
|
||||
|
||||
@@ -37,29 +39,19 @@ impl Plugin for InSystemPlugin {
|
||||
.add_plugins(TimedOperationPlugin)
|
||||
.add_systems(
|
||||
OnEnter(AppState::InGame),
|
||||
(
|
||||
scene::setup_in_system_view,
|
||||
// UI removed - no longer needed
|
||||
// ui::setup_docked_ui,
|
||||
add_targetable_to_pois,
|
||||
).chain(),
|
||||
(scene::setup_in_system_view, add_targetable_to_pois).chain(),
|
||||
)
|
||||
.add_systems(
|
||||
OnExit(AppState::InGame),
|
||||
(
|
||||
// UI removed - no longer needed
|
||||
// ui::despawn_docked_ui,
|
||||
// flight_ui::despawn_flight_ui,
|
||||
scene::despawn_in_system_scene,
|
||||
).chain(),
|
||||
(hud::despawn_in_system_hud, scene::despawn_in_system_scene).chain(),
|
||||
)
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
// UI removed - no longer needed
|
||||
// ui::refresh_docked_ui,
|
||||
// ui::undock_button_handler,
|
||||
// flight_ui::update_flight_ui,
|
||||
hud::sync_hud_panels,
|
||||
ui::refresh_docked_ui,
|
||||
flight_ui::update_flight_ui,
|
||||
complete_operations,
|
||||
handle_action_triggered,
|
||||
)
|
||||
.chain()
|
||||
@@ -68,38 +60,77 @@ impl Plugin for InSystemPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle action triggered events from the action buttons.
|
||||
/// Bundles the resources/event-writers [`handle_action_triggered`] dispatches
|
||||
/// through, keeping its parameter list under the system-argument threshold.
|
||||
#[derive(SystemParam)]
|
||||
struct ActionDispatch<'w> {
|
||||
time: Res<'w, Time>,
|
||||
durations: Res<'w, operations::OperationDurations>,
|
||||
started: EventWriter<'w, operations::OperationStartedEvent>,
|
||||
dock: EventWriter<'w, flight::DockEvent>,
|
||||
}
|
||||
|
||||
/// Handle action triggered events from the contextual action buttons.
|
||||
///
|
||||
/// - **Undock** starts a timed operation; on completion [`complete_operations`]
|
||||
/// fires the [`UndockEvent`] that drives the docked → flight transition.
|
||||
/// - **Dock** fires a [`flight::DockEvent`] directly (instant) for the selected
|
||||
/// station / habitable planet so the flight → docked transition (and the HUD
|
||||
/// swap back to the station panel) is reachable.
|
||||
fn handle_action_triggered(
|
||||
mut commands: Commands,
|
||||
mut events: EventReader<ActionTriggeredEvent>,
|
||||
player_query: Query<Entity, With<scene::PlayerShip>>,
|
||||
durations: Res<operations::OperationDurations>,
|
||||
mut operation_events: EventWriter<operations::OperationStartedEvent>,
|
||||
selected_target_query: Query<&SelectedTarget, With<scene::PlayerShip>>,
|
||||
mut dispatch: ActionDispatch,
|
||||
) {
|
||||
let Ok(player_entity) = player_query.single() else {
|
||||
return;
|
||||
};
|
||||
let now_ms = dispatch.time.elapsed_secs_f64() * 1000.0;
|
||||
|
||||
for event in events.read() {
|
||||
bevy::log::info!("Action triggered: {:?}", event.action_type);
|
||||
|
||||
match event.action_type {
|
||||
ActionType::Undock => {
|
||||
operations::start_undocking(&mut commands, player_entity, &durations, &mut operation_events);
|
||||
operations::start_undocking(
|
||||
&mut commands,
|
||||
player_entity,
|
||||
&dispatch.durations,
|
||||
&mut dispatch.started,
|
||||
now_ms,
|
||||
);
|
||||
}
|
||||
ActionType::Approach => {
|
||||
// Get selected target
|
||||
if let Ok(selected) = selected_target_query.single() {
|
||||
operations::start_travel(&mut commands, player_entity, selected.name.clone(), &durations, &mut operation_events);
|
||||
operations::start_travel(
|
||||
&mut commands,
|
||||
player_entity,
|
||||
selected.name.clone(),
|
||||
&dispatch.durations,
|
||||
&mut dispatch.started,
|
||||
now_ms,
|
||||
);
|
||||
}
|
||||
}
|
||||
ActionType::Dock => {
|
||||
// TODO: Implement docking operation
|
||||
bevy::log::info!("Dock action triggered");
|
||||
if let Ok(selected) = selected_target_query.single() {
|
||||
match selected.kind {
|
||||
TargetKind::Station | TargetKind::HabitablePlanet => {
|
||||
bevy::log::info!("Docking at {}", selected.name);
|
||||
dispatch.dock.write(flight::DockEvent {
|
||||
ship: player_entity,
|
||||
station: selected.entity,
|
||||
});
|
||||
}
|
||||
kind => {
|
||||
bevy::log::info!("Cannot dock at {:?} target", kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ActionType::StartMining => {
|
||||
// TODO: Implement mining operation
|
||||
bevy::log::info!("Start mining action triggered");
|
||||
}
|
||||
_ => {
|
||||
@@ -109,6 +140,29 @@ fn handle_action_triggered(
|
||||
}
|
||||
}
|
||||
|
||||
/// Bridge completed timed operations back into the docked ↔ flight state
|
||||
/// machine. Today only undocking is wired — when the timed undock completes it
|
||||
/// fires the [`UndockEvent`] consumed by [`flight::handle_undock`]. Other
|
||||
/// operation kinds are logged for future work.
|
||||
fn complete_operations(
|
||||
mut completed: EventReader<operations::OperationCompletedEvent>,
|
||||
docked: Res<DockedState>,
|
||||
mut undock_events: EventWriter<UndockEvent>,
|
||||
) {
|
||||
for event in completed.read() {
|
||||
bevy::log::info!(
|
||||
"Operation completed: {:?} on entity {:?}",
|
||||
event.kind,
|
||||
event.entity
|
||||
);
|
||||
if let operations::OperationKind::Undocking = event.kind {
|
||||
undock_events.write(UndockEvent {
|
||||
station_entity: docked.station_entity.unwrap_or(Entity::PLACEHOLDER),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add Targetable components to spawned POIs (stations and asteroid belts)
|
||||
/// so they can be selected by the target selection system.
|
||||
fn add_targetable_to_pois(
|
||||
|
||||
Reference in New Issue
Block a user