update dependencies
This commit is contained in:
parent
fdd93fa7e8
commit
fc550267da
2564
Cargo.lock
generated
2564
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
16
Cargo.toml
@ -6,16 +6,16 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
argmin = { version = "0.5.1", features = ["nalgebra"] }
|
||||
bevy_ecs = "0.7.0"
|
||||
eframe = { version = "0.18.0", features = [] }
|
||||
argmin = { version = "0.8.1", features = [] }
|
||||
argmin-math = { version = "0.3.0", features = ["nalgebra_0_32"] }
|
||||
bevy_ecs = "0.10.1"
|
||||
eframe = { version = "0.21.3", features = [] }
|
||||
indexmap = "1.8.1"
|
||||
iyes_loopless = "0.5.1"
|
||||
levenberg-marquardt = "0.12.0"
|
||||
nalgebra = "0.30.1"
|
||||
nalgebra-sparse = "0.6.0"
|
||||
levenberg-marquardt = "0.13.0"
|
||||
nalgebra = "0.32.0"
|
||||
nalgebra-sparse = "0.9.0"
|
||||
nohash-hasher = "0.2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.5"
|
||||
criterion = "0.4.0"
|
||||
|
||||
|
@ -62,9 +62,9 @@ pub struct Circle {
|
||||
|
||||
pub fn insert_point_at(commands: &mut Commands, point: impl Into<PointPos>) -> PointId {
|
||||
let point = point.into();
|
||||
let x = commands.spawn().insert(Var::new_free(point.x)).id();
|
||||
let y = commands.spawn().insert(Var::new_free(point.y)).id();
|
||||
commands.spawn().insert(Point::new(x, y)).id()
|
||||
let x = commands.spawn(Var::new_free(point.x)).id();
|
||||
let y = commands.spawn(Var::new_free(point.y)).id();
|
||||
commands.spawn(Point::new(x, y)).id()
|
||||
}
|
||||
|
||||
// TODO: figure out generic for this
|
||||
|
254
src/main.rs
254
src/main.rs
@ -1,14 +1,15 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use bevy_ecs::{
|
||||
prelude::*,
|
||||
system::{Commands, IntoSystem, Query, Res, ResMut, System},
|
||||
system::{Commands, IntoSystem, Query, ReadOnlySystem, Res, ResMut, System},
|
||||
};
|
||||
use eframe::{
|
||||
egui::{self, CursorIcon, Painter, Response, Sense, Ui},
|
||||
emath::{Pos2, Rect, RectTransform, Vec2},
|
||||
epaint::{color::Hsva, Color32, Stroke},
|
||||
epaint::{Color32, Hsva, Stroke},
|
||||
};
|
||||
use geometry::{Line, LinePosQuery, Point, PointId, PointPos, PointPosQuery, PointPosQueryMut};
|
||||
use iyes_loopless::prelude::*;
|
||||
|
||||
mod geometry;
|
||||
mod optimization;
|
||||
@ -20,15 +21,16 @@ fn main() {
|
||||
"sketchrs",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Resource)]
|
||||
enum Tool {
|
||||
Select,
|
||||
Move,
|
||||
AddPoint,
|
||||
AddLine,
|
||||
AddRelation,
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
impl ToScreen {
|
||||
@ -73,7 +103,7 @@ fn color_for_var_status(status: geometry::VarStatus) -> Hsva {
|
||||
const POINT_RADIUS: f32 = 3.0;
|
||||
|
||||
fn update_hover_point(
|
||||
response: Res<Response>,
|
||||
response: Res<ResponseRes>,
|
||||
to_screen: Res<ToScreen>,
|
||||
point_pos: PointPosQuery,
|
||||
points: Query<(PointId, &Point)>,
|
||||
@ -98,7 +128,7 @@ fn update_hover_point(
|
||||
}
|
||||
|
||||
fn update_hover_line(
|
||||
response: Res<Response>,
|
||||
response: Res<ResponseRes>,
|
||||
to_screen: Res<ToScreen>,
|
||||
lines: Query<(Entity, &Line)>,
|
||||
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(
|
||||
response: Res<Response>,
|
||||
response: Res<ResponseRes>,
|
||||
hovered: Query<Entity, With<Hovered>>,
|
||||
selected: Query<Entity, With<Selected>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
response.ctx.output().cursor_icon = if !hovered.is_empty() {
|
||||
CursorIcon::PointingHand
|
||||
} else {
|
||||
CursorIcon::Default
|
||||
};
|
||||
response.ctx.output_mut(|output| {
|
||||
output.cursor_icon = if !hovered.is_empty() {
|
||||
CursorIcon::PointingHand
|
||||
} else {
|
||||
CursorIcon::Default
|
||||
}
|
||||
});
|
||||
|
||||
if response.clicked() {
|
||||
selected.for_each(|selected| {
|
||||
@ -185,7 +189,7 @@ struct DragDelta(Vec2);
|
||||
|
||||
// TODO: move other entities
|
||||
fn move_tool(
|
||||
response: Res<Response>,
|
||||
response: Res<ResponseRes>,
|
||||
to_screen: Res<ToScreen>,
|
||||
mut drag_delta: Local<DragDelta>,
|
||||
mut point_pos: PointPosQueryMut,
|
||||
@ -195,13 +199,15 @@ fn move_tool(
|
||||
) {
|
||||
let hover_pos = response.hover_pos().unwrap();
|
||||
|
||||
response.ctx.output().cursor_icon = if !selected.is_empty() {
|
||||
CursorIcon::Grabbing
|
||||
} else if !hovered.is_empty() {
|
||||
CursorIcon::Grab
|
||||
} else {
|
||||
CursorIcon::Move
|
||||
};
|
||||
response.ctx.output_mut(|o| {
|
||||
o.cursor_icon = if !selected.is_empty() {
|
||||
CursorIcon::Grabbing
|
||||
} else if !hovered.is_empty() {
|
||||
CursorIcon::Grab
|
||||
} else {
|
||||
CursorIcon::Move
|
||||
}
|
||||
});
|
||||
|
||||
let selected = if response.drag_started() {
|
||||
// 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(
|
||||
response: Res<Response>,
|
||||
response: Res<ResponseRes>,
|
||||
to_screen: Res<ToScreen>,
|
||||
painter: ResMut<egui::Painter>,
|
||||
painter: ResMut<PainterRes>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let hover_pos = response.hover_pos().unwrap();
|
||||
@ -251,9 +257,9 @@ fn add_point_tool(
|
||||
}
|
||||
|
||||
fn add_line_tool(
|
||||
response: Res<Response>,
|
||||
response: Res<ResponseRes>,
|
||||
to_screen: Res<ToScreen>,
|
||||
painter: ResMut<egui::Painter>,
|
||||
painter: ResMut<PainterRes>,
|
||||
hovered: Query<Entity, (With<Hovered>, With<Point>)>,
|
||||
selected: Query<(Entity, &Point), With<Selected>>,
|
||||
point_pos: PointPosQuery,
|
||||
@ -272,8 +278,8 @@ fn add_line_tool(
|
||||
};
|
||||
commands.entity(point_id).insert(Selected);
|
||||
}
|
||||
(Some(start_point), false) => {
|
||||
let start_point_pos = point_pos.get(start_point.1);
|
||||
(Some((_, start_point)), false) => {
|
||||
let start_point_pos = point_pos.get(start_point);
|
||||
let points = [to_screen.transform_pos(&start_point_pos), hover_pos];
|
||||
|
||||
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);
|
||||
}
|
||||
(Some(start_point), true) => {
|
||||
(Some((start_point_id, _)), true) => {
|
||||
// TODO: add point if no hover point
|
||||
let end_point = hovered
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap_or_else(|| add_point(&mut commands, hover_pos, &*to_screen));
|
||||
|
||||
let line = Line::new(start_point.0, end_point);
|
||||
commands.spawn().insert(line);
|
||||
let line = Line::new(start_point_id, end_point);
|
||||
commands.spawn(line);
|
||||
|
||||
selected.for_each(|selected| {
|
||||
commands.entity(selected.0).remove::<Selected>();
|
||||
selected.for_each(|(selected_id, _)| {
|
||||
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()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn paint_lines(
|
||||
to_screen: Res<ToScreen>,
|
||||
painter: ResMut<Painter>,
|
||||
painter: ResMut<PainterRes>,
|
||||
lines: Query<(Entity, &Line)>,
|
||||
hovered: Query<(), With<Hovered>>,
|
||||
selected: Query<(), With<Selected>>,
|
||||
@ -336,7 +368,7 @@ fn paint_lines(
|
||||
|
||||
fn paint_points(
|
||||
to_screen: Res<ToScreen>,
|
||||
painter: ResMut<Painter>,
|
||||
painter: ResMut<PainterRes>,
|
||||
points: Query<(Entity, &Point)>,
|
||||
hovered: Query<(), With<Hovered>>,
|
||||
selected: Query<(), With<Selected>>,
|
||||
@ -360,14 +392,15 @@ fn paint_points(
|
||||
|
||||
struct MyApp {
|
||||
world: World,
|
||||
show_entities_stage: SystemStage,
|
||||
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.));
|
||||
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 {
|
||||
@ -376,45 +409,52 @@ impl Default for MyApp {
|
||||
|
||||
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);
|
||||
|
||||
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 ScheduleSet {
|
||||
Input,
|
||||
Tools,
|
||||
Paint,
|
||||
}
|
||||
|
||||
impl MyApp {
|
||||
fn create_show_entities_stage() -> SystemStage {
|
||||
#[derive(SystemLabel, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct InputGroup;
|
||||
|
||||
#[derive(SystemLabel, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct ToolsGroup;
|
||||
|
||||
SystemStage::single_threaded()
|
||||
.with_system_set(
|
||||
ConditionSet::new()
|
||||
.label("input")
|
||||
.with_system(update_hover_point)
|
||||
.with_system(update_hover_line)
|
||||
.into(),
|
||||
fn create_show_entities_stage() -> Schedule {
|
||||
let mut schedule = Schedule::new();
|
||||
schedule
|
||||
.configure_sets((ScheduleSet::Input, ScheduleSet::Tools, ScheduleSet::Paint).chain());
|
||||
schedule
|
||||
.add_systems((update_hover_point, update_hover_line).in_base_set(ScheduleSet::Input));
|
||||
schedule.add_systems(
|
||||
(
|
||||
select_tool.run_if(is_tool_active(Tool::Select)),
|
||||
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)),
|
||||
)
|
||||
.with_system_set(
|
||||
ConditionSet::new()
|
||||
.label("tools")
|
||||
.after("input")
|
||||
.run_if(is_hovered)
|
||||
.with_system(update_cursor_icon)
|
||||
.with_system(select_tool.run_if(is_tool_active(Tool::Select)))
|
||||
.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)))
|
||||
.into(),
|
||||
)
|
||||
.with_system(paint_lines.label("paint_lines").after("tools")) // TODO order dependency
|
||||
.with_system(paint_points.after("paint_lines"))
|
||||
.distributive_run_if(is_hovered)
|
||||
.in_base_set(ScheduleSet::Tools),
|
||||
);
|
||||
schedule.add_systems(
|
||||
(paint_lines, paint_points.after(paint_lines)).in_base_set(ScheduleSet::Paint),
|
||||
);
|
||||
schedule
|
||||
}
|
||||
|
||||
fn create_show_sidebar_stage() -> Schedule {
|
||||
let mut schedule = Schedule::new();
|
||||
schedule
|
||||
}
|
||||
|
||||
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::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::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);
|
||||
@ -444,13 +485,13 @@ impl MyApp {
|
||||
response.rect,
|
||||
));
|
||||
self.world.insert_resource(to_screen);
|
||||
self.world.insert_resource(response);
|
||||
self.world.insert_resource(painter);
|
||||
self.world.insert_resource(ResponseRes(response));
|
||||
self.world.insert_resource(PainterRes(painter));
|
||||
|
||||
self.show_entities_stage.run(&mut self.world);
|
||||
|
||||
self.world.remove_resource::<Painter>();
|
||||
self.world.remove_resource::<Response>();
|
||||
self.world.remove_resource::<PainterRes>();
|
||||
self.world.remove_resource::<ResponseRes>();
|
||||
self.world.remove_resource::<ToScreen>();
|
||||
}
|
||||
|
||||
@ -465,15 +506,24 @@ impl MyApp {
|
||||
selected.for_each(&self.world, |(id, point, line)| {
|
||||
count += 1;
|
||||
if point.is_some() {
|
||||
ui.label(format!("Selected point {}", id.id()));
|
||||
ui.label(format!("Selected point {}", id.index()));
|
||||
} else if line.is_some() {
|
||||
ui.label(format!("Selected line {}", id.id()));
|
||||
ui.label(format!("Selected line {}", id.index()));
|
||||
}
|
||||
});
|
||||
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");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ui.label(":)");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user