You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.3 KiB
Rust

use bevy::input_focus::tab_navigation::TabGroup;
use engine::theme::ThemedText;
use super::*;
/// Debug UI for Tetris
/// Some overlap with more general purpose debug tools,
/// but built one-off because of the changse to UI in Bevy 0.17
pub struct DebugPlugin;
// Debugging wish-list:
// - Bounding boxes around entities
// - Toggleable in UI
// - Cursor at the center of the world
// - Toggleable in UI
// - Show current state(s) in UI
impl Plugin for DebugPlugin {
fn build(&self, app: &mut App) {
app
.init_state::<DebugState>()
.add_systems(Startup, setup_ui)
.add_systems(Update,
// Logging state transitions
(
log_transition::<DebugState>.run_if(state_changed::<DebugState>),
log_transition::<Loading>.run_if(state_changed::<Loading>),
log_transition::<GameState>.run_if(state_changed::<GameState>),
))
.add_systems(Update, toggle_debug.run_if(input_just_pressed(KeyCode::F12)))
.add_systems(Update,
(
toggle_state_visibility::<DebugState>,
sync_state_to_ui::<DebugState>,
).run_if(state_changed::<DebugState>)
);
}
}
/// Tracks if the game is in debug mode
#[derive(States, Default, Clone, Eq, Debug, PartialEq, Hash, Component)]
pub struct DebugState(bool);
impl From<bool> for DebugState {
fn from(b: bool) -> Self {
DebugState(b)
}
}
impl fmt::Display for DebugState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "DebugState {}", self.0)
}
}
/// Setup the debugger UI
fn setup_ui(
mut commands: Commands,
) {
commands.spawn((
Node {
display: Display::Flex,
flex_direction: FlexDirection::Row,
align_items: AlignItems::Center,
justify_content: JustifyContent::Start,
column_gap: px(8),
..default()
},
children![
(Text::new("debugger:"), ThemedText),
(toggle_switch((),), observe(checkbox_self_update), observe(debug_toggle)),
],
));
commands.spawn((
Node {
bottom: px(0.0),
left: px(0.0),
position_type: PositionType::Absolute,
flex_direction: FlexDirection::Column,
..default()
},
DebugState(true),
children![
(Text::new("DebugState State"), SyncState::<DebugState>::default()),
(Text::new("Loading State"), SyncState::<Loading>::default()),
(Text::new("Game State"), SyncState::<GameState>::default()),
]
));
}
/// Logs all state transitions for state T
fn log_transition<T: States + PartialEq + Clone>(
curr: Res<State<T>>,
mut prev: Local<Option<T>>,
) {
debug_assert!(Some(curr.get().clone()) != *prev);
info!("State Change:: {:?} -> {:?}", *prev, *curr);
*prev = Some(curr.get().clone());
}
/// Toggle the debug state when a key is pressed
fn toggle_debug(
curr: Res<State<DebugState>>,
mut next: ResMut<NextState<DebugState>>,
) {
next.set(DebugState(!curr.get().0));
}
fn debug_toggle(event: On<ValueChange<bool>>, mut next_state: ResMut<NextState<DebugState>>) {
info!("Debug State Toggled: {:?}", event.event().value);
next_state.set(event.event().value.into());
}