mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
ability to add/remove interaction modes dynamically
This commit is contained in:
@@ -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(..)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ pub enum Message {
|
||||
SaveLayout,
|
||||
LoadLayout,
|
||||
ViewSurfaceData(SurfaceResource),
|
||||
SyncInteractionModes,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user