Use bevy schedule for all UI
This commit is contained in:
parent
d744525903
commit
25c03beb2d
260
src/main.rs
260
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::<Tool>();
|
||||
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<ContextRes>) {
|
||||
ctx.request_repaint();
|
||||
ctx.set_visuals(egui::Visuals::dark());
|
||||
}
|
||||
|
||||
fn toolbar<'a>(
|
||||
ctx: Res<ContextRes>,
|
||||
selected: Query<Entity, With<Selected>>,
|
||||
mut commands: Commands,
|
||||
mut tool: ResMut<Tool>,
|
||||
) {
|
||||
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::<Selected>();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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<ShowEntitiesSchedule>) {
|
||||
let ctx = world.get_resource::<ContextRes>().unwrap().0.clone();
|
||||
egui::CentralPanel::default()
|
||||
.frame(egui::Frame::none())
|
||||
.show(&ctx, |ui| {
|
||||
let sense = match *world.resource::<Tool>() {
|
||||
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::<Tool>();
|
||||
|
||||
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::<PainterRes>();
|
||||
world.remove_resource::<ResponseRes>();
|
||||
world.remove_resource::<ToScreen>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn show_entities(&mut self, ui: &mut Ui) {
|
||||
let sense = match *self.world.resource::<Tool>() {
|
||||
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::<PainterRes>();
|
||||
self.world.remove_resource::<ResponseRes>();
|
||||
self.world.remove_resource::<ToScreen>();
|
||||
}
|
||||
|
||||
fn show_side_panel(&mut self, ui: &mut Ui) {
|
||||
let tool = *self.world.resource::<Tool>();
|
||||
ui.vertical(|ui| match tool {
|
||||
Tool::Select => {
|
||||
let mut selected = self
|
||||
.world
|
||||
.query_filtered::<(Entity, Option<&Point>, Option<&Line>), With<Selected>>();
|
||||
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<ContextRes>,
|
||||
selected: Query<(Entity, Option<&Point>, Option<&Line>), With<Selected>>,
|
||||
tool: Res<Tool>,
|
||||
) {
|
||||
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<Selected>>();
|
||||
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<ContextRes>) {
|
||||
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::<Tool>();
|
||||
|
||||
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::<ContextRes>();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user