-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split out workcell editor #239
base: luca/model_workflows
Are you sure you want to change the base?
Changes from 24 commits
56c548c
d3ff2c6
260d263
f67733f
721696e
244df49
2884774
67b07e6
b6d2645
1bb998c
9251bb1
605fbe9
007f524
12f9371
4d44e3a
873ff9d
11357ca
6039f32
cbfeebf
d9b0ffe
1bc6bcf
29f290a
ef513f9
3496425
d7be917
df86e3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,11 +16,11 @@ | |
*/ | ||
|
||
use crate::site::{ | ||
update_anchor_transforms, CollisionMeshMarker, ConstraintMarker, DoorMarker, FiducialMarker, | ||
FloorMarker, LaneMarker, LiftCabin, LiftCabinDoorMarker, LocationTags, MeasurementMarker, | ||
SiteUpdateSet, VisualMeshMarker, WallMarker, | ||
update_anchor_transforms, CollisionMeshMarker, CurrentEditDrawing, CurrentLevel, DoorMarker, | ||
FiducialMarker, FloorMarker, LaneMarker, LiftCabin, LiftCabinDoorMarker, LocationTags, | ||
MeasurementMarker, SiteUpdateSet, ToggleLiftDoorAvailability, VisualMeshMarker, WallMarker, | ||
}; | ||
use crate::workcell::WorkcellVisualizationMarker; | ||
use crate::widgets::UserCameraDisplayPlugin; | ||
|
||
pub mod anchor; | ||
pub use anchor::*; | ||
|
@@ -151,11 +151,14 @@ impl Plugin for InteractionPlugin { | |
.init_resource::<Picked>() | ||
.init_resource::<PickingBlockers>() | ||
.init_resource::<GizmoState>() | ||
.init_resource::<CurrentEditDrawing>() | ||
.init_resource::<CurrentLevel>() | ||
.insert_resource(HighlightAnchors(false)) | ||
.add_event::<ChangePick>() | ||
.add_event::<MoveTo>() | ||
.add_event::<GizmoClicked>() | ||
.add_event::<SpawnPreview>() | ||
.add_event::<ToggleLiftDoorAvailability>() | ||
.add_plugins(( | ||
OutlinePlugin, | ||
CategoryVisibilityPlugin::<DoorMarker>::visible(true), | ||
|
@@ -165,14 +168,16 @@ impl Plugin for InteractionPlugin { | |
CategoryVisibilityPlugin::<LiftCabinDoorMarker>::visible(true), | ||
CategoryVisibilityPlugin::<LocationTags>::visible(true), | ||
CategoryVisibilityPlugin::<FiducialMarker>::visible(true), | ||
CategoryVisibilityPlugin::<ConstraintMarker>::visible(true), | ||
CategoryVisibilityPlugin::<VisualMeshMarker>::visible(true), | ||
CategoryVisibilityPlugin::<CollisionMeshMarker>::visible(false), | ||
CategoryVisibilityPlugin::<MeasurementMarker>::visible(true), | ||
CategoryVisibilityPlugin::<WallMarker>::visible(true), | ||
CategoryVisibilityPlugin::<WorkcellVisualizationMarker>::visible(true), | ||
)) | ||
.add_plugins((CameraControlsPlugin, ModelPreviewPlugin)); | ||
.add_plugins(( | ||
CameraControlsPlugin, | ||
ModelPreviewPlugin, | ||
UserCameraDisplayPlugin::default(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to resource initialization, the interaction plugin panics if this plugin is not present, so I added it here rather than keeping it in the widgets to decouple widget plugin and interaction plugin. |
||
)); | ||
|
||
if !self.headless { | ||
app.add_plugins(SelectionPlugin::default()) | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -15,8 +15,11 @@ | |||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
use crate::{interaction::select::*, site::Model}; | ||||||||||||||||||||||||||||
use bevy::ecs::system::SystemParam; | ||||||||||||||||||||||||||||
use crate::{ | ||||||||||||||||||||||||||||
interaction::select::*, | ||||||||||||||||||||||||||||
site::{CurrentLevel, Model}, | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
use bevy::ecs::system::{Command, SystemParam, SystemState}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
#[derive(Default)] | ||||||||||||||||||||||||||||
pub struct ObjectPlacementPlugin {} | ||||||||||||||||||||||||||||
|
@@ -31,38 +34,28 @@ impl Plugin for ObjectPlacementPlugin { | |||||||||||||||||||||||||||
#[derive(Resource, Clone, Copy)] | ||||||||||||||||||||||||||||
pub struct ObjectPlacementServices { | ||||||||||||||||||||||||||||
pub place_object_2d: Service<Option<Entity>, ()>, | ||||||||||||||||||||||||||||
pub place_object_3d: Service<Option<Entity>, ()>, | ||||||||||||||||||||||||||||
pub replace_parent_3d: Service<Option<Entity>, ()>, | ||||||||||||||||||||||||||||
pub hover_service_object_3d: Service<(), (), Hover>, | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
impl ObjectPlacementServices { | ||||||||||||||||||||||||||||
pub fn from_app(app: &mut App) -> Self { | ||||||||||||||||||||||||||||
let hover_service_object_3d = app.spawn_continuous_service( | ||||||||||||||||||||||||||||
Update, | ||||||||||||||||||||||||||||
hover_service::<PlaceObject3dFilter> | ||||||||||||||||||||||||||||
.configure(|config: SystemConfigs| config.in_set(SelectionServiceStages::Hover)), | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
let place_object_2d = spawn_place_object_2d_workflow(app); | ||||||||||||||||||||||||||||
let place_object_3d = spawn_place_object_3d_workflow(hover_service_object_3d, app); | ||||||||||||||||||||||||||||
let replace_parent_3d = spawn_replace_parent_3d_workflow(hover_service_object_3d, app); | ||||||||||||||||||||||||||||
Self { | ||||||||||||||||||||||||||||
place_object_2d, | ||||||||||||||||||||||||||||
place_object_3d, | ||||||||||||||||||||||||||||
replace_parent_3d, | ||||||||||||||||||||||||||||
hover_service_object_3d, | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
Self { place_object_2d } | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
#[derive(SystemParam)] | ||||||||||||||||||||||||||||
pub struct ObjectPlacement<'w, 's> { | ||||||||||||||||||||||||||||
pub services: Res<'w, ObjectPlacementServices>, | ||||||||||||||||||||||||||||
pub commands: Commands<'w, 's>, | ||||||||||||||||||||||||||||
current_level: Res<'w, CurrentLevel>, | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
impl<'w, 's> ObjectPlacement<'w, 's> { | ||||||||||||||||||||||||||||
pub fn place_object_2d(&mut self, object: Model, level: Entity) { | ||||||||||||||||||||||||||||
pub fn place_object_2d(&mut self, object: Model) { | ||||||||||||||||||||||||||||
let Some(level) = self.current_level.0 else { | ||||||||||||||||||||||||||||
warn!("Unble to create [object:?] outside a level"); | ||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
Comment on lines
-65
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is part of my effort to reduce code duplication. I refactored both 2d and 3d object placement to take the same input (just a rmf_site/rmf_site_editor/src/widgets/fuel_asset_browser.rs Lines 28 to 40 in 3496425
|
||||||||||||||||||||||||||||
let state = self | ||||||||||||||||||||||||||||
.commands | ||||||||||||||||||||||||||||
.spawn(SelectorInput(PlaceObject2d { object, level })) | ||||||||||||||||||||||||||||
|
@@ -73,40 +66,32 @@ impl<'w, 's> ObjectPlacement<'w, 's> { | |||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
pub fn place_object_3d( | ||||||||||||||||||||||||||||
&mut self, | ||||||||||||||||||||||||||||
object: PlaceableObject, | ||||||||||||||||||||||||||||
parent: Option<Entity>, | ||||||||||||||||||||||||||||
workspace: Entity, | ||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||
let state = self | ||||||||||||||||||||||||||||
.commands | ||||||||||||||||||||||||||||
.spawn(SelectorInput(PlaceObject3d { | ||||||||||||||||||||||||||||
object, | ||||||||||||||||||||||||||||
parent, | ||||||||||||||||||||||||||||
workspace, | ||||||||||||||||||||||||||||
})) | ||||||||||||||||||||||||||||
.id(); | ||||||||||||||||||||||||||||
self.send(RunSelector { | ||||||||||||||||||||||||||||
selector: self.services.place_object_3d, | ||||||||||||||||||||||||||||
input: Some(state), | ||||||||||||||||||||||||||||
fn send(&mut self, run: RunSelector) { | ||||||||||||||||||||||||||||
self.commands.add(move |world: &mut World| { | ||||||||||||||||||||||||||||
world.send_event(run); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
pub fn replace_parent_3d(&mut self, object: Entity, workspace: Entity) { | ||||||||||||||||||||||||||||
let state = self | ||||||||||||||||||||||||||||
.commands | ||||||||||||||||||||||||||||
.spawn(SelectorInput(ReplaceParent3d { object, workspace })) | ||||||||||||||||||||||||||||
.id(); | ||||||||||||||||||||||||||||
self.send(RunSelector { | ||||||||||||||||||||||||||||
selector: self.services.replace_parent_3d, | ||||||||||||||||||||||||||||
input: Some(state), | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
/// Trait to be implemented to allow placing models with commands | ||||||||||||||||||||||||||||
pub trait ObjectPlacementExt<'w, 's> { | ||||||||||||||||||||||||||||
fn place_object_2d(&mut self, object: Model); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
impl<'w, 's> ObjectPlacementExt<'w, 's> for Commands<'w, 's> { | ||||||||||||||||||||||||||||
fn place_object_2d(&mut self, object: Model) { | ||||||||||||||||||||||||||||
self.add(ObjectPlaceCommand(object)); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
fn send(&mut self, run: RunSelector) { | ||||||||||||||||||||||||||||
self.commands.add(move |world: &mut World| { | ||||||||||||||||||||||||||||
world.send_event(run); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
#[derive(Deref, DerefMut)] | ||||||||||||||||||||||||||||
pub struct ObjectPlaceCommand(Model); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
impl Command for ObjectPlaceCommand { | ||||||||||||||||||||||||||||
fn apply(self, world: &mut World) { | ||||||||||||||||||||||||||||
let mut system_state: SystemState<ObjectPlacement> = SystemState::new(world); | ||||||||||||||||||||||||||||
let mut placement = system_state.get_mut(world); | ||||||||||||||||||||||||||||
placement.place_object_2d(self.0); | ||||||||||||||||||||||||||||
system_state.apply(world); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This resource initialization has been moved here from other plugins since the
InteractionPlugin
will panic if used in a third party app without them.An alternative solution could be to split the interaction plugin into several sub-plugins and allow users to only include the ones they need, but that would have been a much larger refactor so I left it out for now.