ability to add/remove interaction modes dynamically

This commit is contained in:
Dmitry Stepanov
2024-06-17 22:58:57 +03:00
parent b73362bb84
commit f2d8b968ec
5 changed files with 52 additions and 4 deletions
+32 -1
View File
@@ -5,6 +5,7 @@ use crate::{
color::Color,
pool::Handle,
uuid::Uuid,
TypeUuidProvider,
},
gui::{
border::BorderBuilder,
@@ -22,9 +23,10 @@ use crate::{
scene::{camera::Projection, graph::Graph, node::Node},
},
load_image,
message::MessageSender,
scene::{controller::SceneController, Selection},
settings::Settings,
Engine,
Engine, Message,
};
use std::any::Any;
@@ -41,6 +43,8 @@ pub trait BaseInteractionMode: 'static {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
}
impl<T> BaseInteractionMode for T
@@ -54,6 +58,10 @@ where
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
}
pub trait InteractionMode: BaseInteractionMode {
@@ -228,11 +236,33 @@ pub struct InteractionModeContainer {
// is not an issue, because there are tiny amount of modes anyway (currently - max 5) and linear
// search is faster in such conditions.
container: Vec<Box<dyn InteractionMode>>,
pub sender: Option<MessageSender>,
}
impl InteractionModeContainer {
fn try_notify_changed(&self) {
if let Some(sender) = self.sender.as_ref() {
sender.send(Message::SyncInteractionModes);
}
}
pub fn add<T: InteractionMode>(&mut self, mode: T) {
self.container.push(Box::new(mode));
self.try_notify_changed();
}
pub fn remove(&mut self, id: &Uuid) -> Option<Box<dyn InteractionMode>> {
if let Some(position) = self.container.iter().position(|mode| mode.uuid() == *id) {
self.try_notify_changed();
Some(self.container.remove(position))
} else {
None
}
}
pub fn remove_typed<T: InteractionMode + TypeUuidProvider>(&mut self) -> Option<Box<T>> {
self.remove(&T::type_uuid())
.and_then(|mode| mode.into_any().downcast::<T>().ok())
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut dyn InteractionMode> + '_ {
@@ -254,6 +284,7 @@ impl InteractionModeContainer {
}
pub fn drain(&mut self) -> impl Iterator<Item = Box<dyn InteractionMode>> + '_ {
self.try_notify_changed();
self.container.drain(..)
}
}
+6
View File
@@ -2488,6 +2488,12 @@ impl Editor {
viewer.open(data, &mut self.engine);
self.surface_data_viewer = Some(viewer);
}
Message::SyncInteractionModes => {
self.scene_viewer.sync_interaction_modes(
self.scenes.current_scene_entry_mut(),
self.engine.user_interfaces.first_mut(),
);
}
_ => (),
}
}
+1
View File
@@ -78,6 +78,7 @@ pub enum Message {
SaveLayout,
LoadLayout,
ViewSurfaceData(SurfaceResource),
SyncInteractionModes,
}
#[derive(Clone, Debug)]
+2
View File
@@ -93,6 +93,7 @@ impl EditorSceneEntry {
message_sender.clone(),
scene_viewer.frame(),
));
interaction_modes.sender = Some(message_sender.clone());
let mut entry = EditorSceneEntry {
has_unsaved_changes: false,
@@ -128,6 +129,7 @@ impl EditorSceneEntry {
message_sender.clone(),
));
interaction_modes.add(MoveWidgetsInteractionMode::new(message_sender.clone()));
interaction_modes.sender = Some(message_sender.clone());
let mut entry = EditorSceneEntry {
has_unsaved_changes: false,
+11 -3
View File
@@ -592,9 +592,9 @@ impl SceneViewer {
}
}
pub fn on_current_scene_changed(
pub fn sync_interaction_modes(
&mut self,
new_scene: Option<&mut EditorSceneEntry>,
scene: Option<&mut EditorSceneEntry>,
ui: &mut UserInterface,
) {
// Remove interaction mode buttons first.
@@ -603,7 +603,7 @@ impl SceneViewer {
}
// Create new buttons for each mode.
if let Some(scene_entry) = new_scene {
if let Some(scene_entry) = scene {
for mode in scene_entry.interaction_modes.iter_mut() {
let button = mode.make_button(
&mut ui.build_ctx(),
@@ -619,6 +619,14 @@ impl SceneViewer {
}
}
pub fn on_current_scene_changed(
&mut self,
new_scene: Option<&mut EditorSceneEntry>,
ui: &mut UserInterface,
) {
self.sync_interaction_modes(new_scene, ui)
}
pub fn handle_ui_message(
&mut self,
message: &mut UiMessage,