use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
input::mouse::{MouseButtonInput, MouseWheel},
prelude::*,
};
use bevy_iced::iced::{
self,
widget::{slider, text, text_input, Button, Column, Row},
Alignment, Style,
};
use bevy_iced::{IcedContext, IcedPlugin, IcedSettings};
use rand::random as rng;
#[derive(Clone, Event)]
enum UiMessage {
BoxRequested,
Scale(f32),
Text(String),
}
#[derive(Resource, Deref, DerefMut)]
pub struct UiActive(bool);
#[derive(Resource)]
pub struct UiData {
scale: f32,
text: String,
}
pub fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
present_mode: bevy_window::PresentMode::AutoNoVsync,
..Default::default()
}),
..Default::default()
}))
.add_plugins((
IcedPlugin::default(),
FrameTimeDiagnosticsPlugin,
LogDiagnosticsPlugin::default(),
))
.add_event::<UiMessage>()
.insert_resource(UiActive(true))
.insert_resource(UiData {
scale: 50.0,
text: "Welcome to Iced!".to_owned(),
})
.insert_resource(IcedSettings {
scale_factor: None,
theme: iced::Theme::Light,
style: Style {
text_color: iced::Color::from_rgb(0.0, 1.0, 1.0),
},
})
.add_systems(Startup, build_program)
.add_systems(
Update,
(tick, box_system, update_scale_factor, toggle_ui, ui_system),
)
.run();
}
fn build_program(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
}
fn tick(mut sprites: Query<&mut Sprite>, time: Res<Time>, data: Res<UiData>) {
let scale = data.scale;
for mut s in sprites.iter_mut() {
s.custom_size = Some(Vec2::new(scale, scale) * time.elapsed_seconds().sin().abs());
}
}
fn box_system(
mut commands: Commands,
mut messages: EventReader<UiMessage>,
mut data: ResMut<UiData>,
mut sprites: Query<&mut Sprite>,
) {
let pos = (Vec3::new(rng(), rng(), 0.0) - Vec3::new(0.5, 0.5, 0.0)) * 300.0;
for msg in messages.read() {
match msg {
UiMessage::BoxRequested => {
commands.spawn(SpriteBundle {
sprite: Sprite {
color: Color::rgba_u8(rng(), rng(), rng(), rng()),
custom_size: Some(Vec2::new(50.0, 50.0)),
..Default::default()
},
transform: Transform::from_translation(pos),
..Default::default()
});
}
UiMessage::Scale(new_scale) => {
data.scale = *new_scale;
}
UiMessage::Text(s) => {
data.text.clone_from(s);
for mut i in &mut sprites.iter_mut() {
i.color = Color::rgba_u8(rng(), rng(), rng(), rng());
}
}
}
}
}
fn update_scale_factor(
mut wheel: EventReader<MouseWheel>,
mut iced_settings: ResMut<IcedSettings>,
) {
if wheel.is_empty() {
return;
}
for event in wheel.read() {
let scale_factor =
(iced_settings.scale_factor.unwrap_or(1.0) + (event.y / 10.0) as f64).max(1.0);
iced_settings.set_scale_factor(scale_factor);
}
}
fn toggle_ui(mut buttons: EventReader<MouseButtonInput>, mut ui_active: ResMut<UiActive>) {
for ev in buttons.read() {
if ev.button == MouseButton::Right {
**ui_active = !**ui_active;
}
}
}
fn ui_system(
mut ctx: IcedContext<UiMessage>,
data: Res<UiData>,
sprites: Query<(&Sprite,)>,
ui_active: Res<UiActive>,
) {
if !**ui_active {
return;
}
let row = Row::new()
.spacing(10)
.align_items(Alignment::Center)
.push(Button::new(text("Request box")).on_press(UiMessage::BoxRequested))
.push(text(format!(
"{} boxes (amplitude: {})",
sprites.iter().len(),
data.scale
)));
let edit = text_input("", &data.text).on_input(UiMessage::Text);
let column = Column::new()
.align_items(Alignment::Center)
.spacing(10)
.push(edit)
.push(slider(0.0..=100.0, data.scale, UiMessage::Scale))
.push(row);
ctx.display(column);
}