diff --git a/src/components/hidden.rs b/src/components/hidden.rs new file mode 100644 index 0000000..ee4b1a9 --- /dev/null +++ b/src/components/hidden.rs @@ -0,0 +1,8 @@ +use specs::prelude::*; + +#[derive(Debug, Copy, Clone, Default)] +pub struct Hidden; + +impl Component for Hidden { + type Storage = NullStorage; +} \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs index 682a511..08b1dd8 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -3,9 +3,11 @@ mod line; mod circle; mod rectangle; mod selected; +mod hidden; pub use point::*; pub use line::*; pub use circle::*; pub use rectangle::*; -pub use selected::*; \ No newline at end of file +pub use selected::*; +pub use hidden::*; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 500989a..ff461d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ fn main() { .with(interactions::select::SeldeAllViaKeyboard, "selde_all_via_keyboard", &[]) .with(interactions::remove::RemoveSelectedViaDelete, "remove_selected_via_delete", &[]) .with(interactions::create::line::AbortCreateLineViaKeyboard, "abort_create_line_via_keyboard", &[]) + .with(interactions::hide::HideSelectedViaKeyboard, "hide_selected_via_keyboard", &[]) .with(interactions::history::UndoViaKeyboard, "undo_via_keyboard", &[]) .with(interactions::history::RedoViaKeyboard, "redo_via_keyboard", &[]) @@ -56,6 +57,7 @@ fn main() { // Geometry action handlers .with(geometry_actions::SeldeAllHandler::default(), "selde_all_handler", &["selde_all_via_keyboard", "selde_via_mouse"]) .with(geometry_actions::RemoveSelectedHandler::default(), "remove_selected_handler", &["remove_selected_via_delete", "dependency_graph_cache"]) + .with(geometry_actions::HideSelectedHandler::default(), "hide_selected_handler", &["hide_selected_via_keyboard"]) // Geometry helpers .with(interactions::create::point::SnapPointSystem, "snap_point_system", &["spatial_hash_cache", "tool_state_manager", "viewport_state_manager"]) @@ -84,6 +86,7 @@ fn main() { .with(geometry_systems::InsertHistoryGeometry::default(), "insert_history_geometry", &["sketch_history_action_handler"]) // Remove systems + .with(geometry_systems::HideHandler::default(), "hide_handler", &["hide_selected_handler"]) .with(geometry_systems::RemoveHandler::default(), "remove_handler", &["remove_selected_handler", "sketch_history_action_handler"]) // History caching diff --git a/src/resources/events/geometry_action.rs b/src/resources/events/geometry_action.rs index a939b40..aada492 100644 --- a/src/resources/events/geometry_action.rs +++ b/src/resources/events/geometry_action.rs @@ -7,6 +7,8 @@ pub enum GeometryAction { DeselectAll, DeselectAllExcept(Entity), RemoveSelected, + HideSelected, + UnhideAll, DrawParallelOnSelected, DrawPerpendicularOnSelected, DrawMidpointOnSelected, diff --git a/src/resources/events/sketch_event.rs b/src/resources/events/sketch_event.rs index 5e39afb..aaf0cb9 100644 --- a/src/resources/events/sketch_event.rs +++ b/src/resources/events/sketch_event.rs @@ -11,6 +11,8 @@ pub enum SketchEvent { Insert(Entity, SketchGeometry, bool), // the last bool represents "is_by_history" Remove(Entity, SketchGeometry, bool), // the last bool represents "is_by_history" MovePoint(Entity, MovePoint), + Hide(Entity, bool), + Unhide(Entity, bool), } impl SketchEvent { @@ -29,6 +31,22 @@ impl SketchEvent { pub fn remove_by_history(ent: Entity, sketch_geom: SketchGeometry) -> Self { SketchEvent::Remove(ent, sketch_geom, true) } + + pub fn hide(ent: Entity) -> Self { + SketchEvent::Hide(ent, false) + } + + pub fn hide_by_history(ent: Entity) -> Self { + SketchEvent::Hide(ent, true) + } + + pub fn unhide(ent: Entity) -> Self { + SketchEvent::Unhide(ent, false) + } + + pub fn unhide_by_history(ent: Entity) -> Self { + SketchEvent::Unhide(ent, true) + } } #[derive(Debug, Clone, Copy)] diff --git a/src/resources/sketch_history.rs b/src/resources/sketch_history.rs index b07c043..8773e22 100644 --- a/src/resources/sketch_history.rs +++ b/src/resources/sketch_history.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use specs::prelude::*; use super::events::SketchGeometry; @@ -21,6 +21,8 @@ impl Default for SketchHistory { pub enum SketchHistoryEvent { RemoveMany(HashMap), InsertMany(HashMap), + HideMany(HashSet), + UnhideMany(HashSet), // Update(Entity, SketchGeometry, SketchGeometry), // Entity, old, new } diff --git a/src/systems/cache_managers/dependency_graph_cache.rs b/src/systems/cache_managers/dependency_graph_cache.rs index 955532c..3b6ca1c 100644 --- a/src/systems/cache_managers/dependency_graph_cache.rs +++ b/src/systems/cache_managers/dependency_graph_cache.rs @@ -108,7 +108,11 @@ impl<'a> System<'a> for DependencyGraphCache { SketchGeometry::Circle(sym_circle, _) => add_circle(&mut dependency_graph, entity, sym_circle), }, SketchEvent::Remove(entity, _, _) => dependency_graph.remove(entity), - SketchEvent::Select(_) | SketchEvent::Deselect(_) | SketchEvent::MovePoint(_, _) => (), + SketchEvent::Select(_) | + SketchEvent::Deselect(_) | + SketchEvent::MovePoint(_, _) | + SketchEvent::Hide(_, _) | + SketchEvent::Unhide(_, _) => (), } } } else { diff --git a/src/systems/cache_managers/sketch_history_action_handler.rs b/src/systems/cache_managers/sketch_history_action_handler.rs index b810d47..9b7037d 100644 --- a/src/systems/cache_managers/sketch_history_action_handler.rs +++ b/src/systems/cache_managers/sketch_history_action_handler.rs @@ -1,9 +1,10 @@ +use std::collections::{HashMap, HashSet}; use specs::prelude::*; use crate::{ resources::{ events::{ HistoryAction, HistoryActionReader, HistoryActionChannel, - SketchEvent, SketchEventChannel, + SketchEvent, SketchEventChannel, SketchGeometry, }, SketchHistory, SketchHistoryEvent, }, @@ -42,32 +43,20 @@ impl<'a> System<'a> for SketchHistoryActionHandler { HistoryAction::Undo => { if let Some(history_event) = sketch_history.undo() { match history_event { - SketchHistoryEvent::InsertMany(insertions) => { - for (inserted_entity, inserted_geometry) in insertions { - sketch_event_channel.single_write(SketchEvent::remove_by_history(*inserted_entity, *inserted_geometry)); - } - }, - SketchHistoryEvent::RemoveMany(removals) => { - for (removed_entity, removed_geometry) in removals { - sketch_event_channel.single_write(SketchEvent::insert_by_history(*removed_entity, *removed_geometry)); - } - }, + SketchHistoryEvent::InsertMany(insertions) => remove(&mut sketch_event_channel, insertions), + SketchHistoryEvent::RemoveMany(removals) => insert(&mut sketch_event_channel, removals), + SketchHistoryEvent::HideMany(entities) => unhide(&mut sketch_event_channel, entities), + SketchHistoryEvent::UnhideMany(entities) => hide(&mut sketch_event_channel, entities), } } }, HistoryAction::Redo => { if let Some(history_event) = sketch_history.redo() { match history_event { - SketchHistoryEvent::InsertMany(insertions) => { - for (inserted_entity, inserted_geometry) in insertions { - sketch_event_channel.single_write(SketchEvent::insert_by_history(*inserted_entity, *inserted_geometry)); - } - }, - SketchHistoryEvent::RemoveMany(removals) => { - for (removed_entity, removed_geometry) in removals { - sketch_event_channel.single_write(SketchEvent::remove_by_history(*removed_entity, *removed_geometry)); - } - }, + SketchHistoryEvent::InsertMany(insertions) => insert(&mut sketch_event_channel, insertions), + SketchHistoryEvent::RemoveMany(removals) => remove(&mut sketch_event_channel, removals), + SketchHistoryEvent::HideMany(entities) => hide(&mut sketch_event_channel, entities), + SketchHistoryEvent::UnhideMany(entities) => unhide(&mut sketch_event_channel, entities), } } }, @@ -76,4 +65,28 @@ impl<'a> System<'a> for SketchHistoryActionHandler { } } } +} + +fn remove(sketch_event_channel: &mut SketchEventChannel, entities: &HashMap) { + for (entity, geometry) in entities { + sketch_event_channel.single_write(SketchEvent::remove_by_history(*entity, *geometry)); + } +} + +fn insert(sketch_event_channel: &mut SketchEventChannel, entities: &HashMap) { + for (entity, geometry) in entities { + sketch_event_channel.single_write(SketchEvent::insert_by_history(*entity, *geometry)); + } +} + +fn hide(sketch_event_channel: &mut SketchEventChannel, entities: &HashSet) { + for entity in entities { + sketch_event_channel.single_write(SketchEvent::hide_by_history(*entity)); + } +} + +fn unhide(sketch_event_channel: &mut SketchEventChannel, entities: &HashSet) { + for entity in entities { + sketch_event_channel.single_write(SketchEvent::unhide_by_history(*entity)); + } } \ No newline at end of file diff --git a/src/systems/cache_managers/sketch_history_cache.rs b/src/systems/cache_managers/sketch_history_cache.rs index d59e0ff..b187118 100644 --- a/src/systems/cache_managers/sketch_history_cache.rs +++ b/src/systems/cache_managers/sketch_history_cache.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use specs::prelude::*; use crate::{ resources::{ @@ -11,6 +11,8 @@ enum Event { None, Insert(HashMap), Remove(HashMap), + Hide(HashSet), + Unhide(HashSet), } pub struct SketchHistoryCache { @@ -64,6 +66,26 @@ impl<'a> System<'a> for SketchHistoryCache { curr_event = Event::Remove(removals); } }, + SketchEvent::Hide(entity, false) => { + if let Event::Hide(entities) = &mut curr_event { + entities.insert(*entity); + } else { + push_event(curr_event, &mut sketch_history); + let mut entities = HashSet::new(); + entities.insert(*entity); + curr_event = Event::Hide(entities); + } + }, + SketchEvent::Unhide(entity, false) => { + if let Event::Unhide(entities) = &mut curr_event { + entities.insert(*entity); + } else { + push_event(curr_event, &mut sketch_history); + let mut entities = HashSet::new(); + entities.insert(*entity); + curr_event = Event::Unhide(entities); + } + }, _ => (), } } @@ -78,5 +100,7 @@ fn push_event(event: Event, history: &mut SketchHistory) { Event::None => (), Event::Insert(insertions) => history.push(SketchHistoryEvent::InsertMany(insertions)), Event::Remove(removals) => history.push(SketchHistoryEvent::RemoveMany(removals)), + Event::Hide(entities) => history.push(SketchHistoryEvent::HideMany(entities)), + Event::Unhide(entities) => history.push(SketchHistoryEvent::UnhideMany(entities)), } } \ No newline at end of file diff --git a/src/systems/cache_managers/spatial_hash_cache.rs b/src/systems/cache_managers/spatial_hash_cache.rs index aa9edf8..a6f258f 100644 --- a/src/systems/cache_managers/spatial_hash_cache.rs +++ b/src/systems/cache_managers/spatial_hash_cache.rs @@ -118,15 +118,13 @@ impl<'a> System<'a> for SpatialHashCache { let dependents = dependency_graph.get_all_dependents(entity); for dependent in dependents { table.remove_from_all(dependent); - if let Some(point) = points.get(dependent) { - table.insert_point(dependent, *point, &*vp); - } else if let Some(line) = lines.get(dependent) { - table.insert_line(dependent, *line, &*vp); - } else if let Some(circle) = circles.get(dependent) { - table.insert_circle(dependent, *circle, &*vp); - } + insert_entity(dependent, &*vp, &mut table, &points, &lines, &circles); } }, + SketchEvent::Hide(entity, _) => table.remove_from_all(*entity), + SketchEvent::Unhide(entity, _) => { + insert_entity(*entity, &*vp, &mut table, &points, &lines, &circles); + } } } } else { @@ -134,4 +132,21 @@ impl<'a> System<'a> for SpatialHashCache { } } } +} + +fn insert_entity<'a>( + entity: Entity, + viewport: &Viewport, + table: &mut SpatialHashTable, + points: &ReadStorage<'a, Point>, + lines: &ReadStorage<'a, Line>, + circles: &ReadStorage<'a, Circle>, +) { + if let Some(point) = points.get(entity) { + table.insert_point(entity, *point, viewport); + } else if let Some(line) = lines.get(entity) { + table.insert_line(entity, *line, &*viewport); + } else if let Some(circle) = circles.get(entity) { + table.insert_circle(entity, *circle, viewport); + } } \ No newline at end of file diff --git a/src/systems/geometry_actions/hide_selected_handler.rs b/src/systems/geometry_actions/hide_selected_handler.rs new file mode 100644 index 0000000..bb6b63d --- /dev/null +++ b/src/systems/geometry_actions/hide_selected_handler.rs @@ -0,0 +1,48 @@ +use specs::prelude::*; +use crate::{ + resources::events::{ + GeometryAction, GeometryActionChannel, GeometryActionReader, + SketchEvent, SketchEventChannel, + }, + components::{Selected}, +}; + +pub struct HideSelectedHandler { + geometry_action_reader: Option, +} + +impl Default for HideSelectedHandler { + fn default() -> Self { + Self { geometry_action_reader: None } + } +} + +impl<'a> System<'a> for HideSelectedHandler { + type SystemData = ( + Entities<'a>, + Read<'a, GeometryActionChannel>, + Write<'a, SketchEventChannel>, + ReadStorage<'a, Selected>, + ); + + fn setup(&mut self, world: &mut World) { + Self::SystemData::setup(world); + self.geometry_action_reader = Some(world.fetch_mut::().register_reader()); + } + + fn run(&mut self, (entities, geometry_action_channel, mut sketch_event_channel, selected): Self::SystemData) { + if let Some(reader_id) = &mut self.geometry_action_reader { + for event in geometry_action_channel.read(reader_id) { + match event { + GeometryAction::HideSelected => { + for (entity, _) in (&entities, &selected).join() { + sketch_event_channel.single_write(SketchEvent::hide(entity)); + } + break; + }, + _ => () + } + } + } + } +} \ No newline at end of file diff --git a/src/systems/geometry_actions/mod.rs b/src/systems/geometry_actions/mod.rs index 34272a1..2f92ebb 100644 --- a/src/systems/geometry_actions/mod.rs +++ b/src/systems/geometry_actions/mod.rs @@ -1,6 +1,9 @@ mod remove_selected_handler; pub use remove_selected_handler::*; +mod hide_selected_handler; +pub use hide_selected_handler::*; + mod selde_all_handler; pub use selde_all_handler::*; diff --git a/src/systems/geometry_systems/hide_handler.rs b/src/systems/geometry_systems/hide_handler.rs new file mode 100644 index 0000000..5b3bc38 --- /dev/null +++ b/src/systems/geometry_systems/hide_handler.rs @@ -0,0 +1,45 @@ +use specs::prelude::*; +use crate::{ + resources::events::{ + SketchEventReader, SketchEventChannel, SketchEvent, + }, + components::Hidden, +}; + +pub struct HideHandler { + sketch_event_reader: Option, +} + +impl Default for HideHandler { + fn default() -> Self { + Self { sketch_event_reader: None } + } +} + +impl<'a> System<'a> for HideHandler { + type SystemData = ( + Read<'a, SketchEventChannel>, + WriteStorage<'a, Hidden>, + ); + + fn setup(&mut self, world: &mut World) { + Self::SystemData::setup(world); + self.sketch_event_reader = Some(world.fetch_mut::().register_reader()); + } + + fn run(&mut self, (sketch_event_channel, mut hidden): Self::SystemData) { + if let Some(reader_id) = &mut self.sketch_event_reader { + for event in sketch_event_channel.read(reader_id) { + match event { + SketchEvent::Hide(entity, _) => { + if let Err(err) = hidden.insert(*entity, Hidden) { panic!(err) } + }, + SketchEvent::Unhide(entity, _) => { + hidden.remove(*entity); + }, + _ => (), + } + } + } + } +} \ No newline at end of file diff --git a/src/systems/geometry_systems/mod.rs b/src/systems/geometry_systems/mod.rs index 73d025d..bbcf003 100644 --- a/src/systems/geometry_systems/mod.rs +++ b/src/systems/geometry_systems/mod.rs @@ -4,6 +4,9 @@ pub use solver_system::SolverSystem; mod remove_handler; pub use remove_handler::*; +mod hide_handler; +pub use hide_handler::*; + mod selde_handler; pub use selde_handler::*; diff --git a/src/systems/geometry_systems/solver_system.rs b/src/systems/geometry_systems/solver_system.rs index acc6a10..073fd06 100644 --- a/src/systems/geometry_systems/solver_system.rs +++ b/src/systems/geometry_systems/solver_system.rs @@ -318,7 +318,8 @@ impl<'a> System<'a> for SolverSystem { SketchGeometry::Circle(_, _) => stack.push(ToCompute::Circle(*entity)), }, SketchEvent::Remove(_, _, _) => (), // Do nothing since they are already removed - SketchEvent::Select(_) | SketchEvent::Deselect(_) => (), // Do nothing to select/deselect event + SketchEvent::Select(_) | + SketchEvent::Deselect(_) => (), // Do nothing to select/deselect event SketchEvent::MovePoint(ent, _) => { let dependents = dependency_graph.get_all_dependents(ent); for dependent in dependents { @@ -333,7 +334,9 @@ impl<'a> System<'a> for SolverSystem { stack.push(ToCompute::Circle(dependent)); } } - } + }, + SketchEvent::Hide(_, _) | + SketchEvent::Unhide(_, _) => (), } } } else { diff --git a/src/systems/interactions/hide/hide_selected_via_keyboard.rs b/src/systems/interactions/hide/hide_selected_via_keyboard.rs new file mode 100644 index 0000000..9f3b52d --- /dev/null +++ b/src/systems/interactions/hide/hide_selected_via_keyboard.rs @@ -0,0 +1,23 @@ +use specs::prelude::*; +use crate::{ + utilities::Key, + resources::{ + InputState, + events::{GeometryAction, GeometryActionChannel}, + }, +}; + +pub struct HideSelectedViaKeyboard; + +impl<'a> System<'a> for HideSelectedViaKeyboard { + type SystemData = ( + Read<'a, InputState>, + Write<'a, GeometryActionChannel>, + ); + + fn run(&mut self, (input_state, mut geometry_action_channel): Self::SystemData) { + if input_state.keyboard.just_activated(Key::H) && input_state.keyboard.is_command_activated() && !input_state.keyboard.is_shift_activated() { + geometry_action_channel.single_write(GeometryAction::HideSelected); + } + } +} \ No newline at end of file diff --git a/src/systems/interactions/hide/mod.rs b/src/systems/interactions/hide/mod.rs new file mode 100644 index 0000000..df2e262 --- /dev/null +++ b/src/systems/interactions/hide/mod.rs @@ -0,0 +1,2 @@ +mod hide_selected_via_keyboard; +pub use hide_selected_via_keyboard::*; \ No newline at end of file diff --git a/src/systems/interactions/mod.rs b/src/systems/interactions/mod.rs index 4f91818..8a7a830 100644 --- a/src/systems/interactions/mod.rs +++ b/src/systems/interactions/mod.rs @@ -4,6 +4,7 @@ pub mod create; pub mod update; pub mod remove; pub mod select; +pub mod hide; pub mod history; mod change_tool_via_keyboard; diff --git a/src/systems/window_system.rs b/src/systems/window_system.rs index 6fd9711..72a76af 100644 --- a/src/systems/window_system.rs +++ b/src/systems/window_system.rs @@ -7,7 +7,7 @@ use crate::{ DeltaTime, Viewport, ViewportTransform, InputState, events::{ExitEvent, ExitEventChannel, ViewportEvent, ViewportEventChannel, MouseEvent, MouseEventChannel}, }, - components::{Selected, Point, PointStyle, Line, LineStyle, Circle, CircleStyle, Rectangle, RectangleStyle}, + components::{Hidden, Selected, Point, PointStyle, Line, LineStyle, Circle, CircleStyle, Rectangle, RectangleStyle}, }; static CLICK_TIME_THRESHOLD : u128 = 100; // 0.1 second @@ -132,6 +132,7 @@ impl<'a> System<'a> for WindowSystem { ReadStorage<'a, Rectangle>, ReadStorage<'a, RectangleStyle>, ReadStorage<'a, Selected>, + ReadStorage<'a, Hidden>, ); fn run(&mut self, ( @@ -150,6 +151,7 @@ impl<'a> System<'a> for WindowSystem { rects, rect_styles, selected, + hidden, ): Self::SystemData) { // Reset information @@ -227,32 +229,32 @@ impl<'a> System<'a> for WindowSystem { clear(Color::white().into(), graphics); // We clean the screen // Fisrt draw regular lines - for (line, style, _) in (&lines, &line_styles, !&selected).join() { + for (line, style, _, _) in (&lines, &line_styles, !&selected, !&hidden).join() { draw_line(line, style, false, &*viewport, context, graphics); } // Fisrt draw lines - for (line, style, _) in (&lines, &line_styles, &selected).join() { + for (line, style, _, _) in (&lines, &line_styles, &selected, !&hidden).join() { draw_line(line, style, true, &*viewport, context, graphics); } // Draw regular circles - for (circle, style, _) in (&circles, &circle_styles, !&selected).join() { + for (circle, style, _, _) in (&circles, &circle_styles, !&selected, !&hidden).join() { draw_circle(circle, style, false, &*viewport, context, graphics); } // Draw selected circles - for (circle, style, _) in (&circles, &circle_styles, &selected).join() { + for (circle, style, _, _) in (&circles, &circle_styles, &selected, !&hidden).join() { draw_circle(circle, style, true, &*viewport, context, graphics); } // Then draw regular points (not selected) - for (point, style, _) in (&points, &point_styles, !&selected).join() { + for (point, style, _, _) in (&points, &point_styles, !&selected, !&hidden).join() { draw_point(point, style, false, &*viewport, context, graphics); } // Then draw selected points (as points are on top of lines) - for (point, style, _) in (&points, &point_styles, &selected).join() { + for (point, style, _, _) in (&points, &point_styles, &selected, !&hidden).join() { draw_point(point, style, true, &*viewport, context, graphics); }