diff --git a/editor/src/inspector/handlers/node/mod.rs b/editor/src/inspector/handlers/node/mod.rs index 29df5f8d6..aa0eee13c 100644 --- a/editor/src/inspector/handlers/node/mod.rs +++ b/editor/src/inspector/handlers/node/mod.rs @@ -1,33 +1,43 @@ use crate::{ - scene::commands::{make_set_node_property_command, terrain::AddTerrainLayerCommandConstructor}, + scene::commands::{ + make_set_node_property_command, + terrain::{AddTerrainLayerCommand, DeleteTerrainLayerCommand}, + }, SceneCommand, }; use fyrox::{ core::pool::Handle, - fxhash::FxHashMap, - gui::inspector::PropertyChanged, + gui::inspector::{CollectionChanged, FieldKind, PropertyChanged}, scene::{node::Node, terrain::Terrain}, }; +use std::any::TypeId; -/// A set of constructors for special cases, when simple reflection is not enough. -pub trait CommandConstructor { - fn make_command(&self, handle: Handle, node: &mut Node) -> SceneCommand; -} - -pub struct SceneNodePropertyChangedHandler { - unique_handlers: FxHashMap>, -} +pub struct SceneNodePropertyChangedHandler; impl SceneNodePropertyChangedHandler { - pub fn new() -> Self { - let mut unique_handlers = FxHashMap::>::default(); - - unique_handlers.insert( - Terrain::LAYERS.to_string(), - Box::new(AddTerrainLayerCommandConstructor), - ); - - Self { unique_handlers } + fn try_get_command( + &self, + args: &PropertyChanged, + handle: Handle, + node: &mut Node, + ) -> Option { + // Terrain is special and have its own commands for specific properties. + if args.path() == Terrain::LAYERS && args.owner_type_id == TypeId::of::() { + match args.value { + FieldKind::Collection(ref collection_changed) => match **collection_changed { + CollectionChanged::Add(_) => Some(SceneCommand::new( + AddTerrainLayerCommand::new(handle, node.as_terrain()), + )), + CollectionChanged::Remove(index) => Some(SceneCommand::new( + DeleteTerrainLayerCommand::new(handle, index), + )), + CollectionChanged::ItemChanged { .. } => None, + }, + _ => None, + } + } else { + None + } } } @@ -37,11 +47,8 @@ impl SceneNodePropertyChangedHandler { args: &PropertyChanged, handle: Handle, node: &mut Node, - ) -> Option { - if let Some(constructor) = self.unique_handlers.get(&args.path()) { - Some(constructor.make_command(handle, node)) - } else { - Some(make_set_node_property_command(handle, args)) - } + ) -> SceneCommand { + self.try_get_command(args, handle, node) + .unwrap_or_else(|| make_set_node_property_command(handle, args)) } } diff --git a/editor/src/inspector/mod.rs b/editor/src/inspector/mod.rs index 83ea56942..7eb6f70df 100644 --- a/editor/src/inspector/mod.rs +++ b/editor/src/inspector/mod.rs @@ -153,7 +153,7 @@ impl Inspector { inspector, property_editors, needs_sync: true, - node_property_changed_handler: SceneNodePropertyChangedHandler::new(), + node_property_changed_handler: SceneNodePropertyChangedHandler, warning_text, } } @@ -317,11 +317,11 @@ impl Inspector { .iter() .filter_map(|&node_handle| { if scene.graph.is_valid_handle(node_handle) { - self.node_property_changed_handler.handle( + Some(self.node_property_changed_handler.handle( args, node_handle, &mut scene.graph[node_handle], - ) + )) } else { None } diff --git a/editor/src/scene/commands/terrain.rs b/editor/src/scene/commands/terrain.rs index c4fd28a73..457b157bb 100644 --- a/editor/src/scene/commands/terrain.rs +++ b/editor/src/scene/commands/terrain.rs @@ -1,7 +1,4 @@ -use crate::{ - command::Command, create_terrain_layer_material, inspector::handlers::node::CommandConstructor, - scene::commands::SceneContext, SceneCommand, -}; +use crate::{command::Command, create_terrain_layer_material, scene::commands::SceneContext}; use fyrox::{ core::pool::Handle, scene::{node::Node, terrain::Layer, terrain::Terrain}, @@ -13,14 +10,6 @@ pub struct AddTerrainLayerCommand { layer: Option, } -pub struct AddTerrainLayerCommandConstructor; - -impl CommandConstructor for AddTerrainLayerCommandConstructor { - fn make_command(&self, handle: Handle, node: &mut Node) -> SceneCommand { - SceneCommand::new(AddTerrainLayerCommand::new(handle, node.as_terrain())) - } -} - impl AddTerrainLayerCommand { pub fn new(terrain_handle: Handle, terrain: &Terrain) -> Self { Self { @@ -50,6 +39,42 @@ impl Command for AddTerrainLayerCommand { } } +#[derive(Debug)] +pub struct DeleteTerrainLayerCommand { + terrain: Handle, + layer: Option, + index: usize, +} + +impl DeleteTerrainLayerCommand { + pub fn new(terrain: Handle, index: usize) -> Self { + Self { + terrain, + layer: Default::default(), + index, + } + } +} + +impl Command for DeleteTerrainLayerCommand { + fn name(&mut self, _context: &SceneContext) -> String { + "Delete Terrain Layer".to_owned() + } + + fn execute(&mut self, context: &mut SceneContext) { + self.layer = Some( + context.scene.graph[self.terrain] + .as_terrain_mut() + .remove_layer(self.index), + ); + } + + fn revert(&mut self, context: &mut SceneContext) { + let terrain = context.scene.graph[self.terrain].as_terrain_mut(); + terrain.insert_layer(self.layer.take().unwrap(), self.index); + } +} + #[derive(Debug)] pub struct ModifyTerrainHeightCommand { terrain: Handle,