update dependencies

This commit is contained in:
Alex Mikhalev 2023-05-01 17:57:17 -07:00
parent fdd93fa7e8
commit fc550267da
4 changed files with 1823 additions and 1017 deletions

2564
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,16 +6,16 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
argmin = { version = "0.5.1", features = ["nalgebra"] } argmin = { version = "0.8.1", features = [] }
bevy_ecs = "0.7.0" argmin-math = { version = "0.3.0", features = ["nalgebra_0_32"] }
eframe = { version = "0.18.0", features = [] } bevy_ecs = "0.10.1"
eframe = { version = "0.21.3", features = [] }
indexmap = "1.8.1" indexmap = "1.8.1"
iyes_loopless = "0.5.1" levenberg-marquardt = "0.13.0"
levenberg-marquardt = "0.12.0" nalgebra = "0.32.0"
nalgebra = "0.30.1" nalgebra-sparse = "0.9.0"
nalgebra-sparse = "0.6.0"
nohash-hasher = "0.2.0" nohash-hasher = "0.2.0"
[dev-dependencies] [dev-dependencies]
criterion = "0.3.5" criterion = "0.4.0"

View File

@ -62,9 +62,9 @@ pub struct Circle {
pub fn insert_point_at(commands: &mut Commands, point: impl Into<PointPos>) -> PointId { pub fn insert_point_at(commands: &mut Commands, point: impl Into<PointPos>) -> PointId {
let point = point.into(); let point = point.into();
let x = commands.spawn().insert(Var::new_free(point.x)).id(); let x = commands.spawn(Var::new_free(point.x)).id();
let y = commands.spawn().insert(Var::new_free(point.y)).id(); let y = commands.spawn(Var::new_free(point.y)).id();
commands.spawn().insert(Point::new(x, y)).id() commands.spawn(Point::new(x, y)).id()
} }
// TODO: figure out generic for this // TODO: figure out generic for this

View File

@ -1,14 +1,15 @@
use std::ops::{Deref, DerefMut};
use bevy_ecs::{ use bevy_ecs::{
prelude::*, prelude::*,
system::{Commands, IntoSystem, Query, 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, Ui},
emath::{Pos2, Rect, RectTransform, Vec2}, emath::{Pos2, Rect, RectTransform, Vec2},
epaint::{color::Hsva, Color32, Stroke}, epaint::{Color32, Hsva, Stroke},
}; };
use geometry::{Line, LinePosQuery, Point, PointId, PointPos, PointPosQuery, PointPosQueryMut}; use geometry::{Line, LinePosQuery, Point, PointId, PointPos, PointPosQuery, PointPosQueryMut};
use iyes_loopless::prelude::*;
mod geometry; mod geometry;
mod optimization; mod optimization;
@ -20,15 +21,16 @@ fn main() {
"sketchrs", "sketchrs",
options, options,
Box::new(|_cc| Box::new(MyApp::default())), Box::new(|_cc| Box::new(MyApp::default())),
); ).unwrap();
} }
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq, Resource)]
enum Tool { enum Tool {
Select, Select,
Move, Move,
AddPoint, AddPoint,
AddLine, AddLine,
AddRelation,
} }
impl Default for Tool { impl Default for Tool {
@ -37,6 +39,34 @@ impl Default for Tool {
} }
} }
#[derive(Resource)]
struct ResponseRes(Response);
impl Deref for ResponseRes {
type Target = Response;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Resource)]
struct PainterRes(Painter);
impl Deref for PainterRes {
type Target = Painter;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for PainterRes {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Resource)]
struct ToScreen(RectTransform); struct ToScreen(RectTransform);
impl ToScreen { impl ToScreen {
@ -73,7 +103,7 @@ fn color_for_var_status(status: geometry::VarStatus) -> Hsva {
const POINT_RADIUS: f32 = 3.0; const POINT_RADIUS: f32 = 3.0;
fn update_hover_point( fn update_hover_point(
response: Res<Response>, response: Res<ResponseRes>,
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
point_pos: PointPosQuery, point_pos: PointPosQuery,
points: Query<(PointId, &Point)>, points: Query<(PointId, &Point)>,
@ -98,7 +128,7 @@ fn update_hover_point(
} }
fn update_hover_line( fn update_hover_line(
response: Res<Response>, response: Res<ResponseRes>,
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
lines: Query<(Entity, &Line)>, lines: Query<(Entity, &Line)>,
line_pos: LinePosQuery, line_pos: LinePosQuery,
@ -129,45 +159,19 @@ fn update_hover_line(
}); });
} }
fn update_cursor_icon(
response: Res<Response>,
tool: Res<Tool>,
hovered: Query<(), With<Hovered>>,
selected: Query<(), With<Selected>>,
) {
response.ctx.output().cursor_icon = match *tool {
Tool::Select => {
if !hovered.is_empty() {
CursorIcon::PointingHand
} else {
CursorIcon::Default
}
}
Tool::Move => {
if !selected.is_empty() {
CursorIcon::Grabbing
} else if !hovered.is_empty() {
CursorIcon::Grab
} else {
CursorIcon::Move
}
}
Tool::AddPoint => CursorIcon::None,
Tool::AddLine => CursorIcon::None,
};
}
fn select_tool( fn select_tool(
response: Res<Response>, response: Res<ResponseRes>,
hovered: Query<Entity, With<Hovered>>, hovered: Query<Entity, With<Hovered>>,
selected: Query<Entity, With<Selected>>, selected: Query<Entity, With<Selected>>,
mut commands: Commands, mut commands: Commands,
) { ) {
response.ctx.output().cursor_icon = if !hovered.is_empty() { response.ctx.output_mut(|output| {
CursorIcon::PointingHand output.cursor_icon = if !hovered.is_empty() {
} else { CursorIcon::PointingHand
CursorIcon::Default } else {
}; CursorIcon::Default
}
});
if response.clicked() { if response.clicked() {
selected.for_each(|selected| { selected.for_each(|selected| {
@ -185,7 +189,7 @@ struct DragDelta(Vec2);
// TODO: move other entities // TODO: move other entities
fn move_tool( fn move_tool(
response: Res<Response>, response: Res<ResponseRes>,
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
mut drag_delta: Local<DragDelta>, mut drag_delta: Local<DragDelta>,
mut point_pos: PointPosQueryMut, mut point_pos: PointPosQueryMut,
@ -195,13 +199,15 @@ fn move_tool(
) { ) {
let hover_pos = response.hover_pos().unwrap(); let hover_pos = response.hover_pos().unwrap();
response.ctx.output().cursor_icon = if !selected.is_empty() { response.ctx.output_mut(|o| {
CursorIcon::Grabbing o.cursor_icon = if !selected.is_empty() {
} else if !hovered.is_empty() { CursorIcon::Grabbing
CursorIcon::Grab } else if !hovered.is_empty() {
} else { CursorIcon::Grab
CursorIcon::Move } else {
}; CursorIcon::Move
}
});
let selected = if response.drag_started() { let selected = if response.drag_started() {
// TODO: choose which to select // TODO: choose which to select
@ -237,9 +243,9 @@ fn add_point(commands: &mut Commands, pos: Pos2, to_screen: &ToScreen) -> PointI
} }
fn add_point_tool( fn add_point_tool(
response: Res<Response>, response: Res<ResponseRes>,
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
painter: ResMut<egui::Painter>, painter: ResMut<PainterRes>,
mut commands: Commands, mut commands: Commands,
) { ) {
let hover_pos = response.hover_pos().unwrap(); let hover_pos = response.hover_pos().unwrap();
@ -251,9 +257,9 @@ fn add_point_tool(
} }
fn add_line_tool( fn add_line_tool(
response: Res<Response>, response: Res<ResponseRes>,
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
painter: ResMut<egui::Painter>, painter: ResMut<PainterRes>,
hovered: Query<Entity, (With<Hovered>, With<Point>)>, hovered: Query<Entity, (With<Hovered>, With<Point>)>,
selected: Query<(Entity, &Point), With<Selected>>, selected: Query<(Entity, &Point), With<Selected>>,
point_pos: PointPosQuery, point_pos: PointPosQuery,
@ -272,8 +278,8 @@ fn add_line_tool(
}; };
commands.entity(point_id).insert(Selected); commands.entity(point_id).insert(Selected);
} }
(Some(start_point), false) => { (Some((_, start_point)), false) => {
let start_point_pos = point_pos.get(start_point.1); let start_point_pos = point_pos.get(start_point);
let points = [to_screen.transform_pos(&start_point_pos), hover_pos]; let points = [to_screen.transform_pos(&start_point_pos), hover_pos];
let stroke = Stroke::new(2.0, Color32::DARK_GRAY); let stroke = Stroke::new(2.0, Color32::DARK_GRAY);
@ -282,34 +288,60 @@ fn add_line_tool(
painter.circle_filled(hover_pos, POINT_RADIUS, Color32::DARK_GRAY); painter.circle_filled(hover_pos, POINT_RADIUS, Color32::DARK_GRAY);
} }
(Some(start_point), true) => { (Some((start_point_id, _)), true) => {
// TODO: add point if no hover point // TODO: add point if no hover point
let end_point = hovered let end_point = hovered
.iter() .iter()
.next() .next()
.unwrap_or_else(|| add_point(&mut commands, hover_pos, &*to_screen)); .unwrap_or_else(|| add_point(&mut commands, hover_pos, &*to_screen));
let line = Line::new(start_point.0, end_point); let line = Line::new(start_point_id, end_point);
commands.spawn().insert(line); commands.spawn(line);
selected.for_each(|selected| { selected.for_each(|(selected_id, _)| {
commands.entity(selected.0).remove::<Selected>(); commands.entity(selected_id).remove::<Selected>();
}); });
} }
} }
} }
fn is_hovered(response: Res<Response>) -> bool { fn add_relation_tool(
response: Res<ResponseRes>,
hovered: Query<Entity, With<Hovered>>,
selected: Query<Entity, With<Selected>>,
mut commands: Commands,
) {
response.ctx.output_mut(|o| {
o.cursor_icon = if !hovered.is_empty() {
CursorIcon::PointingHand
} else {
CursorIcon::Default
}
});
if response.clicked() {
// TODO: choose which to select
if let Some(hovered) = hovered.iter().next() {
commands.entity(hovered).insert(Selected);
} else {
selected.for_each(|selected| {
commands.entity(selected).remove::<Selected>();
});
}
}
}
fn is_hovered(response: Res<ResponseRes>) -> bool {
response.hover_pos().is_some() response.hover_pos().is_some()
} }
fn is_tool_active(tool: Tool) -> impl System<In = (), Out = bool> { fn is_tool_active(tool: Tool) -> impl System<In = (), Out = bool> + ReadOnlySystem {
IntoSystem::into_system(move |active_tool: Res<Tool>| *active_tool == tool) IntoSystem::into_system(move |active_tool: Res<Tool>| *active_tool == tool)
} }
fn paint_lines( fn paint_lines(
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
painter: ResMut<Painter>, painter: ResMut<PainterRes>,
lines: Query<(Entity, &Line)>, lines: Query<(Entity, &Line)>,
hovered: Query<(), With<Hovered>>, hovered: Query<(), With<Hovered>>,
selected: Query<(), With<Selected>>, selected: Query<(), With<Selected>>,
@ -336,7 +368,7 @@ fn paint_lines(
fn paint_points( fn paint_points(
to_screen: Res<ToScreen>, to_screen: Res<ToScreen>,
painter: ResMut<Painter>, painter: ResMut<PainterRes>,
points: Query<(Entity, &Point)>, points: Query<(Entity, &Point)>,
hovered: Query<(), With<Hovered>>, hovered: Query<(), With<Hovered>>,
selected: Query<(), With<Selected>>, selected: Query<(), With<Selected>>,
@ -360,14 +392,15 @@ fn paint_points(
struct MyApp { struct MyApp {
world: World, world: World,
show_entities_stage: SystemStage, 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.));
geometry::insert_point_at(&mut commands, (0., -10.)); geometry::insert_point_at(&mut commands, (0., -10.));
commands.spawn().insert(Line::new(p1, p2)); commands.spawn(Line::new(p1, p2));
} }
impl Default for MyApp { impl Default for MyApp {
@ -376,45 +409,52 @@ impl Default for MyApp {
world.init_resource::<Tool>(); world.init_resource::<Tool>();
let mut init_stage = SystemStage::single_threaded().with_system(init); let mut init_stage = Schedule::new();
init_stage.add_system(init);
init_stage.run(&mut world); init_stage.run(&mut world);
Self { Self {
world, world,
show_entities_stage: Self::create_show_entities_stage(), 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 ScheduleSet {
Input,
Tools,
Paint,
}
impl MyApp { impl MyApp {
fn create_show_entities_stage() -> SystemStage { fn create_show_entities_stage() -> Schedule {
#[derive(SystemLabel, Debug, Clone, PartialEq, Eq, Hash)] let mut schedule = Schedule::new();
struct InputGroup; schedule
.configure_sets((ScheduleSet::Input, ScheduleSet::Tools, ScheduleSet::Paint).chain());
#[derive(SystemLabel, Debug, Clone, PartialEq, Eq, Hash)] schedule
struct ToolsGroup; .add_systems((update_hover_point, update_hover_line).in_base_set(ScheduleSet::Input));
schedule.add_systems(
SystemStage::single_threaded() (
.with_system_set( select_tool.run_if(is_tool_active(Tool::Select)),
ConditionSet::new() move_tool.run_if(is_tool_active(Tool::Move)),
.label("input") add_point_tool.run_if(is_tool_active(Tool::AddPoint)),
.with_system(update_hover_point) add_line_tool.run_if(is_tool_active(Tool::AddLine)),
.with_system(update_hover_line)
.into(),
) )
.with_system_set( .distributive_run_if(is_hovered)
ConditionSet::new() .in_base_set(ScheduleSet::Tools),
.label("tools") );
.after("input") schedule.add_systems(
.run_if(is_hovered) (paint_lines, paint_points.after(paint_lines)).in_base_set(ScheduleSet::Paint),
.with_system(update_cursor_icon) );
.with_system(select_tool.run_if(is_tool_active(Tool::Select))) schedule
.with_system(move_tool.run_if(is_tool_active(Tool::Move))) }
.with_system(add_point_tool.run_if(is_tool_active(Tool::AddPoint)))
.with_system(add_line_tool.run_if(is_tool_active(Tool::AddLine))) fn create_show_sidebar_stage() -> Schedule {
.into(), let mut schedule = Schedule::new();
) schedule
.with_system(paint_lines.label("paint_lines").after("tools")) // TODO order dependency
.with_system(paint_points.after("paint_lines"))
} }
fn show_toolbar(&mut self, ui: &mut Ui) { fn show_toolbar(&mut self, ui: &mut Ui) {
@ -429,13 +469,14 @@ impl MyApp {
ui.selectable_value(tool, Tool::Move, "Move"); ui.selectable_value(tool, Tool::Move, "Move");
ui.selectable_value(tool, Tool::AddPoint, "+ Point"); ui.selectable_value(tool, Tool::AddPoint, "+ Point");
ui.selectable_value(tool, Tool::AddLine, "+ Line"); ui.selectable_value(tool, Tool::AddLine, "+ Line");
ui.selectable_value(tool, Tool::AddRelation, "+ Relation");
}); });
} }
fn show_entities(&mut self, ui: &mut Ui) { fn show_entities(&mut self, ui: &mut Ui) {
let sense = match *self.world.resource::<Tool>() { let sense = match *self.world.resource::<Tool>() {
Tool::Move => Sense::drag(), Tool::Move => Sense::drag(),
Tool::Select | Tool::AddPoint | Tool::AddLine => 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);
@ -444,13 +485,13 @@ impl MyApp {
response.rect, response.rect,
)); ));
self.world.insert_resource(to_screen); self.world.insert_resource(to_screen);
self.world.insert_resource(response); self.world.insert_resource(ResponseRes(response));
self.world.insert_resource(painter); self.world.insert_resource(PainterRes(painter));
self.show_entities_stage.run(&mut self.world); self.show_entities_stage.run(&mut self.world);
self.world.remove_resource::<Painter>(); self.world.remove_resource::<PainterRes>();
self.world.remove_resource::<Response>(); self.world.remove_resource::<ResponseRes>();
self.world.remove_resource::<ToScreen>(); self.world.remove_resource::<ToScreen>();
} }
@ -465,15 +506,24 @@ impl MyApp {
selected.for_each(&self.world, |(id, point, line)| { selected.for_each(&self.world, |(id, point, line)| {
count += 1; count += 1;
if point.is_some() { if point.is_some() {
ui.label(format!("Selected point {}", id.id())); ui.label(format!("Selected point {}", id.index()));
} else if line.is_some() { } else if line.is_some() {
ui.label(format!("Selected line {}", id.id())); ui.label(format!("Selected line {}", id.index()));
} }
}); });
if count == 0 { if count == 0 {
ui.label("No selection"); 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");
}
}
_ => { _ => {
ui.label(":)"); ui.label(":)");
} }