From 25c03beb2dc9ea2872cf7b8aeb72dbd997abdab0 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Tue, 2 May 2023 21:28:37 -0700 Subject: [PATCH] Use bevy schedule for all UI --- src/main.rs | 260 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 111 deletions(-) diff --git a/src/main.rs b/src/main.rs index dcdedc1..d039dc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use bevy_ecs::{ system::{Commands, IntoSystem, Query, ReadOnlySystem, Res, ResMut, System}, }; use eframe::{ - egui::{self, CursorIcon, Painter, Response, Sense, Ui}, + egui::{self, CursorIcon, Painter, Response, Sense}, emath::{Pos2, Rect, RectTransform, Vec2}, epaint::{Color32, Hsva, Stroke}, }; @@ -21,7 +21,8 @@ fn main() { "sketchrs", options, Box::new(|_cc| Box::new(MyApp::default())), - ).unwrap(); + ) + .unwrap(); } #[derive(Clone, Copy, PartialEq, Resource)] @@ -390,12 +391,6 @@ fn paint_points( }); } -struct MyApp { - world: World, - show_entities_stage: Schedule, - show_sidebar_stage: Schedule, -} - fn init(mut commands: Commands) { let p1 = geometry::insert_point_at(&mut commands, (10., 30.)); let p2 = geometry::insert_point_at(&mut commands, (-20., 15.)); @@ -403,24 +398,25 @@ fn init(mut commands: Commands) { commands.spawn(Line::new(p1, p2)); } -impl Default for MyApp { - fn default() -> Self { - let mut world = World::default(); +#[derive(Resource)] +struct ContextRes(egui::Context); - world.init_resource::(); +impl Deref for ContextRes { + type Target = egui::Context; - let mut init_stage = Schedule::new(); - init_stage.add_system(init); - init_stage.run(&mut world); - - Self { - world, - show_entities_stage: Self::create_show_entities_stage(), - show_sidebar_stage: Self::create_show_sidebar_stage(), - } + fn deref(&self) -> &Self::Target { + &self.0 } } +#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] +#[system_set(base)] +pub enum ShowEntitiesStage { + Input, + Tools, + Paint, +} + #[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] #[system_set(base)] pub enum ScheduleSet { @@ -429,8 +425,40 @@ pub enum ScheduleSet { Paint, } -impl MyApp { - fn create_show_entities_stage() -> Schedule { +fn prepare(ctx: Res) { + ctx.request_repaint(); + ctx.set_visuals(egui::Visuals::dark()); +} + +fn toolbar<'a>( + ctx: Res, + selected: Query>, + mut commands: Commands, + mut tool: ResMut, +) { + egui::TopBottomPanel::top("top_panel").show(&**ctx, |ui| { + // ui.heading("sketchrs"); + let mut selected_tool = *tool; + ui.horizontal(|ui| { + ui.radio_value(&mut selected_tool, Tool::Select, "Select"); + ui.radio_value(&mut selected_tool, Tool::Move, "Move"); + ui.radio_value(&mut selected_tool, Tool::AddPoint, "Add Point"); + ui.radio_value(&mut selected_tool, Tool::AddLine, "Add Line"); + }); + if selected_tool != *tool { + *tool = selected_tool; + + for selected in selected.iter() { + commands.entity(selected).remove::(); + } + } + }); +} + +struct ShowEntitiesSchedule(Schedule); + +impl Default for ShowEntitiesSchedule { + fn default() -> Self { let mut schedule = Schedule::new(); schedule .configure_sets((ScheduleSet::Input, ScheduleSet::Tools, ScheduleSet::Paint).chain()); @@ -442,6 +470,7 @@ impl MyApp { move_tool.run_if(is_tool_active(Tool::Move)), add_point_tool.run_if(is_tool_active(Tool::AddPoint)), add_line_tool.run_if(is_tool_active(Tool::AddLine)), + add_relation_tool.run_if(is_tool_active(Tool::AddRelation)), ) .distributive_run_if(is_hovered) .in_base_set(ScheduleSet::Tools), @@ -449,111 +478,120 @@ impl MyApp { schedule.add_systems( (paint_lines, paint_points.after(paint_lines)).in_base_set(ScheduleSet::Paint), ); - schedule + Self(schedule) } +} - fn create_show_sidebar_stage() -> Schedule { - let mut schedule = Schedule::new(); - schedule - } +fn central_panel(mut world: &mut World, mut schedule: Local) { + let ctx = world.get_resource::().unwrap().0.clone(); + egui::CentralPanel::default() + .frame(egui::Frame::none()) + .show(&ctx, |ui| { + let sense = match *world.resource::() { + Tool::Move => Sense::drag(), + Tool::Select | Tool::AddPoint | Tool::AddLine | Tool::AddRelation => Sense::click(), + }; - fn show_toolbar(&mut self, ui: &mut Ui) { - ui.heading("sketchrs"); + let (response, painter) = ui.allocate_painter(ui.available_size(), sense); + let to_screen = RectTransform::from_to( + Rect::from_center_size(Pos2::ZERO, response.rect.size() / 2.0), + response.rect, + ); + world.insert_resource(ToScreen(to_screen)); + world.insert_resource(ResponseRes(response)); + world.insert_resource(PainterRes(painter)); - ui.horizontal(|ui| { - ui.label("Tool: "); + schedule.0.run(&mut world); - let tool = &mut *self.world.resource_mut::(); - - ui.selectable_value(tool, Tool::Select, "Select"); - ui.selectable_value(tool, Tool::Move, "Move"); - ui.selectable_value(tool, Tool::AddPoint, "+ Point"); - ui.selectable_value(tool, Tool::AddLine, "+ Line"); - ui.selectable_value(tool, Tool::AddRelation, "+ Relation"); + world.remove_resource::(); + world.remove_resource::(); + world.remove_resource::(); }); - } +} - fn show_entities(&mut self, ui: &mut Ui) { - let sense = match *self.world.resource::() { - Tool::Move => Sense::drag(), - Tool::Select | Tool::AddPoint | Tool::AddLine | Tool::AddRelation => Sense::click(), - }; - - let (response, painter) = ui.allocate_painter(ui.available_size(), sense); - let to_screen = ToScreen(RectTransform::from_to( - Rect::from_center_size(Pos2::ZERO, response.rect.size() / 2.0), - response.rect, - )); - self.world.insert_resource(to_screen); - self.world.insert_resource(ResponseRes(response)); - self.world.insert_resource(PainterRes(painter)); - - self.show_entities_stage.run(&mut self.world); - - self.world.remove_resource::(); - self.world.remove_resource::(); - self.world.remove_resource::(); - } - - fn show_side_panel(&mut self, ui: &mut Ui) { - let tool = *self.world.resource::(); - ui.vertical(|ui| match tool { - Tool::Select => { - let mut selected = self - .world - .query_filtered::<(Entity, Option<&Point>, Option<&Line>), With>(); - let mut count = 0; - selected.for_each(&self.world, |(id, point, line)| { - count += 1; - if point.is_some() { - ui.label(format!("Selected point {}", id.index())); - } else if line.is_some() { - ui.label(format!("Selected line {}", id.index())); +fn side_panel( + ctx: Res, + selected: Query<(Entity, Option<&Point>, Option<&Line>), With>, + tool: Res, +) { + egui::SidePanel::right("side_panel") + .resizable(true) + .default_width(150.0) + .width_range(80.0..=200.0) + .show(&**ctx, |ui| { + let tool = *tool; + ui.vertical(|ui| match tool { + Tool::Select => { + let mut count = 0; + selected.for_each(|(id, point, line)| { + count += 1; + if point.is_some() { + ui.label(format!("Selected point {}", id.index())); + } else if line.is_some() { + ui.label(format!("Selected line {}", id.index())); + } + }); + if count == 0 { + ui.label("No selection"); } - }); - if count == 0 { - ui.label("No selection"); } - } - Tool::AddRelation => { - let mut selected = self - .world - .query_filtered::<(Entity, Option<&Point>, Option<&Line>), With>(); - if let Some(first) = selected.iter(&self.world).next() { - } else { - ui.label("Select an entity to add a relation"); + Tool::AddRelation => { + if let Some(first) = selected.iter().next() { + } else { + ui.label("Select an entity to add a relation"); + } } - } - _ => { - ui.label(":)"); - } + _ => { + ui.label(":)"); + } + }); }); +} + +fn bottom_panel(ctx: Res) { + egui::TopBottomPanel::bottom("bottom_panel").show(&ctx, |ui| { + ui.horizontal(|ui| { + ui.label("Status:"); + }); + }); +} + +struct MyApp { + world: World, + update_schedule: Schedule, +} + +impl Default for MyApp { + fn default() -> Self { + Self::new() + } +} +impl MyApp { + fn new() -> Self { + let mut world = World::default(); + + world.init_resource::(); + + let mut init_sched = Schedule::new(); + init_sched.add_system(init); + init_sched.run(&mut world); + + let mut update = Schedule::default(); + update.add_systems((prepare, toolbar, side_panel, bottom_panel, central_panel).chain()); + + Self { + world, + update_schedule: update, + } } } impl eframe::App for MyApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - ctx.request_repaint(); - ctx.set_visuals(egui::Visuals::dark()); + self.world.insert_resource(ContextRes(ctx.clone())); - egui::TopBottomPanel::top("top_panel").show(ctx, |ui| self.show_toolbar(ui)); + self.update_schedule.run(&mut self.world); - egui::CentralPanel::default() - .frame(egui::Frame::none()) - .show(ctx, |ui| { - self.show_entities(ui); - }); - - egui::SidePanel::right("right_panel") - .resizable(true) - .default_width(150.0) - .width_range(80.0..=200.0) - .show(ctx, |ui| self.show_side_panel(ui)); - - egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| { - ui.horizontal(|ui| { - ui.label("Status: "); - }); - }); + self.world.remove_resource::(); } }