Use bevy schedule for all UI
This commit is contained in:
parent
d744525903
commit
25c03beb2d
210
src/main.rs
210
src/main.rs
@ -5,7 +5,7 @@ use bevy_ecs::{
|
|||||||
system::{Commands, IntoSystem, Query, ReadOnlySystem, Res, ResMut, System},
|
system::{Commands, IntoSystem, Query, ReadOnlySystem, Res, ResMut, System},
|
||||||
};
|
};
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{self, CursorIcon, Painter, Response, Sense, Ui},
|
egui::{self, CursorIcon, Painter, Response, Sense},
|
||||||
emath::{Pos2, Rect, RectTransform, Vec2},
|
emath::{Pos2, Rect, RectTransform, Vec2},
|
||||||
epaint::{Color32, Hsva, Stroke},
|
epaint::{Color32, Hsva, Stroke},
|
||||||
};
|
};
|
||||||
@ -21,7 +21,8 @@ fn main() {
|
|||||||
"sketchrs",
|
"sketchrs",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::new(MyApp::default())),
|
Box::new(|_cc| Box::new(MyApp::default())),
|
||||||
).unwrap();
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Resource)]
|
#[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) {
|
fn init(mut commands: Commands) {
|
||||||
let p1 = geometry::insert_point_at(&mut commands, (10., 30.));
|
let p1 = geometry::insert_point_at(&mut commands, (10., 30.));
|
||||||
let p2 = geometry::insert_point_at(&mut commands, (-20., 15.));
|
let p2 = geometry::insert_point_at(&mut commands, (-20., 15.));
|
||||||
@ -403,22 +398,23 @@ fn init(mut commands: Commands) {
|
|||||||
commands.spawn(Line::new(p1, p2));
|
commands.spawn(Line::new(p1, p2));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MyApp {
|
#[derive(Resource)]
|
||||||
fn default() -> Self {
|
struct ContextRes(egui::Context);
|
||||||
let mut world = World::default();
|
|
||||||
|
|
||||||
world.init_resource::<Tool>();
|
impl Deref for ContextRes {
|
||||||
|
type Target = egui::Context;
|
||||||
|
|
||||||
let mut init_stage = Schedule::new();
|
fn deref(&self) -> &Self::Target {
|
||||||
init_stage.add_system(init);
|
&self.0
|
||||||
init_stage.run(&mut world);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
world,
|
|
||||||
show_entities_stage: Self::create_show_entities_stage(),
|
|
||||||
show_sidebar_stage: Self::create_show_sidebar_stage(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[system_set(base)]
|
||||||
|
pub enum ShowEntitiesStage {
|
||||||
|
Input,
|
||||||
|
Tools,
|
||||||
|
Paint,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -429,8 +425,40 @@ pub enum ScheduleSet {
|
|||||||
Paint,
|
Paint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MyApp {
|
fn prepare(ctx: Res<ContextRes>) {
|
||||||
fn create_show_entities_stage() -> Schedule {
|
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();
|
let mut schedule = Schedule::new();
|
||||||
schedule
|
schedule
|
||||||
.configure_sets((ScheduleSet::Input, ScheduleSet::Tools, ScheduleSet::Paint).chain());
|
.configure_sets((ScheduleSet::Input, ScheduleSet::Tools, ScheduleSet::Paint).chain());
|
||||||
@ -442,6 +470,7 @@ impl MyApp {
|
|||||||
move_tool.run_if(is_tool_active(Tool::Move)),
|
move_tool.run_if(is_tool_active(Tool::Move)),
|
||||||
add_point_tool.run_if(is_tool_active(Tool::AddPoint)),
|
add_point_tool.run_if(is_tool_active(Tool::AddPoint)),
|
||||||
add_line_tool.run_if(is_tool_active(Tool::AddLine)),
|
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)
|
.distributive_run_if(is_hovered)
|
||||||
.in_base_set(ScheduleSet::Tools),
|
.in_base_set(ScheduleSet::Tools),
|
||||||
@ -449,61 +478,52 @@ impl MyApp {
|
|||||||
schedule.add_systems(
|
schedule.add_systems(
|
||||||
(paint_lines, paint_points.after(paint_lines)).in_base_set(ScheduleSet::Paint),
|
(paint_lines, paint_points.after(paint_lines)).in_base_set(ScheduleSet::Paint),
|
||||||
);
|
);
|
||||||
schedule
|
Self(schedule)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_show_sidebar_stage() -> Schedule {
|
fn central_panel(mut world: &mut World, mut schedule: Local<ShowEntitiesSchedule>) {
|
||||||
let mut schedule = Schedule::new();
|
let ctx = world.get_resource::<ContextRes>().unwrap().0.clone();
|
||||||
schedule
|
egui::CentralPanel::default()
|
||||||
}
|
.frame(egui::Frame::none())
|
||||||
|
.show(&ctx, |ui| {
|
||||||
fn show_toolbar(&mut self, ui: &mut Ui) {
|
let sense = match *world.resource::<Tool>() {
|
||||||
ui.heading("sketchrs");
|
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label("Tool: ");
|
|
||||||
|
|
||||||
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");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show_entities(&mut self, ui: &mut Ui) {
|
|
||||||
let sense = match *self.world.resource::<Tool>() {
|
|
||||||
Tool::Move => Sense::drag(),
|
Tool::Move => Sense::drag(),
|
||||||
Tool::Select | Tool::AddPoint | Tool::AddLine | Tool::AddRelation => Sense::click(),
|
Tool::Select | Tool::AddPoint | Tool::AddLine | Tool::AddRelation => Sense::click(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (response, painter) = ui.allocate_painter(ui.available_size(), sense);
|
let (response, painter) = ui.allocate_painter(ui.available_size(), sense);
|
||||||
let to_screen = ToScreen(RectTransform::from_to(
|
let to_screen = RectTransform::from_to(
|
||||||
Rect::from_center_size(Pos2::ZERO, response.rect.size() / 2.0),
|
Rect::from_center_size(Pos2::ZERO, response.rect.size() / 2.0),
|
||||||
response.rect,
|
response.rect,
|
||||||
));
|
);
|
||||||
self.world.insert_resource(to_screen);
|
world.insert_resource(ToScreen(to_screen));
|
||||||
self.world.insert_resource(ResponseRes(response));
|
world.insert_resource(ResponseRes(response));
|
||||||
self.world.insert_resource(PainterRes(painter));
|
world.insert_resource(PainterRes(painter));
|
||||||
|
|
||||||
self.show_entities_stage.run(&mut self.world);
|
schedule.0.run(&mut world);
|
||||||
|
|
||||||
self.world.remove_resource::<PainterRes>();
|
world.remove_resource::<PainterRes>();
|
||||||
self.world.remove_resource::<ResponseRes>();
|
world.remove_resource::<ResponseRes>();
|
||||||
self.world.remove_resource::<ToScreen>();
|
world.remove_resource::<ToScreen>();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_side_panel(&mut self, ui: &mut Ui) {
|
fn side_panel(
|
||||||
let tool = *self.world.resource::<Tool>();
|
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 {
|
ui.vertical(|ui| match tool {
|
||||||
Tool::Select => {
|
Tool::Select => {
|
||||||
let mut selected = self
|
|
||||||
.world
|
|
||||||
.query_filtered::<(Entity, Option<&Point>, Option<&Line>), With<Selected>>();
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
selected.for_each(&self.world, |(id, point, line)| {
|
selected.for_each(|(id, point, line)| {
|
||||||
count += 1;
|
count += 1;
|
||||||
if point.is_some() {
|
if point.is_some() {
|
||||||
ui.label(format!("Selected point {}", id.index()));
|
ui.label(format!("Selected point {}", id.index()));
|
||||||
@ -516,10 +536,7 @@ impl MyApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tool::AddRelation => {
|
Tool::AddRelation => {
|
||||||
let mut selected = self
|
if let Some(first) = selected.iter().next() {
|
||||||
.world
|
|
||||||
.query_filtered::<(Entity, Option<&Point>, Option<&Line>), With<Selected>>();
|
|
||||||
if let Some(first) = selected.iter(&self.world).next() {
|
|
||||||
} else {
|
} else {
|
||||||
ui.label("Select an entity to add a relation");
|
ui.label("Select an entity to add a relation");
|
||||||
}
|
}
|
||||||
@ -528,32 +545,53 @@ impl MyApp {
|
|||||||
ui.label(":)");
|
ui.label(":)");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| self.show_toolbar(ui));
|
|
||||||
|
|
||||||
egui::CentralPanel::default()
|
|
||||||
.frame(egui::Frame::none())
|
|
||||||
.show(ctx, |ui| {
|
|
||||||
self.show_entities(ui);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
egui::SidePanel::right("right_panel")
|
fn bottom_panel(ctx: Res<ContextRes>) {
|
||||||
.resizable(true)
|
egui::TopBottomPanel::bottom("bottom_panel").show(&ctx, |ui| {
|
||||||
.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.horizontal(|ui| {
|
||||||
ui.label("Status:");
|
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) {
|
||||||
|
self.world.insert_resource(ContextRes(ctx.clone()));
|
||||||
|
|
||||||
|
self.update_schedule.run(&mut self.world);
|
||||||
|
|
||||||
|
self.world.remove_resource::<ContextRes>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user