From a2204cea3a91c7822e730eda923d0502a94c4a6a Mon Sep 17 00:00:00 2001 From: "Michael X. Grey" Date: Thu, 6 Jun 2024 08:56:23 +0000 Subject: [PATCH] Making floor grid available to all edit modes Signed-off-by: Michael X. Grey --- rmf_site_editor/src/floor_grid.rs | 49 +++++++++++++++++++++++++++++ rmf_site_editor/src/lib.rs | 4 +++ rmf_site_editor/src/shapes.rs | 3 +- rmf_site_editor/src/view_menu.rs | 31 +++++++++++++++--- rmf_site_editor/src/workcell/mod.rs | 30 +++++------------- 5 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 rmf_site_editor/src/floor_grid.rs diff --git a/rmf_site_editor/src/floor_grid.rs b/rmf_site_editor/src/floor_grid.rs new file mode 100644 index 00000000..0c43def1 --- /dev/null +++ b/rmf_site_editor/src/floor_grid.rs @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +use bevy::prelude::{Entity, Resource, World, FromWorld, Plugin, App}; +use bevy_infinite_grid::InfiniteGridPlugin; + +use crate::shapes::make_infinite_grid; + +#[derive(Resource)] +pub struct FloorGrid { + entity: Entity, +} + +impl FloorGrid { + pub fn get(&self) -> Entity { + self.entity + } +} + +impl FromWorld for FloorGrid { + fn from_world(world: &mut World) -> Self { + let entity = world.spawn(make_infinite_grid(1.0, 100.0, None)).id(); + Self { entity } + } +} + +pub struct FloorGridPlugin; + +impl Plugin for FloorGridPlugin { + fn build(&self, app: &mut App) { + app + .add_plugins(InfiniteGridPlugin) + .init_resource::(); + } +} diff --git a/rmf_site_editor/src/lib.rs b/rmf_site_editor/src/lib.rs index ffc25c81..281a2de9 100644 --- a/rmf_site_editor/src/lib.rs +++ b/rmf_site_editor/src/lib.rs @@ -53,6 +53,9 @@ use view_menu::*; pub mod wireframe; use wireframe::*; +pub mod floor_grid; +use floor_grid::*; + use aabb::AabbUpdatePlugin; use animate::AnimationPlugin; use interaction::InteractionPlugin; @@ -190,6 +193,7 @@ impl Plugin for SiteEditor { AnimationPlugin, OccupancyPlugin, WorkspacePlugin, + FloorGridPlugin, )) // Note order matters, plugins that edit the menus must be initialized after the UI .add_plugins(( diff --git a/rmf_site_editor/src/shapes.rs b/rmf_site_editor/src/shapes.rs index 1d173766..b14223db 100644 --- a/rmf_site_editor/src/shapes.rs +++ b/rmf_site_editor/src/shapes.rs @@ -1254,7 +1254,8 @@ pub(crate) fn make_infinite_grid( settings.fadeout_distance = fadeout_distance; settings.shadow_color = shadow_color; let transform = Transform::from_rotation(Quat::from_rotation_x(90_f32.to_radians())) - .with_scale(Vec3::splat(scale)); + .with_scale(Vec3::splat(scale)) + .with_translation(Vec3::new(0.0, 0.0, -0.005)); InfiniteGridBundle { settings, diff --git a/rmf_site_editor/src/view_menu.rs b/rmf_site_editor/src/view_menu.rs index a4586b16..abbdf321 100644 --- a/rmf_site_editor/src/view_menu.rs +++ b/rmf_site_editor/src/view_menu.rs @@ -20,9 +20,11 @@ use crate::site::{ CollisionMeshMarker, DoorMarker, FiducialMarker, FloorMarker, LaneMarker, LiftCabin, LiftCabinDoorMarker, LocationTags, MeasurementMarker, VisualMeshMarker, WallMarker, }; -use crate::widgets::menu_bar::{MenuEvent, MenuItem, MenuVisualizationStates, ViewMenu}; -use crate::workcell::WorkcellVisualizationMarker; -use crate::AppState; +use crate::{ + widgets::menu_bar::{MenuEvent, MenuItem, MenuVisualizationStates, ViewMenu}, + workcell::WorkcellVisualizationMarker, + AppState, FloorGrid, +}; use bevy::ecs::system::SystemParam; use bevy::prelude::*; use std::collections::HashSet; @@ -59,6 +61,7 @@ pub struct ViewMenuItems { visuals: Entity, walls: Entity, origin_axis: Entity, + floor_grid: Entity, } impl FromWorld for ViewMenuItems { @@ -150,7 +153,7 @@ impl FromWorld for ViewMenuItems { "Visual meshes".to_string(), default_visibility.0, )) - .insert(MenuVisualizationStates(active_states)) + .insert(MenuVisualizationStates(active_states.clone())) .set_parent(view_header) .id(); let default_visibility = world.resource::>(); @@ -172,6 +175,14 @@ impl FromWorld for ViewMenuItems { .insert(MenuVisualizationStates(workcell_states)) .set_parent(view_header) .id(); + let floor_grid = world + .spawn(MenuItem::CheckBox( + "Floor grid".to_string(), + true, + )) + .insert(MenuVisualizationStates(active_states)) + .set_parent(view_header) + .id(); ViewMenuItems { doors, @@ -185,6 +196,7 @@ impl FromWorld for ViewMenuItems { visuals, walls, origin_axis, + floor_grid, } } } @@ -194,6 +206,8 @@ fn handle_view_menu_events( view_menu: Res, mut menu_items: Query<&mut MenuItem>, mut events: VisibilityEvents, + floor_grid: Res, + mut visibility: Query<&mut Visibility>, ) { let mut toggle = |entity| { let mut menu = menu_items.get_mut(entity).unwrap(); @@ -226,6 +240,15 @@ fn handle_view_menu_events( events.walls.send(toggle(event.source()).into()); } else if event.clicked() && event.source() == view_menu.origin_axis { events.origin_axis.send(toggle(event.source()).into()); + } else if event.clicked() && event.source() == view_menu.floor_grid { + let floor_grid_visible = toggle(event.source()); + if let Ok(mut vis) = visibility.get_mut(floor_grid.get()) { + if floor_grid_visible { + *vis = Visibility::Visible; + } else { + *vis = Visibility::Hidden; + } + } } } } diff --git a/rmf_site_editor/src/workcell/mod.rs b/rmf_site_editor/src/workcell/mod.rs index 4992fbef..6d0f1dfd 100644 --- a/rmf_site_editor/src/workcell/mod.rs +++ b/rmf_site_editor/src/workcell/mod.rs @@ -42,42 +42,26 @@ pub mod workcell; pub use workcell::*; use bevy::prelude::*; -use bevy_infinite_grid::{InfiniteGrid, InfiniteGridPlugin}; use crate::AppState; -use crate::{ - shapes::make_infinite_grid, - site::{ - clear_model_trashcan, handle_model_loaded_events, handle_new_primitive_shapes, - handle_update_fuel_cache_requests, make_models_selectable, propagate_model_render_layers, - read_update_fuel_cache_results, reload_failed_models_with_new_api_key, - update_anchor_transforms, update_model_scales, update_model_scenes, - update_model_tentative_formats, update_transforms_for_changed_poses, - }, +use crate::site::{ + clear_model_trashcan, handle_model_loaded_events, handle_new_primitive_shapes, + handle_update_fuel_cache_requests, make_models_selectable, propagate_model_render_layers, + read_update_fuel_cache_results, reload_failed_models_with_new_api_key, + update_anchor_transforms, update_model_scales, update_model_scenes, + update_model_tentative_formats, update_transforms_for_changed_poses, }; #[derive(Default)] pub struct WorkcellEditorPlugin; -fn spawn_grid(mut commands: Commands) { - commands.spawn(make_infinite_grid(1.0, 100.0, None)); -} - -fn delete_grid(mut commands: Commands, grids: Query>) { - for grid in grids.iter() { - commands.entity(grid).despawn_recursive(); - } -} - impl Plugin for WorkcellEditorPlugin { fn build(&self, app: &mut App) { - app.add_plugins(InfiniteGridPlugin) + app .add_event::() .add_event::() .add_event::() .add_event::() - .add_systems(OnEnter(AppState::WorkcellEditor), spawn_grid) - .add_systems(OnExit(AppState::WorkcellEditor), delete_grid) .add_systems( Update, (