use crate::scene::EntityInfo;
use crate::{
command::{make_command, Command, SetPropertyCommand},
fyrox::{
core::{
pool::{ErasedHandle, Handle},
reflect::Reflect,
uuid::Uuid,
variable::InheritableVariable,
},
engine::Engine,
generic_animation::{Animation, AnimationContainer},
graph::{SceneGraph, SceneGraphNode},
gui::inspector::PropertyChanged,
scene::SceneContainer,
},
message::MessageSender,
plugins::{animation, animation::command::fetch_animations_container},
scene::{controller::SceneController, GameScene, SelectionContainer},
ui_scene::UiScene,
};
use std::fmt::{Debug, Formatter};
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SelectedEntity {
Track(Uuid),
Curve(Uuid),
Signal(Uuid),
}
#[derive(Eq)]
pub struct AnimationSelection<N>
where
N: Reflect,
{
pub animation_player: Handle<N>,
pub animation: Handle<Animation<Handle<N>>>,
pub entities: Vec<SelectedEntity>,
}
impl<N> Debug for AnimationSelection<N>
where
N: Reflect,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} {} {:?}",
self.animation_player, self.animation, self.entities
)
}
}
impl<N> Clone for AnimationSelection<N>
where
N: Reflect,
{
fn clone(&self) -> Self {
Self {
animation_player: self.animation_player,
animation: self.animation,
entities: self.entities.clone(),
}
}
}
impl<N> PartialEq for AnimationSelection<N>
where
N: Reflect,
{
fn eq(&self, other: &Self) -> bool {
self.entities == other.entities
&& self.animation == other.animation
&& self.animation_player == other.animation_player
}
}
pub fn get_animations_container<'a, N: Reflect>(
handle: Handle<N>,
controller: &'a dyn SceneController,
scenes: &'a SceneContainer,
) -> Option<&'a InheritableVariable<AnimationContainer<Handle<N>>>> {
if let Some(game_scene) = controller.downcast_ref::<GameScene>() {
scenes[game_scene.scene]
.graph
.node(ErasedHandle::from(handle).into())
.component_ref::<InheritableVariable<AnimationContainer<Handle<N>>>>()
} else if let Some(ui) = controller.downcast_ref::<UiScene>() {
ui.ui
.node(ErasedHandle::from(handle).into())
.component_ref::<InheritableVariable<AnimationContainer<Handle<N>>>>()
} else {
None
}
}
impl<N> SelectionContainer for AnimationSelection<N>
where
N: Reflect,
{
fn len(&self) -> usize {
self.entities.len()
}
fn first_selected_entity(
&self,
controller: &dyn SceneController,
scenes: &SceneContainer,
callback: &mut dyn FnMut(EntityInfo),
) {
if let Some(container) = get_animations_container(self.animation_player, controller, scenes)
{
if let Ok(animation) = container.try_get(self.animation) {
if let Some(animation::selection::SelectedEntity::Signal(id)) =
self.entities.first()
{
if let Some(signal) = animation.signals().iter().find(|s| s.id == *id) {
(callback)(EntityInfo::with_no_parent(signal as &dyn Reflect));
}
}
}
}
}
fn on_property_changed(
&mut self,
_controller: &mut dyn SceneController,
args: &PropertyChanged,
_engine: &mut Engine,
sender: &MessageSender,
) {
let animation_player = self.animation_player;
let animation = self.animation;
let group: Vec<Command> = self
.entities
.iter()
.filter_map(|e| {
if let &animation::selection::SelectedEntity::Signal(id) = e {
make_command(args, move |ctx| {
fetch_animations_container(animation_player, ctx)[animation]
.signals_mut()
.iter_mut()
.find(|s| s.id == id)
.map(|s| s as &mut dyn Reflect)
})
} else {
None
}
})
.collect();
sender.do_command_group_with_inheritance(group, args);
}
fn paste_property(&mut self, path: &str, value: &dyn Reflect, sender: &MessageSender) {
let animation_player = self.animation_player;
let animation = self.animation;
let group = self
.entities
.iter()
.filter_map(|e| {
if let &animation::selection::SelectedEntity::Signal(id) = e {
value.try_clone_box().map(|value| {
Command::new(SetPropertyCommand::new(
path.to_string(),
value,
move |ctx| {
fetch_animations_container(animation_player, ctx)[animation]
.signals_mut()
.iter_mut()
.find(|s| s.id == id)
.map(|s| s as &mut dyn Reflect)
},
))
})
} else {
None
}
})
.collect();
sender.do_command_group(group);
}
fn provide_docs(&self, controller: &dyn SceneController, engine: &Engine) -> Option<String> {
if let Some(game_scene) = controller.downcast_ref::<GameScene>() {
Some(
engine.scenes[game_scene.scene]
.graph
.node(ErasedHandle::from(self.animation_player).into())
.doc()
.to_string(),
)
} else {
controller.downcast_ref::<UiScene>().map(|ui| {
ui.ui
.node(ErasedHandle::from(self.animation_player).into())
.doc()
.to_string()
})
}
}
}
impl<N> AnimationSelection<N>
where
N: Reflect,
{
pub fn first_selected_track(&self) -> Option<Uuid> {
self.entities.iter().find_map(|e| {
if let SelectedEntity::Track(id) = e {
Some(*id)
} else {
None
}
})
}
}