From 53aaf8963a500916ddc092e38ebe691e17328d01 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Tue, 9 Jun 2026 17:02:51 -0700 Subject: [PATCH] prototypes/life: ui buttons: play, pause, step, quit --- prototypes/src/bin/life.rs | 82 +++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/prototypes/src/bin/life.rs b/prototypes/src/bin/life.rs index 337054e..3e893d8 100644 --- a/prototypes/src/bin/life.rs +++ b/prototypes/src/bin/life.rs @@ -1,5 +1,6 @@ // TODO: Rearchitected so it's Cell and Coordiantes not Cell { position { coordiantes } } +use bevy::picking::hover::Hovered; use engine::*; const GREY_TILE: &str = "tileGrey_01.png"; @@ -25,6 +26,7 @@ fn main() { .init_resource::() .init_state::() .add_message::() + .add_message::() .add_systems(Startup, setup) .add_systems( Update, @@ -43,6 +45,14 @@ fn main() { Update, simulation_step.run_if(input_just_pressed(KeyCode::Space)), ) + .add_systems( + Update, + simulation_step.run_if(in_state(SimulationState::Run)).run_if(cooldown_secs(1.0)), + ) + .add_systems( + Update, + simulation_step.run_if(on_message::), + ) .add_systems(Update, cell_lifecycle.run_if(on_message::)) .add_observer(on_add_ui_button) .add_observer(on_add_coordinates) @@ -86,6 +96,7 @@ fn on_add_ui_button( .entity(trigger.entity) .insert(( Button, + Hovered::default(), BackgroundColor(GRAY.into()), ImageNode { image: server.load(GREY_TILE), @@ -130,14 +141,33 @@ fn setup(mut commands: Commands) { Transform::default(), )) .with_children(|parent| { - parent.spawn(UiButton::Power); - parent.spawn(UiButton::Pause); - parent.spawn(UiButton::Step); - parent.spawn(UiButton::Play); - parent.spawn(UiButton::ZoomOut); - parent.spawn(UiButton::ZoomIn); + parent.spawn(UiButton::Power).observe(shutdown); + parent.spawn(UiButton::Pause).observe(pause_sim); + parent.spawn(UiButton::Step).observe(step_sim); + parent.spawn(UiButton::Play).observe(play_sim); + parent.spawn(UiButton::ZoomOut).observe(zoom_out); + parent.spawn(UiButton::ZoomIn).observe(zoom_in); }); + fn shutdown(_trigger: On>, mut writer: MessageWriter) { + writer.write(AppExit::Success); + } + fn pause_sim(_trigger: On>, mut next: ResMut>) { + next.set(SimulationState::Pause); + } + fn step_sim(_trigger: On>, mut writer: MessageWriter) { + writer.write(SimulationState::Step); + } + fn play_sim(_trigger: On>, mut next: ResMut>) { + next.set(SimulationState::Run); + } + fn zoom_out(trigger: On>) { + todo!() + } + fn zoom_in(trigger: On>) { + todo!() + } + // Spawn Coordiantes commands .spawn((Transform::default(), Visibility::Visible)) @@ -268,17 +298,20 @@ struct Cell; // When left mouse clicked, spawn a cell at GridPosition fn de_spawn_cells( - mut commands: Commands, coordinates: Res, cells: Query<(Entity, &Coordinates), With>, + mut lifecycle: MessageWriter, + hovered: Query<&Hovered>, ) { - if let Some(e) = cells - .iter() - .find_map(|(e, c)| (*coordinates == *c).then_some(e)) - { - commands.entity(e).despawn(); - } else { - commands.spawn((coordinates.clone(), Cell)); + if hovered.iter().all(|Hovered(h)| !h) { + if let Some(e) = cells + .iter() + .find_map(|(e, c)| (*coordinates == *c).then_some(e)) + { + lifecycle.write(Lifecycle::Dead(e)); + } else { + lifecycle.write(Lifecycle::Alive(coordinates.clone())); + } } } @@ -292,12 +325,12 @@ fn assert_cell_uniqueness(q: Query<(Entity, &Coordinates), With>) { }) } -#[derive(States, Debug, Default, Hash, PartialEq, Eq, Clone)] +#[derive(States, Debug, Default, Hash, PartialEq, Eq, Clone, Message)] enum SimulationState { #[default] - Off, - Step, + Pause, Run, + Step, } /// Simulate the Game of Life Rules: @@ -407,8 +440,21 @@ fn cell_lifecycle( commands.spawn((c.clone(), Cell)); } Lifecycle::Dead(e) => { - // TODO: Maybe include the entity instead of the coordinates for Dead commands.entity(*e).despawn(); } }) } + +// Run condition for running a system every `input` seconds +fn cooldown_secs(input: f32) -> impl FnMut(Local, Res