use crate::{
command::make_command,
fyrox::{
core::{log::Log, pool::Handle},
generic_animation::machine::parameter::{
Parameter, ParameterContainer, ParameterDefinition,
},
graph::{PrefabData, SceneGraph, SceneGraphNode},
gui::{
inspector::{
editors::{
collection::VecCollectionPropertyEditorDefinition,
enumeration::EnumPropertyEditorDefinition,
inspectable::InspectablePropertyEditorDefinition,
PropertyEditorDefinitionContainer,
},
InspectorBuilder, InspectorContext, InspectorContextArgs, InspectorMessage,
PropertyAction,
},
message::UiMessage,
scroll_viewer::ScrollViewerBuilder,
widget::WidgetBuilder,
window::{WindowBuilder, WindowTitle},
BuildContext, UserInterface,
},
},
message::MessageSender,
plugins::absm::command::fetch_machine,
Message,
};
use fyrox::gui::inspector::Inspector;
use fyrox::gui::window::Window;
use std::sync::Arc;
pub struct ParameterPanel {
pub window: Handle<Window>,
inspector: Handle<Inspector>,
property_editors: Arc<PropertyEditorDefinitionContainer>,
}
impl ParameterPanel {
pub fn new(
ctx: &mut BuildContext,
property_editors: Arc<PropertyEditorDefinitionContainer>,
) -> Self {
property_editors
.insert(VecCollectionPropertyEditorDefinition::<ParameterDefinition>::new());
property_editors.insert(EnumPropertyEditorDefinition::<Parameter>::new());
property_editors.insert(InspectablePropertyEditorDefinition::<ParameterDefinition>::new());
let inspector;
let window = WindowBuilder::new(WidgetBuilder::new())
.with_title(WindowTitle::text("Parameters"))
.with_content(
ScrollViewerBuilder::new(WidgetBuilder::new())
.with_content({
inspector = InspectorBuilder::new(WidgetBuilder::new()).build(ctx);
inspector
})
.build(ctx),
)
.can_close(false)
.can_minimize(false)
.build(ctx);
Self {
window,
inspector,
property_editors,
}
}
pub fn on_selection_changed(
&self,
ui: &mut UserInterface,
parameters: Option<&ParameterContainer>,
) {
let inspector_context = parameters
.map(|parameters| {
InspectorContext::from_object(InspectorContextArgs {
object: parameters,
ctx: &mut ui.build_ctx(),
definition_container: self.property_editors.clone(),
environment: None,
layer_index: 0,
generate_property_string_values: true,
filter: Default::default(),
name_column_width: 150.0,
base_path: Default::default(),
has_parent_object: false,
})
})
.unwrap_or_default();
ui.send(self.inspector, InspectorMessage::Context(inspector_context));
}
pub fn reset(&self, ui: &UserInterface) {
ui.send(
self.inspector,
InspectorMessage::Context(Default::default()),
);
}
pub fn sync_to_model(&mut self, ui: &mut UserInterface, parameters: &ParameterContainer) {
let ctx = ui[self.inspector].context().clone();
if let Err(sync_errors) = ctx.sync(
parameters,
ui,
0,
true,
Default::default(),
Default::default(),
) {
for error in sync_errors {
Log::err(format!("Failed to sync property. Reason: {error:?}"))
}
}
}
pub fn handle_ui_message<P, G, N>(
&mut self,
message: &UiMessage,
sender: &MessageSender,
absm_node_handle: Handle<N>,
parameters: &mut ParameterContainer,
is_in_preview_mode: bool,
) where
P: PrefabData<Graph = G>,
G: SceneGraph<Node = N, Prefab = P>,
N: SceneGraphNode<SceneGraph = G, ResourceData = P>,
{
if let Some(InspectorMessage::PropertyChanged(args)) =
message.data_from::<InspectorMessage>(self.inspector)
{
if is_in_preview_mode {
PropertyAction::from_field_kind(&args.value).apply(
&args.path(),
parameters,
&mut |result| {
Log::verify(result);
},
);
} else {
sender.send(Message::DoCommand(
make_command(args, move |ctx| {
Some(fetch_machine(ctx, absm_node_handle).parameters_mut())
})
.unwrap(),
));
}
}
}
}