|
|
|
@ -1,13 +1,8 @@
|
|
|
|
use bevy::{
|
|
|
|
use bevy::{feathers::theme::ThemeProps, ui::InteractionDisabled};
|
|
|
|
asset::{AssetPath, HandleTemplate},
|
|
|
|
|
|
|
|
audio::AudioPlayerTemplate,
|
|
|
|
|
|
|
|
mesh::Mesh2dTemplate,
|
|
|
|
|
|
|
|
sprite_render::MeshMaterial2dTemplate,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
use engine::*;
|
|
|
|
use engine::*;
|
|
|
|
|
|
|
|
|
|
|
|
const TILE: &str = "tileGrey_01.png";
|
|
|
|
const TILE: &str = "tileGrey_01.png";
|
|
|
|
const FRAME_DURATION: f32 = 0.5;
|
|
|
|
const SIM_FRAME_DURATION: f32 = 0.5;
|
|
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
fn main() {
|
|
|
|
App::new()
|
|
|
|
App::new()
|
|
|
|
@ -20,6 +15,7 @@ fn main() {
|
|
|
|
.init_resource::<CellAssets>()
|
|
|
|
.init_resource::<CellAssets>()
|
|
|
|
.init_resource::<Panning>()
|
|
|
|
.init_resource::<Panning>()
|
|
|
|
.insert_resource(ClearColor(WHITE.into()))
|
|
|
|
.insert_resource(ClearColor(WHITE.into()))
|
|
|
|
|
|
|
|
.insert_resource(UiTheme(create_light_theme()))
|
|
|
|
.init_state::<SimulationPlayback>()
|
|
|
|
.init_state::<SimulationPlayback>()
|
|
|
|
.init_state::<AudioPlayback>()
|
|
|
|
.init_state::<AudioPlayback>()
|
|
|
|
.add_message::<Lifecycle>()
|
|
|
|
.add_message::<Lifecycle>()
|
|
|
|
@ -58,27 +54,19 @@ fn main() {
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
simulation_step
|
|
|
|
simulation_step
|
|
|
|
.run_if(in_state(SimulationPlayback::Run))
|
|
|
|
.run_if(in_state(SimulationPlayback::Run))
|
|
|
|
.run_if(cooldown_secs(FRAME_DURATION)),
|
|
|
|
.run_if(cooldown_secs(SIM_FRAME_DURATION)),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
simulation_step.run_if(state_changed::<SimulationPlayback>),
|
|
|
|
simulation_step.run_if(state_changed::<SimulationPlayback>),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(
|
|
|
|
// TODO: Visualize audio play/mute buttons enable/disable
|
|
|
|
Update,
|
|
|
|
.add_systems(Update, toggle_interactive::<SimulationPlayback>)
|
|
|
|
visualize_ui_state.run_if(on_message::<Pointer<Click>>),
|
|
|
|
.add_systems(Update, toggle_interactive::<AudioPlayback>)
|
|
|
|
)
|
|
|
|
// TODO Visualize simulation run/pause buttons enable/disable
|
|
|
|
.add_systems(Update, cell_lifecycle.run_if(on_message::<Lifecycle>))
|
|
|
|
.add_systems(Update, cell_lifecycle.run_if(on_message::<Lifecycle>))
|
|
|
|
.add_systems(Update, mouse_pan.run_if(on_message::<MouseMotion>))
|
|
|
|
.add_systems(Update, mouse_pan.run_if(on_message::<MouseMotion>))
|
|
|
|
.add_systems(Update, set_pan_state)
|
|
|
|
.add_systems(Update, set_pan_state)
|
|
|
|
.add_systems(
|
|
|
|
|
|
|
|
Update,
|
|
|
|
|
|
|
|
toggle_state_entities::<SimulationPlayback>.run_if(state_changed::<SimulationPlayback>),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.add_systems(
|
|
|
|
|
|
|
|
Update,
|
|
|
|
|
|
|
|
toggle_state_entities::<AudioPlayback>.run_if(state_changed::<AudioPlayback>),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.run();
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -176,13 +164,13 @@ fn the_ui() -> impl Scene {
|
|
|
|
writer.write(AppExit::Success);
|
|
|
|
writer.write(AppExit::Success);
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
ui_button(UiButton::Pause)
|
|
|
|
ui_button(UiButton::Pause)
|
|
|
|
SimulationPlayback::Run
|
|
|
|
SimulationPlayback::Pause
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<SimulationPlayback>>| {
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<SimulationPlayback>>| {
|
|
|
|
// Set simulation state
|
|
|
|
// Set simulation state
|
|
|
|
next.set(SimulationPlayback::Pause);
|
|
|
|
next.set(SimulationPlayback::Pause);
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
ui_button(UiButton::Play)
|
|
|
|
ui_button(UiButton::Play)
|
|
|
|
SimulationPlayback::Pause
|
|
|
|
SimulationPlayback::Run
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<SimulationPlayback>>| {
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<SimulationPlayback>>| {
|
|
|
|
// Set simulation state
|
|
|
|
// Set simulation state
|
|
|
|
next.set(SimulationPlayback::Run);
|
|
|
|
next.set(SimulationPlayback::Run);
|
|
|
|
@ -210,12 +198,12 @@ fn the_ui() -> impl Scene {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
ui_button(UiButton::MuteAudio)
|
|
|
|
ui_button(UiButton::MuteAudio)
|
|
|
|
AudioPlayback::Play
|
|
|
|
AudioPlayback::Mute
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<AudioPlayback>>| {
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<AudioPlayback>>| {
|
|
|
|
next.set(AudioPlayback::Mute);
|
|
|
|
next.set(AudioPlayback::Mute);
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
ui_button(UiButton::PlayAudio)
|
|
|
|
ui_button(UiButton::PlayAudio)
|
|
|
|
AudioPlayback::Mute
|
|
|
|
AudioPlayback::Play
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<AudioPlayback>>| {
|
|
|
|
on(|_: On<Activate>, mut next: ResMut<NextState<AudioPlayback>>| {
|
|
|
|
next.set(AudioPlayback::Play);
|
|
|
|
next.set(AudioPlayback::Play);
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
@ -506,7 +494,8 @@ fn new_cell(
|
|
|
|
let c = Coordinates { x, y };
|
|
|
|
let c = Coordinates { x, y };
|
|
|
|
|
|
|
|
|
|
|
|
let volume = {
|
|
|
|
let volume = {
|
|
|
|
if *sim_state.get() == SimulationPlayback::Run && *audio_state.get() == AudioPlayback::Play {
|
|
|
|
if *sim_state.get() == SimulationPlayback::Run && *audio_state.get() == AudioPlayback::Play
|
|
|
|
|
|
|
|
{
|
|
|
|
let ratio = 1.0 / (sinks.count() + 1) as f32;
|
|
|
|
let ratio = 1.0 / (sinks.count() + 1) as f32;
|
|
|
|
Volume::Linear(ratio)
|
|
|
|
Volume::Linear(ratio)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -565,23 +554,6 @@ fn cooldown_secs(input: f32) -> impl FnMut(Local<Timer>, Res<Time>) -> bool + Cl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Visualize active state (run vs pause):
|
|
|
|
|
|
|
|
// If in Run state, keep Run button light, or blinking or outlined or something.
|
|
|
|
|
|
|
|
// If in Pause state, keep Pauses button light, or blinking or outlined or something.
|
|
|
|
|
|
|
|
fn visualize_ui_state(
|
|
|
|
|
|
|
|
mut query: Query<(&UiButton, &mut Outline)>,
|
|
|
|
|
|
|
|
state: Res<State<SimulationPlayback>>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
query.iter_mut().for_each(|(uib, mut o)| {
|
|
|
|
|
|
|
|
o.color = match (uib, state.get()) {
|
|
|
|
|
|
|
|
(UiButton::Pause, SimulationPlayback::Pause) => BLACK.into(),
|
|
|
|
|
|
|
|
(UiButton::Step, SimulationPlayback::Step) => BLACK.into(),
|
|
|
|
|
|
|
|
(UiButton::Play, SimulationPlayback::Run) => BLACK.into(),
|
|
|
|
|
|
|
|
_ => Color::NONE,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Scale grid with background?
|
|
|
|
// Scale grid with background?
|
|
|
|
// Pan camera: click and drag
|
|
|
|
// Pan camera: click and drag
|
|
|
|
|
|
|
|
|
|
|
|
@ -769,17 +741,41 @@ fn is_panning(panning: Res<Panning>) -> bool {
|
|
|
|
panning.0
|
|
|
|
panning.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn toggle_state_entities<S: States + Component>(
|
|
|
|
// TODO: Do not spawn cell when clicking UI
|
|
|
|
mut query: Query<(&mut Visibility, &S)>,
|
|
|
|
|
|
|
|
state: Res<State<S>>,
|
|
|
|
// This may or may not be an eye sore
|
|
|
|
|
|
|
|
fn create_light_theme() -> ThemeProps {
|
|
|
|
|
|
|
|
ThemeProps {
|
|
|
|
|
|
|
|
color: create_dark_theme()
|
|
|
|
|
|
|
|
.color
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.map(|(token, color)| {
|
|
|
|
|
|
|
|
let c = match color {
|
|
|
|
|
|
|
|
Color::Oklcha(oklcha) => Color::Oklcha(Oklcha {
|
|
|
|
|
|
|
|
lightness: oklcha.lightness + 0.1,
|
|
|
|
|
|
|
|
..*oklcha
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
x => {
|
|
|
|
|
|
|
|
info!("Passing along color theme {:?} {:?}", token, x);
|
|
|
|
|
|
|
|
*x
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
(token.clone(), c)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn toggle_interactive<T: Component + States + PartialEq>(
|
|
|
|
|
|
|
|
q: Query<(Entity, &T)>,
|
|
|
|
|
|
|
|
s: Res<State<T>>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
query.iter_mut().for_each(|(mut v, s)| {
|
|
|
|
q.iter().for_each(|(e, c)| {
|
|
|
|
*v = if state.get() == s {
|
|
|
|
if c == s.get() {
|
|
|
|
Visibility::Inherited
|
|
|
|
commands.entity(e).insert(InteractionDisabled);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Visibility::Hidden
|
|
|
|
commands.entity(e).remove::<InteractionDisabled>();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Do not spawn cell when clicking UI
|
|
|
|
|
|
|
|
|