use bevy::ecs::schedule::ShouldRun; use bevy::input::mouse::{MouseMotion, MouseWheel}; use bevy::math::Vec3Swizzles; use bevy::{prelude::*, window::PresentMode, winit::WinitSettings}; use bevy_egui::{egui, EguiContext, EguiPlugin}; use bevy_prototype_lyon::prelude::*; use shape_maker::*; fn main() { let mut app = App::new(); app .insert_resource(ClearColor(Color::rgb(0.1, 0.1, 0.12))) .insert_resource(Msaa { samples: 4 }) // Optimal power saving and present mode settings for desktop apps. .insert_resource(WinitSettings::desktop_app()) .insert_resource(WindowDescriptor { present_mode: PresentMode::Fifo, title: "Shape Maker".to_string(), ..Default::default() }) .insert_resource(ButtonsColors::default()) .insert_resource(UiState::default()) .insert_resource(PointSize(6.0)) .insert_resource(SnapGrid::default()) ; app .add_plugins(DefaultPlugins) .add_plugin(EguiPlugin) .add_plugin(ShapePlugin) ; app .add_startup_system(configure_visuals) .add_startup_system(basic_setup_sys) .add_system(create_sys.with_run_criteria(|state: Res, mut ec: ResMut| if !ec.ctx_mut().is_pointer_over_area() && state.current_action == Action::Create { ShouldRun::Yes } else { ShouldRun::No } )) .add_system(modify_sys.with_run_criteria(|state: Res, mut ec: ResMut| if !ec.ctx_mut().is_pointer_over_area() && state.current_action == Action::Modify { ShouldRun::Yes } else { ShouldRun::No } )) .add_system(ui::action_bar_sys) .add_system(ui::shape_tree_sys) .add_system(show_hide_points) .add_system(color_points) .add_system(drag_camera_sys) .add_system(zoom_camera_sys) .add_system(scale_points) .add_system(ui::grid_window_sys) ; app.run(); } fn basic_setup_sys( mut coms: Commands, ) { coms.spawn_bundle(Camera2dBundle::default()) .insert(MainCamera); } fn configure_visuals(mut egui_ctx: ResMut) { egui_ctx.ctx_mut().set_visuals(egui::Visuals { window_rounding: 0.0.into(), ..Default::default() }); } fn zoom_camera_sys( mut mouse_scroll: EventReader, mut cam: Query<&mut OrthographicProjection, With>, ) { let mut scroll = 0.0; for m in mouse_scroll.iter() { scroll += m.y * 0.1; } for mut op in cam.iter_mut() { op.scale += scroll ; if op.scale <= 0.05 { op.scale = 0.05; } } } fn scale_points( scale: Query<&OrthographicProjection, (With, Changed)>, shapes: Query<&ShapeData>, p_size: Res, mut paths: Query<&mut Path, With>, ) { if let Ok(scale) = scale.get_single() { let scale = scale.scale; for sd in shapes.iter() { if let Ok(mut p) = paths.get_mut(sd.center.unwrap()) { let shape = shapes::Circle { radius: p_size.0 * scale, center: Vec2::ZERO, }; *p = ShapePath::build_as(&shape); } for &edge in sd.edges.iter() { if let Ok(mut p) = paths.get_mut(edge) { let shape = shapes::Circle { radius: p_size.0 * scale, center: Vec2::ZERO, }; *p = ShapePath::build_as(&shape); } } } } } fn drag_camera_sys( mut mouse_move: EventReader, mouse_input: Res>, mut cam: Query<(&mut Transform, &OrthographicProjection), With>, ) { if mouse_input.pressed(MouseButton::Middle) { let mut delta = Vec2::ZERO; for m in mouse_move.iter() { delta -= Vec2::new(m.delta.x, -m.delta.y) * 2.0; } for (mut t, op) in cam.iter_mut() { t.translation += delta.extend(0.0) * op.scale; } } } fn show_hide_points( state: Res, shapes: Query<&ShapeData>, mut dots: Query<&mut Visibility, (With, With)>, ) { let (center, edge) = match state.current_action { Action::Create => (false, false), Action::Modify => (true, true), }; for sd in shapes.iter() { // center if let Ok(mut v) = dots.get_mut(sd.center.unwrap()) { if v.is_visible != center { v.is_visible = center; } } for e in sd.edges.iter() { if let Ok(mut v) = dots.get_mut(*e) { if v.is_visible != edge { v.is_visible = edge; } } } } } fn color_points( mut current: Local>, scale: Query<&OrthographicProjection, With>, wnds: Res, p_size: Res, q_cam: Query<(&Camera, &GlobalTransform), With>, shapes: Query<&ShapeData>, global_transforms: Query<&GlobalTransform, With>, mut dots: Query<&mut DrawMode, With>, ) { let scale = scale.get_single().map(|s| s.scale).unwrap_or(1.0); let normal = DrawMode::Outlined { fill_mode: FillMode::color(Color::RED), outline_mode: StrokeMode::new(Color::rgb(0.9,0.0,0.0), 0.0) }; let hover = DrawMode::Outlined { fill_mode: FillMode::color(Color::RED), outline_mode: StrokeMode::new(Color::ORANGE, 3.0 * scale) }; let mouse_pos = get_mouse_pos(&q_cam, &wnds); if let Some(mpos) = mouse_pos { let mut hovering = false; 'shapes: for sd in shapes.iter() { let e = sd.center.unwrap(); let p = global_transforms.get(e).unwrap().translation().xy(); if (mpos - p).length_squared() < (p_size.0 * scale).powi(2) { if Some(e) != *current { if let Some(c) = &*current { if let Ok(mut md) = dots.get_mut(*c) { *md = normal; } } *current = Some(e); if let Ok(mut md) = dots.get_mut(e) { *md = hover; } } hovering = true; break; } for edge in sd.edges.iter() { let p = global_transforms.get(*edge).unwrap().translation().xy(); if (mpos - p).length_squared() < (p_size.0 * scale).powi(2) { if Some(*edge) != *current { if let Some(c) = &*current { if let Ok(mut md) = dots.get_mut(*c) { *md = normal; } } *current = Some(*edge); if let Ok(mut md) = dots.get_mut(*edge) { *md = hover; } } hovering = true; break 'shapes; } } } if !hovering { if let Some(c) = &*current { if let Ok(mut md) = dots.get_mut(*c) { *md = normal; } *current = None; } } } }