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
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());
|
|
}
|