prototypes/life: ui buttons: play, pause, step, quit

main
Elijah Voigt 1 month ago
parent 59996c9c86
commit 53aaf8963a

@ -1,5 +1,6 @@
// TODO: Rearchitected so it's Cell and Coordiantes not Cell { position { coordiantes } } // TODO: Rearchitected so it's Cell and Coordiantes not Cell { position { coordiantes } }
use bevy::picking::hover::Hovered;
use engine::*; use engine::*;
const GREY_TILE: &str = "tileGrey_01.png"; const GREY_TILE: &str = "tileGrey_01.png";
@ -25,6 +26,7 @@ fn main() {
.init_resource::<Coordinates>() .init_resource::<Coordinates>()
.init_state::<SimulationState>() .init_state::<SimulationState>()
.add_message::<Lifecycle>() .add_message::<Lifecycle>()
.add_message::<SimulationState>()
.add_systems(Startup, setup) .add_systems(Startup, setup)
.add_systems( .add_systems(
Update, Update,
@ -43,6 +45,14 @@ fn main() {
Update, Update,
simulation_step.run_if(input_just_pressed(KeyCode::Space)), 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::<SimulationState>),
)
.add_systems(Update, cell_lifecycle.run_if(on_message::<Lifecycle>)) .add_systems(Update, cell_lifecycle.run_if(on_message::<Lifecycle>))
.add_observer(on_add_ui_button) .add_observer(on_add_ui_button)
.add_observer(on_add_coordinates) .add_observer(on_add_coordinates)
@ -86,6 +96,7 @@ fn on_add_ui_button(
.entity(trigger.entity) .entity(trigger.entity)
.insert(( .insert((
Button, Button,
Hovered::default(),
BackgroundColor(GRAY.into()), BackgroundColor(GRAY.into()),
ImageNode { ImageNode {
image: server.load(GREY_TILE), image: server.load(GREY_TILE),
@ -130,14 +141,33 @@ fn setup(mut commands: Commands) {
Transform::default(), Transform::default(),
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(UiButton::Power); parent.spawn(UiButton::Power).observe(shutdown);
parent.spawn(UiButton::Pause); parent.spawn(UiButton::Pause).observe(pause_sim);
parent.spawn(UiButton::Step); parent.spawn(UiButton::Step).observe(step_sim);
parent.spawn(UiButton::Play); parent.spawn(UiButton::Play).observe(play_sim);
parent.spawn(UiButton::ZoomOut); parent.spawn(UiButton::ZoomOut).observe(zoom_out);
parent.spawn(UiButton::ZoomIn); parent.spawn(UiButton::ZoomIn).observe(zoom_in);
}); });
fn shutdown(_trigger: On<Pointer<Press>>, mut writer: MessageWriter<AppExit>) {
writer.write(AppExit::Success);
}
fn pause_sim(_trigger: On<Pointer<Press>>, mut next: ResMut<NextState<SimulationState>>) {
next.set(SimulationState::Pause);
}
fn step_sim(_trigger: On<Pointer<Press>>, mut writer: MessageWriter<SimulationState>) {
writer.write(SimulationState::Step);
}
fn play_sim(_trigger: On<Pointer<Press>>, mut next: ResMut<NextState<SimulationState>>) {
next.set(SimulationState::Run);
}
fn zoom_out(trigger: On<Pointer<Press>>) {
todo!()
}
fn zoom_in(trigger: On<Pointer<Press>>) {
todo!()
}
// Spawn Coordiantes // Spawn Coordiantes
commands commands
.spawn((Transform::default(), Visibility::Visible)) .spawn((Transform::default(), Visibility::Visible))
@ -268,17 +298,20 @@ struct Cell;
// When left mouse clicked, spawn a cell at GridPosition // When left mouse clicked, spawn a cell at GridPosition
fn de_spawn_cells( fn de_spawn_cells(
mut commands: Commands,
coordinates: Res<Coordinates>, coordinates: Res<Coordinates>,
cells: Query<(Entity, &Coordinates), With<Cell>>, cells: Query<(Entity, &Coordinates), With<Cell>>,
mut lifecycle: MessageWriter<Lifecycle>,
hovered: Query<&Hovered>,
) { ) {
if let Some(e) = cells if hovered.iter().all(|Hovered(h)| !h) {
.iter() if let Some(e) = cells
.find_map(|(e, c)| (*coordinates == *c).then_some(e)) .iter()
{ .find_map(|(e, c)| (*coordinates == *c).then_some(e))
commands.entity(e).despawn(); {
} else { lifecycle.write(Lifecycle::Dead(e));
commands.spawn((coordinates.clone(), Cell)); } else {
lifecycle.write(Lifecycle::Alive(coordinates.clone()));
}
} }
} }
@ -292,12 +325,12 @@ fn assert_cell_uniqueness(q: Query<(Entity, &Coordinates), With<Cell>>) {
}) })
} }
#[derive(States, Debug, Default, Hash, PartialEq, Eq, Clone)] #[derive(States, Debug, Default, Hash, PartialEq, Eq, Clone, Message)]
enum SimulationState { enum SimulationState {
#[default] #[default]
Off, Pause,
Step,
Run, Run,
Step,
} }
/// Simulate the Game of Life Rules: /// Simulate the Game of Life Rules:
@ -407,8 +440,21 @@ fn cell_lifecycle(
commands.spawn((c.clone(), Cell)); commands.spawn((c.clone(), Cell));
} }
Lifecycle::Dead(e) => { Lifecycle::Dead(e) => {
// TODO: Maybe include the entity instead of the coordinates for Dead
commands.entity(*e).despawn(); commands.entity(*e).despawn();
} }
}) })
} }
// Run condition for running a system every `input` seconds
fn cooldown_secs(input: f32) -> impl FnMut(Local<Timer>, Res<Time>) -> bool + Clone
{
move |mut timer: Local<Timer>, time: Res<Time>| {
if *timer == Timer::default() {
*timer = Timer::from_seconds(input, TimerMode::Repeating);
} else {
timer.tick(time.delta());
}
timer.is_finished()
}
}

Loading…
Cancel
Save