diff --git a/.idea/rg3d-core.iml b/.idea/rg3d-core.iml index a9ad7420a..19864a77b 100644 --- a/.idea/rg3d-core.iml +++ b/.idea/rg3d-core.iml @@ -31,6 +31,7 @@ + diff --git a/Cargo.toml b/Cargo.toml index c689867bb..f71adce6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ members = [ "fyrox-ui", "fyrox-resource", "fyrox-scripts", + "fyrox-animation", "editor", "editor-standalone", "template" @@ -41,6 +42,7 @@ fyrox-core = { path = "fyrox-core", version = "0.26.0", features = ["serde"] } fyrox-sound = { path = "fyrox-sound", version = "0.33.0" } fyrox-ui = { path = "fyrox-ui", version = "0.23.0" } fyrox-resource = { path = "fyrox-resource", version = "0.10.0" } +fyrox-animation = { path = "fyrox-animation", version = "0.1.0" } rapier2d = { version = "0.17", features = ["debug-render"] } rapier3d = { version = "0.17", features = ["debug-render"] } image = { version = "0.24.3", default-features = false, features = ["gif", "jpeg", "png", "tga", "tiff", "bmp"] } @@ -58,7 +60,6 @@ fxhash = "0.2.1" strum = "0.25.0" strum_macros = "0.25.0" clap = { version = "4", features = ["derive"] } -spade = "2.1.0" winit = { version = "0.29.2", features = ["serde"] } half = "2.2.1" fast_image_resize = "2.7.0" diff --git a/editor/src/absm/blendspace.rs b/editor/src/absm/blendspace.rs index 7373a7e1a..726bcaa3e 100644 --- a/editor/src/absm/blendspace.rs +++ b/editor/src/absm/blendspace.rs @@ -11,6 +11,7 @@ use crate::{ send_sync_message, }; use fyrox::core::uuid_provider; +use fyrox::scene::node::Node; use fyrox::{ animation::machine::{ node::blendspace::BlendSpacePoint, Machine, MachineLayer, Parameter, ParameterContainer, @@ -811,7 +812,7 @@ impl BlendSpaceEditor { pub fn sync_to_model( &mut self, parameters: &ParameterContainer, - layer: &MachineLayer, + layer: &MachineLayer>, selection: &AbsmSelection, ui: &mut UserInterface, ) { @@ -893,7 +894,7 @@ impl BlendSpaceEditor { selection: &AbsmSelection, message: &UiMessage, sender: &MessageSender, - machine: &mut Machine, + machine: &mut Machine>, is_preview_mode_active: bool, ) { if let Some(SelectedEntity::PoseNode(first)) = selection.entities.first() { diff --git a/editor/src/absm/command/blend.rs b/editor/src/absm/command/blend.rs index 5033432e9..ad89d1b4c 100644 --- a/editor/src/absm/command/blend.rs +++ b/editor/src/absm/command/blend.rs @@ -13,7 +13,7 @@ use fyrox::{ scene::node::Node, }; -define_push_element_to_collection_command!(AddInputCommand, IndexedBlendInput>(self, context) { +define_push_element_to_collection_command!(AddInputCommand>>, IndexedBlendInput>>(self, context) { let machine = fetch_machine(context, self.node_handle); match &mut machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { PoseNode::BlendAnimationsByIndex(definition) => &mut definition.inputs, @@ -21,7 +21,7 @@ define_push_element_to_collection_command!(AddInputCommand, Ind } }); -define_push_element_to_collection_command!(AddPoseSourceCommand, BlendPose>(self, context) { +define_push_element_to_collection_command!(AddPoseSourceCommand>>, BlendPose>>(self, context) { let machine = fetch_machine(context, self.node_handle); match &mut machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { PoseNode::BlendAnimations(definition) => &mut definition.pose_sources, @@ -29,7 +29,7 @@ define_push_element_to_collection_command!(AddPoseSourceCommand } }); -define_push_element_to_collection_command!(AddBlendSpacePointCommand, BlendSpacePoint>(self, context) { +define_push_element_to_collection_command!(AddBlendSpacePointCommand>>, BlendSpacePoint>>(self, context) { let machine = fetch_machine(context, self.node_handle); match &mut machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { PoseNode::BlendSpace(definition) => definition.points_mut(), @@ -38,7 +38,7 @@ define_push_element_to_collection_command!(AddBlendSpacePointCommand, Handle>(self, context) { + SetBlendAnimationByIndexInputPoseSourceCommand>>, Handle>>>(self, context) { let machine = fetch_machine(context, self.node_handle); if let PoseNode::BlendAnimationsByIndex(ref mut definition) = machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { std::mem::swap(&mut definition.inputs[self.index].pose_source, &mut self.value) @@ -47,7 +47,7 @@ define_set_collection_element_command!( ); define_set_collection_element_command!( - SetBlendAnimationsPoseSourceCommand, Handle>(self, context) { + SetBlendAnimationsPoseSourceCommand>>, Handle>>>(self, context) { let machine = fetch_machine(context, self.node_handle); if let PoseNode::BlendAnimations(ref mut definition) = machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { std::mem::swap(&mut definition.pose_sources[self.index].pose_source, &mut self.value); @@ -56,7 +56,7 @@ define_set_collection_element_command!( ); define_set_collection_element_command!( - SetBlendSpacePoseSourceCommand, Handle>(self, context) { + SetBlendSpacePoseSourceCommand>>, Handle>>>(self, context) { let machine = fetch_machine(context, self.node_handle); if let PoseNode::BlendSpace(ref mut definition) = machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { std::mem::swap( &mut definition.points_mut()[self.index].pose_source, &mut self.value); @@ -65,7 +65,7 @@ define_set_collection_element_command!( ); define_set_collection_element_command!( - SetBlendSpacePointPositionCommand, Vector2>(self, context) { + SetBlendSpacePointPositionCommand>>, Vector2>(self, context) { let machine = fetch_machine(context, self.node_handle); if let PoseNode::BlendSpace(ref mut definition) = machine.layers_mut()[self.layer_index].nodes_mut()[self.handle] { std::mem::swap( &mut definition.points_mut()[self.index].position, &mut self.value); @@ -78,9 +78,9 @@ define_set_collection_element_command!( pub struct RemoveBlendSpacePointCommand { pub scene_node_handle: Handle, pub layer_index: usize, - pub node_handle: Handle, + pub node_handle: Handle>>, pub point_index: usize, - pub point: Option, + pub point: Option>>, } impl GameSceneCommandTrait for RemoveBlendSpacePointCommand { diff --git a/editor/src/absm/command/mod.rs b/editor/src/absm/command/mod.rs index 5fc1b1922..9d2c77a39 100644 --- a/editor/src/absm/command/mod.rs +++ b/editor/src/absm/command/mod.rs @@ -126,7 +126,11 @@ macro_rules! define_spawn_command { }; } -define_spawn_command!(AddTransitionCommand, Transition, transitions_mut); +define_spawn_command!( + AddTransitionCommand, + Transition>, + transitions_mut +); #[derive(Debug)] pub enum AddStateCommand { @@ -134,24 +138,24 @@ pub enum AddStateCommand { NonExecuted { node_handle: Handle, layer_index: usize, - state: State, + state: State>, }, Executed { node_handle: Handle, layer_index: usize, - handle: Handle, - prev_entry_state: Handle, + handle: Handle>>, + prev_entry_state: Handle>>, }, Reverted { node_handle: Handle, layer_index: usize, - ticket: Ticket, - state: State, + ticket: Ticket>>, + state: State>, }, } impl AddStateCommand { - pub fn new(node_handle: Handle, layer_index: usize, state: State) -> Self { + pub fn new(node_handle: Handle, layer_index: usize, state: State>) -> Self { Self::NonExecuted { node_handle, layer_index, @@ -163,7 +167,7 @@ impl AddStateCommand { fn fetch_machine<'a>( context: &'a mut GameSceneContext, node_handle: Handle, -) -> &'a mut Machine { +) -> &'a mut Machine> { context.scene.graph[node_handle] .query_component_mut::() .unwrap() @@ -279,24 +283,28 @@ pub enum AddPoseNodeCommand { NonExecuted { node_handle: Handle, layer_index: usize, - node: PoseNode, + node: PoseNode>, }, Executed { node_handle: Handle, layer_index: usize, - handle: Handle, - prev_root_node: Handle, + handle: Handle>>, + prev_root_node: Handle>>, }, Reverted { node_handle: Handle, layer_index: usize, - ticket: Ticket, - node: PoseNode, + ticket: Ticket>>, + node: PoseNode>, }, } impl AddPoseNodeCommand { - pub fn new(node_handle: Handle, layer_index: usize, node: PoseNode) -> Self { + pub fn new( + node_handle: Handle, + layer_index: usize, + node: PoseNode>, + ) -> Self { Self::NonExecuted { node_handle, layer_index, @@ -464,8 +472,8 @@ macro_rules! define_move_command { }; } -define_move_command!(MoveStateNodeCommand, State, states_mut); -define_move_command!(MovePoseNodeCommand, PoseNode, nodes_mut); +define_move_command!(MoveStateNodeCommand, State>, states_mut); +define_move_command!(MovePoseNodeCommand, PoseNode>, nodes_mut); macro_rules! define_free_command { ($name:ident, $ent_type:ty, $container:ident) => { @@ -578,9 +586,13 @@ macro_rules! define_free_command { }; } -define_free_command!(DeleteStateCommand, State, states_mut); -define_free_command!(DeletePoseNodeCommand, PoseNode, nodes_mut); -define_free_command!(DeleteTransitionCommand, Transition, transitions_mut); +define_free_command!(DeleteStateCommand, State>, states_mut); +define_free_command!(DeletePoseNodeCommand, PoseNode>, nodes_mut); +define_free_command!( + DeleteTransitionCommand, + Transition>, + transitions_mut +); #[macro_export] macro_rules! define_push_element_to_collection_command { @@ -700,7 +712,7 @@ macro_rules! define_set_collection_element_command { pub struct SetMachineEntryStateCommand { pub node_handle: Handle, pub layer: usize, - pub entry: Handle, + pub entry: Handle>>, } impl SetMachineEntryStateCommand { @@ -765,7 +777,7 @@ macro_rules! define_absm_swap_command { }; } -define_absm_swap_command!(SetStateRootPoseCommand, Handle>[layer_index: usize](self, context) { +define_absm_swap_command!(SetStateRootPoseCommand>>, Handle>>>[layer_index: usize](self, context) { let machine = fetch_machine(context, self.node_handle); &mut machine.layers_mut()[self.layer_index].states_mut()[self.handle].root }); @@ -804,7 +816,7 @@ impl GameSceneCommandTrait for SetLayerNameCommand { #[derive(Debug)] pub struct AddLayerCommand { pub absm_node_handle: Handle, - pub layer: Option, + pub layer: Option>>, } impl GameSceneCommandTrait for AddLayerCommand { @@ -825,7 +837,7 @@ impl GameSceneCommandTrait for AddLayerCommand { pub struct RemoveLayerCommand { pub absm_node_handle: Handle, pub layer_index: usize, - pub layer: Option, + pub layer: Option>>, } impl RemoveLayerCommand { @@ -858,7 +870,7 @@ impl GameSceneCommandTrait for RemoveLayerCommand { pub struct SetLayerMaskCommand { pub absm_node_handle: Handle, pub layer_index: usize, - pub mask: LayerMask, + pub mask: LayerMask>, } impl SetLayerMaskCommand { diff --git a/editor/src/absm/command/pose.rs b/editor/src/absm/command/pose.rs index 44e136424..d5ad0d434 100644 --- a/editor/src/absm/command/pose.rs +++ b/editor/src/absm/command/pose.rs @@ -15,7 +15,7 @@ define_universal_commands! { GameSceneCommandTrait, GameSceneCommand, GameSceneContext, - Handle, + Handle>>, ctx, handle, self, diff --git a/editor/src/absm/command/state.rs b/editor/src/absm/command/state.rs index b233ef35e..6162f4459 100644 --- a/editor/src/absm/command/state.rs +++ b/editor/src/absm/command/state.rs @@ -15,7 +15,7 @@ define_universal_commands!( GameSceneCommandTrait, GameSceneCommand, GameSceneContext, - Handle, + Handle>>, ctx, handle, self, diff --git a/editor/src/absm/command/transition.rs b/editor/src/absm/command/transition.rs index bba55e217..a3cc07937 100644 --- a/editor/src/absm/command/transition.rs +++ b/editor/src/absm/command/transition.rs @@ -15,7 +15,7 @@ define_universal_commands!( GameSceneCommandTrait, GameSceneCommand, GameSceneContext, - Handle, + Handle>>, ctx, handle, self, diff --git a/editor/src/absm/mod.rs b/editor/src/absm/mod.rs index 9ffed0d86..e2b867074 100644 --- a/editor/src/absm/mod.rs +++ b/editor/src/absm/mod.rs @@ -59,7 +59,7 @@ const NORMAL_ROOT_COLOR: Color = Color::opaque(40, 80, 0); const SELECTED_ROOT_COLOR: Color = Color::opaque(60, 100, 0); struct PreviewModeData { - machine: Machine, + machine: Machine>, nodes: Vec<(Handle, Node)>, } @@ -175,7 +175,7 @@ impl AbsmEditor { fn enter_preview_mode( &mut self, - machine: Machine, + machine: Machine>, animation_targets: FxHashSet>, scene: &Scene, ui: &UserInterface, @@ -525,7 +525,7 @@ impl AbsmEditor { AbsmNodeMessage::Enter => { if let Some(node) = ui .node(message.destination()) - .query_component::>() + .query_component::>>>() { if let Some(layer_index) = selection.layer { self.state_viewer.set_state( @@ -541,7 +541,7 @@ impl AbsmEditor { AbsmNodeMessage::Edit => { if let Some(node) = ui .node(message.destination()) - .query_component::>() + .query_component::>>>() { if let Some(layer_index) = selection.layer { let model_ref = &absm_node.machine().layers()[layer_index].nodes() @@ -556,7 +556,7 @@ impl AbsmEditor { AbsmNodeMessage::AddInput => { if let Some(node) = ui .node(message.destination()) - .query_component::>() + .query_component::>>>() { if let Some(layer_index) = selection.layer { let model_ref = &absm_node.machine().layers()[layer_index].nodes() diff --git a/editor/src/absm/selection.rs b/editor/src/absm/selection.rs index fbe4712a5..58fe60426 100644 --- a/editor/src/absm/selection.rs +++ b/editor/src/absm/selection.rs @@ -6,9 +6,9 @@ use fyrox::{ #[derive(PartialEq, Eq, Debug, Clone)] pub enum SelectedEntity { - Transition(Handle), - State(Handle), - PoseNode(Handle), + Transition(Handle>>), + State(Handle>>), + PoseNode(Handle>>), } #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/editor/src/absm/socket.rs b/editor/src/absm/socket.rs index 2a72a2ec2..d96becb15 100644 --- a/editor/src/absm/socket.rs +++ b/editor/src/absm/socket.rs @@ -1,4 +1,5 @@ use fyrox::core::uuid_provider; +use fyrox::scene::node::Node; use fyrox::{ animation::machine::PoseNode, core::{algebra::Vector2, color::Color, pool::Handle}, @@ -44,7 +45,7 @@ pub enum SocketDirection { pub struct Socket { widget: Widget, click_position: Option>, - pub parent_node: Handle, + pub parent_node: Handle>>, pub direction: SocketDirection, #[allow(dead_code)] // TODO editor: Handle, @@ -124,7 +125,7 @@ impl Control for Socket { pub struct SocketBuilder { widget_builder: WidgetBuilder, - parent_node: Handle, + parent_node: Handle>>, direction: SocketDirection, editor: Handle, index: usize, @@ -143,7 +144,7 @@ impl SocketBuilder { } } - pub fn with_parent_node(mut self, parent_node: Handle) -> Self { + pub fn with_parent_node(mut self, parent_node: Handle>>) -> Self { self.parent_node = parent_node; self } diff --git a/editor/src/absm/state_graph/context.rs b/editor/src/absm/state_graph/context.rs index 30a4a3389..8b00a1e8d 100644 --- a/editor/src/absm/state_graph/context.rs +++ b/editor/src/absm/state_graph/context.rs @@ -277,7 +277,7 @@ impl NodeContextMenu { layer: layer_index, entry: ui .node(self.placement_target) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle, }); @@ -296,7 +296,7 @@ impl NodeContextMenu { .children() .iter() .cloned() - .filter(|c| ui.node(*c).has_component::>()) + .filter(|c| ui.node(*c).has_component::>>>()) .collect::>(); ui.send_message(AbsmCanvasMessage::commit_transition_to_all_nodes( self.canvas, diff --git a/editor/src/absm/state_graph/mod.rs b/editor/src/absm/state_graph/mod.rs index 944b0a0a1..5a6f28504 100644 --- a/editor/src/absm/state_graph/mod.rs +++ b/editor/src/absm/state_graph/mod.rs @@ -41,9 +41,12 @@ pub struct StateGraphViewer { last_selection: AbsmSelection, } -fn fetch_state_node_model_handle(handle: Handle, ui: &UserInterface) -> Handle { +fn fetch_state_node_model_handle( + handle: Handle, + ui: &UserInterface, +) -> Handle>> { ui.node(handle) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle } @@ -93,7 +96,11 @@ impl StateGraphViewer { } } - pub fn activate_transition(&self, ui: &UserInterface, transition: Handle) { + pub fn activate_transition( + &self, + ui: &UserInterface, + transition: Handle>>, + ) { if let Some(view_handle) = ui.node(self.canvas).children().iter().cloned().find(|c| { ui.node(*c) .query_component::() @@ -108,7 +115,7 @@ impl StateGraphViewer { } } - pub fn activate_state(&self, ui: &UserInterface, state: Handle) { + pub fn activate_state(&self, ui: &UserInterface, state: Handle>>) { for (state_view_handle, state_view_ref) in ui .node(self.canvas) .children() @@ -116,7 +123,7 @@ impl StateGraphViewer { .cloned() .filter_map(|c| { ui.node(c) - .query_component::>() + .query_component::>>>() .map(|state_view_ref| (c, state_view_ref)) }) { @@ -184,8 +191,8 @@ impl StateGraphViewer { .filter_map(|n| { let node_ref = ui.node(*n); - if let Some(state_node) = - node_ref.query_component::>() + if let Some(state_node) = node_ref + .query_component::>>>() { Some(SelectedEntity::State(state_node.model_handle)) } else { @@ -263,7 +270,7 @@ impl StateGraphViewer { pub fn sync_to_model( &mut self, - machine_layer: &MachineLayer, + machine_layer: &MachineLayer>, ui: &mut UserInterface, editor_selection: &Selection, ) { @@ -287,7 +294,7 @@ impl StateGraphViewer { .children() .iter() .cloned() - .filter(|c| ui.node(*c).has_component::>()) + .filter(|c| ui.node(*c).has_component::>>>()) .collect::>(); transitions = canvas @@ -307,7 +314,7 @@ impl StateGraphViewer { for (state_handle, state) in machine_layer.states().pair_iter() { if states.iter().all(|state_view| { ui.node(*state_view) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle != state_handle @@ -351,7 +358,7 @@ impl StateGraphViewer { ( state_view, ui.node(state_view) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle, ) @@ -381,7 +388,7 @@ impl StateGraphViewer { for state in states.iter() { let state_node = ui .node(*state) - .query_component::>() + .query_component::>>>() .unwrap(); let state_model_handle = state_node.model_handle; let state_model_ref = &machine_layer.states()[state_node.model_handle]; @@ -451,7 +458,7 @@ impl StateGraphViewer { != transition_handle }) { fn find_state_view( - state_handle: Handle, + state_handle: Handle>>, states: &[Handle], ui: &UserInterface, ) -> Handle { @@ -459,7 +466,7 @@ impl StateGraphViewer { .iter() .find(|s| { ui.node(**s) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle == state_handle @@ -547,7 +554,7 @@ impl StateGraphViewer { }), SelectedEntity::State(state) => states.iter().cloned().find(|s| { ui.node(*s) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle == *state diff --git a/editor/src/absm/state_viewer/context.rs b/editor/src/absm/state_viewer/context.rs index 09dc0bbf0..78ff95e12 100644 --- a/editor/src/absm/state_viewer/context.rs +++ b/editor/src/absm/state_viewer/context.rs @@ -99,7 +99,7 @@ impl CanvasContextMenu { &mut self, sender: &MessageSender, message: &UiMessage, - current_state: Handle, + current_state: Handle>>, ui: &mut UserInterface, absm_node_handle: Handle, layer_index: usize, @@ -221,7 +221,7 @@ impl NodeContextMenu { pub fn handle_ui_message( &mut self, message: &UiMessage, - machine_layer: &MachineLayer, + machine_layer: &MachineLayer>, sender: &MessageSender, ui: &UserInterface, editor_selection: &Selection, @@ -256,7 +256,7 @@ impl NodeContextMenu { } else if message.destination() == self.set_as_root { let root = ui .node(self.placement_target) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle; @@ -307,7 +307,7 @@ impl ConnectionContextMenu { message: &UiMessage, ui: &mut UserInterface, sender: &MessageSender, - machine_layer: &MachineLayer, + machine_layer: &MachineLayer>, absm_node_handle: Handle, layer_index: usize, ) { @@ -320,7 +320,7 @@ impl ConnectionContextMenu { let dest_node_ref = ui .node(connection_ref.dest_node) - .query_component::>() + .query_component::>>>() .unwrap(); let index = dest_node_ref diff --git a/editor/src/absm/state_viewer/mod.rs b/editor/src/absm/state_viewer/mod.rs index 743bcfbfc..d8694b19d 100644 --- a/editor/src/absm/state_viewer/mod.rs +++ b/editor/src/absm/state_viewer/mod.rs @@ -49,7 +49,7 @@ mod context; pub struct StateViewer { pub window: Handle, canvas: Handle, - state: Handle, + state: Handle>>, canvas_context_menu: CanvasContextMenu, node_context_menu: NodeContextMenu, connection_context_menu: ConnectionContextMenu, @@ -60,7 +60,7 @@ fn create_socket( direction: SocketDirection, index: usize, show_index: bool, - parent_node: Handle, + parent_node: Handle>>, ui: &mut UserInterface, ) -> Handle { SocketBuilder::new(WidgetBuilder::new().with_margin(Thickness::uniform(2.0))) @@ -74,7 +74,7 @@ fn create_socket( fn create_sockets( count: usize, direction: SocketDirection, - parent_node: Handle, + parent_node: Handle>>, ui: &mut UserInterface, ) -> Vec> { (0..count) @@ -82,9 +82,12 @@ fn create_sockets( .collect::>() } -fn fetch_pose_node_model_handle(handle: Handle, ui: &UserInterface) -> Handle { +fn fetch_pose_node_model_handle( + handle: Handle, + ui: &UserInterface, +) -> Handle>> { ui.node(handle) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle } @@ -92,7 +95,7 @@ fn fetch_pose_node_model_handle(handle: Handle, ui: &UserInterface) -> H fn fetch_socket_pose_node_model_handle( handle: Handle, ui: &UserInterface, -) -> Handle { +) -> Handle>> { ui.node(handle) .query_component::() .unwrap() @@ -102,7 +105,7 @@ fn fetch_socket_pose_node_model_handle( fn make_play_animation_name( graph: &Graph, absm_node: &AnimationBlendingStateMachine, - animation: Handle, + animation: Handle>>, ) -> String { if let Some(animation) = graph .try_get_of_type::(absm_node.animation_player()) @@ -115,7 +118,7 @@ fn make_play_animation_name( } fn make_pose_node_name( - model_ref: &PoseNode, + model_ref: &PoseNode>, graph: &Graph, absm_node: &AnimationBlendingStateMachine, ) -> String { @@ -177,7 +180,7 @@ impl StateViewer { pub fn set_state( &mut self, - state: Handle, + state: Handle>>, absm_node: &AnimationBlendingStateMachine, layer_index: usize, ui: &UserInterface, @@ -280,7 +283,7 @@ impl StateViewer { .filter_map(|n| { let node_ref = ui.node(*n); - node_ref.query_component::>().map( + node_ref.query_component::>>>().map( |state_node| { SelectedEntity::PoseNode( state_node.model_handle, @@ -380,7 +383,7 @@ impl StateViewer { pub fn sync_to_model( &mut self, ui: &mut UserInterface, - machine_layer: &MachineLayer, + machine_layer: &MachineLayer>, editor_selection: &Selection, absm_node: &AnimationBlendingStateMachine, graph: &Graph, @@ -401,7 +404,9 @@ impl StateViewer { .iter() .cloned() .filter(|h| { - if let Some(pose_node) = ui.node(*h).query_component::>() + if let Some(pose_node) = ui + .node(*h) + .query_component::>>>() { if machine_layer .nodes() @@ -444,7 +449,7 @@ impl StateViewer { for &pose_definition in models.iter() { if views.iter().all(|v| { ui.node(*v) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle != pose_definition @@ -527,7 +532,7 @@ impl StateViewer { for &view in views.clone().iter() { let view_ref = ui .node(view) - .query_component::>() + .query_component::>>>() .unwrap(); if machine_layer @@ -553,7 +558,7 @@ impl StateViewer { for &view in &views { let view_ref = ui .node(view) - .query_component::>() + .query_component::>>>() .unwrap(); let model_handle = view_ref.model_handle; let model_ref = &machine_layer.nodes()[model_handle]; @@ -640,7 +645,10 @@ impl StateViewer { for model in models.iter().cloned() { let dest_ref = views .iter() - .filter_map(|v| ui.node(*v).query_component::>()) + .filter_map(|v| { + ui.node(*v) + .query_component::>>>() + }) .find(|v| v.model_handle == model) .unwrap(); let dest_handle = dest_ref.handle(); @@ -654,7 +662,10 @@ impl StateViewer { if machine_layer.nodes().is_valid_handle(child) { let source = views .iter() - .filter_map(|v| ui.node(*v).query_component::>()) + .filter_map(|v| { + ui.node(*v) + .query_component::>>>() + }) .find(|v| v.model_handle == child) .unwrap(); @@ -695,7 +706,7 @@ impl StateViewer { } SelectedEntity::PoseNode(pose_node) => views.iter().cloned().find(|s| { ui.node(*s) - .query_component::>() + .query_component::>>>() .unwrap() .model_handle == *pose_node diff --git a/editor/src/absm/toolbar.rs b/editor/src/absm/toolbar.rs index 287eca6eb..c559896ba 100644 --- a/editor/src/absm/toolbar.rs +++ b/editor/src/absm/toolbar.rs @@ -1,4 +1,3 @@ -use crate::message::MessageSender; use crate::{ absm::{ command::{AddLayerCommand, RemoveLayerCommand, SetLayerMaskCommand, SetLayerNameCommand}, @@ -7,6 +6,7 @@ use crate::{ }, gui::make_dropdown_list_option, load_image, + message::MessageSender, scene::{ commands::{ChangeSelectionCommand, CommandGroup, GameSceneCommand}, selector::{HierarchyNode, NodeSelectorMessage, NodeSelectorWindowBuilder}, @@ -287,7 +287,8 @@ impl Toolbar { .mask() .inner() .iter() - .map(|h| ErasedHandle::from(*h)) + .cloned() + .map(ErasedHandle::from) .collect::>(); ui.send_message(NodeSelectorMessage::selection( diff --git a/editor/src/absm/transition.rs b/editor/src/absm/transition.rs index e0ecb7b5c..8229e31f5 100644 --- a/editor/src/absm/transition.rs +++ b/editor/src/absm/transition.rs @@ -7,6 +7,7 @@ use crate::{ }; use fyrox::animation::machine::Transition; use fyrox::core::uuid_provider; +use fyrox::scene::node::Node; use fyrox::{ core::{algebra::Vector2, color::Color, color::Hsv, math::Rect, pool::Handle}, core::{reflect::prelude::*, visitor::prelude::*}, @@ -46,7 +47,7 @@ impl TransitionMessage { pub struct TransitionView { widget: Widget, pub segment: Segment, - pub model_handle: Handle, + pub model_handle: Handle>>, selectable: Selectable, activity_factor: f32, } @@ -182,7 +183,11 @@ impl TransitionBuilder { self } - pub fn build(self, model_handle: Handle, ctx: &mut BuildContext) -> Handle { + pub fn build( + self, + model_handle: Handle>>, + ctx: &mut BuildContext, + ) -> Handle { let transition = TransitionView { widget: self .widget_builder diff --git a/editor/src/animation/command/mod.rs b/editor/src/animation/command/mod.rs index 5020682b0..1f7450362 100644 --- a/editor/src/animation/command/mod.rs +++ b/editor/src/animation/command/mod.rs @@ -34,12 +34,16 @@ fn fetch_animation_player<'a>( #[derive(Debug)] pub struct AddTrackCommand { animation_player: Handle, - animation: Handle, - track: Option, + animation: Handle>>, + track: Option>>, } impl AddTrackCommand { - pub fn new(animation_player: Handle, animation: Handle, track: Track) -> Self { + pub fn new( + animation_player: Handle, + animation: Handle>>, + track: Track>, + ) -> Self { Self { animation_player, animation, @@ -68,13 +72,17 @@ impl GameSceneCommandTrait for AddTrackCommand { #[derive(Debug)] pub struct RemoveTrackCommand { animation_player: Handle, - animation: Handle, + animation: Handle>>, index: usize, - track: Option, + track: Option>>, } impl RemoveTrackCommand { - pub fn new(animation_player: Handle, animation: Handle, index: usize) -> Self { + pub fn new( + animation_player: Handle, + animation: Handle>>, + index: usize, + ) -> Self { Self { animation_player, animation, @@ -105,7 +113,7 @@ impl GameSceneCommandTrait for RemoveTrackCommand { #[derive(Debug)] pub struct ReplaceTrackCurveCommand { pub animation_player: Handle, - pub animation: Handle, + pub animation: Handle>>, pub curve: Curve, } @@ -146,23 +154,23 @@ pub enum AddAnimationCommand { Unknown, NonExecuted { animation_player: Handle, - animation: Animation, + animation: Animation>, }, Executed { animation_player: Handle, - animation: Handle, + animation: Handle>>, selection: Selection, }, Reverted { animation_player: Handle, - animation: Animation, - ticket: Ticket, + animation: Animation>, + ticket: Ticket>>, selection: Selection, }, } impl AddAnimationCommand { - pub fn new(animation_player: Handle, animation: Animation) -> Self { + pub fn new(animation_player: Handle, animation: Animation>) -> Self { Self::NonExecuted { animation_player, animation, @@ -265,21 +273,21 @@ pub enum RemoveAnimationCommand { Unknown, NonExecuted { animation_player: Handle, - animation: Handle, + animation: Handle>>, }, Executed { animation_player: Handle, - animation: Animation, - ticket: Ticket, + animation: Animation>, + ticket: Ticket>>, }, Reverted { animation_player: Handle, - animation: Handle, + animation: Handle>>, }, } impl RemoveAnimationCommand { - pub fn new(animation_player: Handle, animation: Handle) -> Self { + pub fn new(animation_player: Handle, animation: Handle>>) -> Self { Self::NonExecuted { animation_player, animation, @@ -353,8 +361,8 @@ impl GameSceneCommandTrait for RemoveAnimationCommand { #[derive(Debug)] pub struct ReplaceAnimationCommand { pub animation_player: Handle, - pub animation_handle: Handle, - pub animation: Animation, + pub animation_handle: Handle>>, + pub animation: Animation>, } impl ReplaceAnimationCommand { @@ -388,7 +396,7 @@ macro_rules! define_animation_swap_command { #[derive(Debug)] pub struct $name { pub node_handle: Handle, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub value: $value_type, } @@ -416,9 +424,9 @@ macro_rules! define_animation_swap_command { fn fetch_animation<'a>( animation_player: Handle, - animation: Handle, + animation: Handle>>, ctx: &'a mut GameSceneContext, -) -> &'a mut Animation { +) -> &'a mut Animation> { fetch_animation_player(animation_player, ctx) .animations_mut() .index_mut(animation) @@ -459,7 +467,7 @@ define_animation_swap_command!(SetAnimationEnabledCommand(self, context) { self.value = old; }); -define_animation_swap_command!(SetAnimationRootMotionSettingsCommand>(self, context) { +define_animation_swap_command!(SetAnimationRootMotionSettingsCommand>>>(self, context) { let animation = fetch_animation(self.node_handle, self.animation_handle, context); let old = animation.root_motion_settings_ref().cloned(); animation.set_root_motion_settings(self.value.clone()); @@ -469,7 +477,7 @@ define_animation_swap_command!(SetAnimationRootMotionSettingsCommand, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub signal: Option, } @@ -492,7 +500,7 @@ impl GameSceneCommandTrait for AddAnimationSignal { #[derive(Debug)] pub struct MoveAnimationSignal { pub animation_player_handle: Handle, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub signal: Uuid, pub time: f32, } @@ -528,7 +536,7 @@ impl GameSceneCommandTrait for MoveAnimationSignal { #[derive(Debug)] pub struct RemoveAnimationSignal { pub animation_player_handle: Handle, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub signal_index: usize, pub signal: Option, } @@ -554,7 +562,7 @@ impl GameSceneCommandTrait for RemoveAnimationSignal { #[derive(Debug)] pub struct SetTrackEnabledCommand { pub animation_player_handle: Handle, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub track: Uuid, pub enabled: bool, } @@ -590,7 +598,7 @@ impl GameSceneCommandTrait for SetTrackEnabledCommand { #[derive(Debug)] pub struct SetTrackTargetCommand { pub animation_player_handle: Handle, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub track: Uuid, pub target: Handle, } @@ -626,7 +634,7 @@ impl GameSceneCommandTrait for SetTrackTargetCommand { #[derive(Debug)] pub struct SetTrackBindingCommand { pub animation_player_handle: Handle, - pub animation_handle: Handle, + pub animation_handle: Handle>>, pub track: Uuid, pub binding: ValueBinding, } diff --git a/editor/src/animation/command/signal.rs b/editor/src/animation/command/signal.rs index b633b855a..894a6c820 100644 --- a/editor/src/animation/command/signal.rs +++ b/editor/src/animation/command/signal.rs @@ -27,5 +27,5 @@ define_universal_commands!( .unwrap() }, node_handle: Handle, - animation_handle: Handle + animation_handle: Handle>> ); diff --git a/editor/src/animation/selection.rs b/editor/src/animation/selection.rs index 0380987ba..4ed8f1e8e 100644 --- a/editor/src/animation/selection.rs +++ b/editor/src/animation/selection.rs @@ -14,7 +14,7 @@ pub enum SelectedEntity { #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnimationSelection { pub animation_player: Handle, - pub animation: Handle, + pub animation: Handle>>, pub entities: Vec, } diff --git a/editor/src/animation/toolbar.rs b/editor/src/animation/toolbar.rs index b6181afee..9520224b6 100644 --- a/editor/src/animation/toolbar.rs +++ b/editor/src/animation/toolbar.rs @@ -194,7 +194,7 @@ impl RootMotionDropdownArea { game_scene: &GameScene, selection: &AnimationSelection, ) { - let send_command = |settings: Option| { + let send_command = |settings: Option>>| { sender.do_scene_command(SetAnimationRootMotionSettingsCommand { node_handle: selection.animation_player, animation_handle: selection.animation, @@ -285,7 +285,11 @@ impl RootMotionDropdownArea { node_handle: selection.animation_player, animation_handle: selection.animation, value: Some(RootMotionSettings { - node: node_selection.first().cloned().unwrap_or_default().into(), + node: node_selection + .first() + .cloned() + .map(Handle::from) + .unwrap_or_default(), ..*settings }), }); @@ -365,7 +369,7 @@ pub enum ToolbarAction { None, EnterPreviewMode, LeavePreviewMode, - SelectAnimation(Handle), + SelectAnimation(Handle>>), PlayPause, Stop, } @@ -863,7 +867,7 @@ impl Toolbar { .items()[*index]; let animation = ui .node(item) - .user_data_cloned::>() + .user_data_cloned::>>>() .unwrap(); sender.do_scene_command(ChangeSelectionCommand::new( Selection::Animation(AnimationSelection { diff --git a/editor/src/animation/track.rs b/editor/src/animation/track.rs index db6bea6d6..84f6d3e30 100644 --- a/editor/src/animation/track.rs +++ b/editor/src/animation/track.rs @@ -584,7 +584,7 @@ pub struct TrackList { context_menu: TrackContextMenu, property_binding_mode: PropertyBindingMode, scroll_viewer: Handle, - selected_animation: Handle, + selected_animation: Handle>>, } #[derive(Clone)] @@ -735,7 +735,7 @@ impl TrackList { game_scene: &GameScene, sender: &MessageSender, animation_player: Handle, - animation: Handle, + animation: Handle>>, ui: &mut UserInterface, scene: &Scene, ) { @@ -1266,8 +1266,8 @@ impl TrackList { pub fn sync_to_model( &mut self, - animation: &Animation, - animation_handle: Handle, + animation: &Animation>, + animation_handle: Handle>>, graph: &Graph, editor_selection: &Selection, ui: &mut UserInterface, @@ -1348,7 +1348,8 @@ impl TrackList { .map(|v| ui.node(*v)) .all(|v| v.query_component::().unwrap().id != model_track.id()) { - let parent_group = match self.group_views.entry(model_track.target()) { + let parent_group = match self.group_views.entry(model_track.target()) + { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { let ctx = &mut ui.build_ctx(); diff --git a/editor/src/inspector/editors/animation.rs b/editor/src/inspector/editors/animation.rs index 0b8cdec19..ce5999a8b 100644 --- a/editor/src/inspector/editors/animation.rs +++ b/editor/src/inspector/editors/animation.rs @@ -1,6 +1,7 @@ //! Animation selector for `Handle` fields. use crate::{gui::make_dropdown_list_option_universal, inspector::EditorEnvironment, Message}; +use fyrox::scene::node::Node; use fyrox::{ animation::{machine::Machine, Animation, AnimationContainer}, core::pool::Handle, @@ -25,14 +26,16 @@ pub struct AnimationPropertyEditorDefinition; impl PropertyEditorDefinition for AnimationPropertyEditorDefinition { fn value_type_id(&self) -> TypeId { - TypeId::of::>() + TypeId::of::>>>() } fn create_instance( &self, ctx: PropertyEditorBuildContext, ) -> Result { - let value = ctx.property_info.cast_value::>()?; + let value = ctx + .property_info + .cast_value::>>>()?; if let Some(environment) = EditorEnvironment::try_get_from(&ctx.environment) { Ok(PropertyEditorInstance::Simple { editor: DropdownListBuilder::new(WidgetBuilder::new()) @@ -68,7 +71,9 @@ impl PropertyEditorDefinition for AnimationPropertyEditorDefinition { &self, ctx: PropertyEditorMessageContext, ) -> Result, InspectorError> { - let value = ctx.property_info.cast_value::>()?; + let value = ctx + .property_info + .cast_value::>>>()?; if let Some(environment) = EditorEnvironment::try_get_from(&ctx.environment) { if let Some(index) = environment .available_animations @@ -113,7 +118,7 @@ pub struct AnimationContainerPropertyEditorDefinition; impl PropertyEditorDefinition for AnimationContainerPropertyEditorDefinition { fn value_type_id(&self) -> TypeId { - TypeId::of::() + TypeId::of::>>() } fn create_instance( @@ -151,7 +156,7 @@ pub struct MachinePropertyEditorDefinition; impl PropertyEditorDefinition for MachinePropertyEditorDefinition { fn value_type_id(&self) -> TypeId { - TypeId::of::() + TypeId::of::>>() } fn create_instance( diff --git a/editor/src/inspector/editors/mod.rs b/editor/src/inspector/editors/mod.rs index 9f0e39dd4..2c5394031 100644 --- a/editor/src/inspector/editors/mod.rs +++ b/editor/src/inspector/editors/mod.rs @@ -365,39 +365,71 @@ pub fn make_property_editors_container(sender: MessageSender) -> PropertyEditorD container.insert(InheritablePropertyEditorDefinition::::new()); container.insert(InheritablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(VecCollectionPropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(VecCollectionPropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(VecCollectionPropertyEditorDefinition::::new()); + container.insert(InspectablePropertyEditorDefinition::< + BasePoseNode>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + IndexedBlendInput>, + >::new()); + container.insert(VecCollectionPropertyEditorDefinition::< + IndexedBlendInput>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + BlendSpacePoint>, + >::new()); + container.insert(VecCollectionPropertyEditorDefinition::< + BlendSpacePoint>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::>>::new()); + container.insert(VecCollectionPropertyEditorDefinition::< + BlendPose>, + >::new()); container.insert(EnumPropertyEditorDefinition::::new()); - container.insert(EnumPropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(VecCollectionPropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); + container.insert(EnumPropertyEditorDefinition::>>::new()); + container.insert(InspectablePropertyEditorDefinition::< + StateActionWrapper>, + >::new()); + container.insert(VecCollectionPropertyEditorDefinition::< + StateActionWrapper>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + BlendAnimationsByIndex>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + BlendAnimations>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + BlendSpace>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + PlayAnimation>, + >::new()); - container.insert(InspectablePropertyEditorDefinition::>::new()); - container.insert(InspectablePropertyEditorDefinition::>::new()); + container.insert(InspectablePropertyEditorDefinition::< + Handle>>, + >::new()); + container.insert(InspectablePropertyEditorDefinition::< + Handle>>, + >::new()); - container.insert(VecCollectionPropertyEditorDefinition::>::new()); + container.insert(VecCollectionPropertyEditorDefinition::< + Handle>>, + >::new()); container.insert(AnimationPropertyEditorDefinition); container.insert(AnimationContainerPropertyEditorDefinition); - container.insert(InheritablePropertyEditorDefinition::::new()); + container.insert(InheritablePropertyEditorDefinition::< + AnimationContainer>, + >::new()); container.insert(MachinePropertyEditorDefinition); - container.insert(InheritablePropertyEditorDefinition::::new()); + container.insert(InheritablePropertyEditorDefinition::>>::new()); - container.insert(EnumPropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); - container.insert(InspectablePropertyEditorDefinition::::new()); + container.insert(EnumPropertyEditorDefinition::>>::new()); + container.insert(InspectablePropertyEditorDefinition::>>::new()); + container.insert(InspectablePropertyEditorDefinition::>>::new()); + container.insert(InspectablePropertyEditorDefinition::>>::new()); + container.insert(InspectablePropertyEditorDefinition::>>::new()); container.insert(InspectablePropertyEditorDefinition::::new()); container.insert(EnumPropertyEditorDefinition::::new()); diff --git a/editor/src/inspector/mod.rs b/editor/src/inspector/mod.rs index fd86a4a16..5769782aa 100644 --- a/editor/src/inspector/mod.rs +++ b/editor/src/inspector/mod.rs @@ -8,6 +8,7 @@ use crate::{ utils::window_content, Brush, Engine, Message, Mode, WidgetMessage, WrapMode, MSG_SYNC_FLAG, }; +use fyrox::scene::node::Node; use fyrox::{ animation::Animation, asset::manager::ResourceManager, @@ -42,7 +43,7 @@ pub mod handlers; #[derive(Clone)] pub struct AnimationDefinition { name: String, - handle: Handle, + handle: Handle>>, } pub struct EditorEnvironment { diff --git a/fyrox-animation/Cargo.toml b/fyrox-animation/Cargo.toml new file mode 100644 index 000000000..afb2173e9 --- /dev/null +++ b/fyrox-animation/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "fyrox-animation" +version = "0.1.0" +edition = "2021" + +[dependencies] +fyrox-core = { version = "0.26.0", path = "../fyrox-core" } +fyrox-resource = { version = "0.10.0", path = "../fyrox-resource" } +strum = "0.25.0" +strum_macros = "0.25.0" +fxhash = "0.2.1" +spade = "2.1.0" \ No newline at end of file diff --git a/src/animation/container.rs b/fyrox-animation/src/container.rs similarity index 99% rename from src/animation/container.rs rename to fyrox-animation/src/container.rs index 6a5238ffb..7cc0ef5db 100644 --- a/src/animation/container.rs +++ b/fyrox-animation/src/container.rs @@ -2,7 +2,6 @@ //! of parametric curves. See [`TrackDataContainer`] docs for more info. use crate::{ - animation::value::TrackValue, core::{ algebra::{Vector2, Vector3, Vector4}, curve::Curve, @@ -10,6 +9,7 @@ use crate::{ reflect::prelude::*, visitor::prelude::*, }, + value::TrackValue, }; /// The kind of track output value, the animation system works only with numeric properties and the number diff --git a/src/animation/mod.rs b/fyrox-animation/src/lib.rs similarity index 83% rename from src/animation/mod.rs rename to fyrox-animation/src/lib.rs index bed93c8dd..ee05fd69b 100644 --- a/src/animation/mod.rs +++ b/fyrox-animation/src/lib.rs @@ -1,10 +1,9 @@ -//! Animation allows you to change properties of scene nodes at runtime using a set of key frames. +//! Animation allows you to change properties of arbitrary objects at runtime using a set of key frames. //! See [`Animation`] docs for more info. #![warn(missing_docs)] use crate::{ - animation::track::Track, core::{ algebra::{UnitQuaternion, Vector3}, math::wrapf, @@ -13,22 +12,23 @@ use crate::{ uuid::Uuid, visitor::{Visit, VisitResult, Visitor}, }, - scene::{ - graph::{Graph, NodePool}, - node::Node, - }, - utils::{self, NameProvider}, + track::Track, }; -use fyrox_core::uuid_provider; +use fyrox_core::{NameProvider, TypeUuidProvider}; +use std::hash::Hash; use std::{ collections::VecDeque, fmt::Debug, ops::{Index, IndexMut, Range}, }; -use crate::animation::value::{TrackValue, ValueBinding}; +pub use fyrox_core as core; +use fyrox_core::pool::ErasedHandle; +use fyrox_core::uuid::uuid; + pub use pose::{AnimationPose, NodePose}; pub use signal::{AnimationEvent, AnimationSignal}; +use value::{TrackValue, ValueBinding}; pub mod container; pub mod machine; @@ -40,8 +40,8 @@ pub mod value; /// # Overview /// -/// Animation allows you to change properties of scene nodes at runtime using a set of key frames. Animation -/// consists of multiple tracks, where each track is bound to a property of a scene node. A track can animate +/// Animation allows you to change properties of arbitrary entities at runtime using a set of key frames. Animation +/// consists of multiple tracks, where each track is bound to a property of an entity. A track can animate /// any numeric properties, starting from numbers (including `bool`) end ending by 2/3/4 dimensional vectors. /// Each component (number, x/y/z/w vector components) is stored in a _parametric curve_ (see /// [`crate::core::curve::Curve`] docs for more info). Every parametric curve contains zero or more _key frames_. @@ -110,33 +110,24 @@ pub mod value; /// /// # Examples /// -/// Usually, animations are created from the editor or some external tool and then imported in the engine. Before trying the example -/// below, please read the docs for [`crate::scene::animation::AnimationPlayer`] node, it is much more convenient way of animating -/// other nodes. The node can be created from the editor and you don't even need to write any code. -/// -/// Use the following example code as a guide **only** if you need to create procedural animations: +/// Usually, animations are created from the editor or some external tool and then imported in the engine. +/// However, sometimes there's a need for procedural animations. Use the following example code as +/// a guide **only** if you need to create procedural animations: /// /// ```rust -/// use fyrox::{ -/// animation::{ -/// container::{TrackDataContainer, TrackValueKind}, -/// track::Track, -/// value::ValueBinding, -/// Animation, -/// }, +/// use fyrox_animation::{ +/// container::{TrackDataContainer, TrackValueKind}, +/// track::Track, +/// value::ValueBinding, +/// Animation, /// core::{ /// curve::{Curve, CurveKey, CurveKeyKind}, /// pool::Handle, /// }, -/// scene::{ -/// node::Node, -/// base::BaseBuilder, -/// graph::Graph, -/// pivot::PivotBuilder -/// } /// }; +/// use fyrox_core::pool::ErasedHandle; /// -/// fn create_animation(node: Handle) -> Animation { +/// fn create_animation(target: ErasedHandle) -> Animation { /// let mut frames_container = TrackDataContainer::new(TrackValueKind::Vector3); /// /// // We'll animate only X coordinate (at index 0). @@ -148,7 +139,7 @@ pub mod value; /// /// // Create a track that will animated the node using the curve above. /// let mut track = Track::new(frames_container, ValueBinding::Position); -/// track.set_target(node); +/// track.set_target(target); /// /// // Finally create an animation and set its time slice and turn it on. /// let mut animation = Animation::default(); @@ -159,17 +150,12 @@ pub mod value; /// animation /// } /// -/// // Create a graph with a node. -/// let mut graph = Graph::new(); -/// let some_node = PivotBuilder::new(BaseBuilder::new()).build(&mut graph); -/// /// // Create the animation. -/// let mut animation = create_animation(some_node); +/// let mut animation = create_animation(Default::default()); /// /// // Emulate some ticks (like it was updated from the main loop of your game). /// for _ in 0..10 { /// animation.tick(1.0 / 60.0); -/// animation.pose().apply(&mut graph); /// } /// ``` /// @@ -177,10 +163,10 @@ pub mod value; /// is only for the sake of completeness of the example. In the real games you need to add the animation to an animation /// player scene node and it will do the job for you. #[derive(Debug, Reflect, Visit, PartialEq)] -pub struct Animation { +pub struct Animation { #[visit(optional)] name: String, - tracks: Vec, + tracks: Vec>, time_position: f32, #[visit(optional)] time_slice: Range, @@ -190,7 +176,7 @@ pub struct Animation { signals: Vec, #[visit(optional)] - root_motion_settings: Option, + root_motion_settings: Option>, #[reflect(hidden)] #[visit(skip)] @@ -199,23 +185,36 @@ pub struct Animation { // Non-serialized #[reflect(hidden)] #[visit(skip)] - pose: AnimationPose, + pose: AnimationPose, // Non-serialized #[reflect(hidden)] #[visit(skip)] events: VecDeque, } -uuid_provider!(Animation = "aade8e9d-e2cf-401d-a4d1-59c6943645f3"); +impl TypeUuidProvider for Animation { + fn type_uuid() -> Uuid { + uuid!("aade8e9d-e2cf-401d-a4d1-59c6943645f3") + } +} + +/// Identifier of an entity, that can be animated. +pub trait EntityId: + Default + Copy + Reflect + Visit + PartialEq + Eq + Hash + Debug + Ord + PartialEq + 'static +{ +} + +impl EntityId for Handle {} +impl EntityId for ErasedHandle {} /// Root motion settings. It allows you to set a node (root) from which the motion will be taken /// as well as filter out some unnecessary parts of the motion (i.e. do not extract motion on /// Y axis). #[derive(Default, Debug, Clone, PartialEq, Reflect, Visit)] -pub struct RootMotionSettings { +pub struct RootMotionSettings { /// A handle to a node which movement will be extracted and put in root motion field of an animation /// to which these settings were set to. - pub node: Handle, + pub node: T, /// Keeps X part of the translational part of the motion. pub ignore_x_movement: bool, /// Keeps Y part of the translational part of the motion. @@ -248,13 +247,13 @@ impl RootMotion { } } -impl NameProvider for Animation { +impl NameProvider for Animation { fn name(&self) -> &str { &self.name } } -impl Clone for Animation { +impl Clone for Animation { fn clone(&self) -> Self { Self { name: self.name.clone(), @@ -273,7 +272,7 @@ impl Clone for Animation { } } -impl Animation { +impl Animation { /// Sets a new name for the animation. The name then could be used to find the animation in a container. pub fn set_name>(&mut self, name: S) { self.name = name.as_ref().to_owned(); @@ -286,22 +285,22 @@ impl Animation { /// Adds new track to the animation. Animation can have unlimited number of tracks, each track is responsible /// for animation of a single scene node. - pub fn add_track(&mut self, track: Track) { + pub fn add_track(&mut self, track: Track) { self.tracks.push(track); } /// Removes a track at given index. - pub fn remove_track(&mut self, index: usize) -> Track { + pub fn remove_track(&mut self, index: usize) -> Track { self.tracks.remove(index) } /// Inserts a track at given index. - pub fn insert_track(&mut self, index: usize, track: Track) { + pub fn insert_track(&mut self, index: usize, track: Track) { self.tracks.insert(index, track) } /// Removes last track from the list of tracks of the animation. - pub fn pop_track(&mut self) -> Option { + pub fn pop_track(&mut self) -> Option> { self.tracks.pop() } @@ -319,7 +318,7 @@ impl Animation { } /// Returns a reference to tracks container. - pub fn tracks(&self) -> &[Track] { + pub fn tracks(&self) -> &[Track] { &self.tracks } @@ -401,7 +400,7 @@ impl Animation { } fn update_root_motion(&mut self, prev_time_position: f32) { - fn fetch_position_at_time(tracks: &[Track], time: f32) -> Vector3 { + fn fetch_position_at_time(tracks: &[Track], time: f32) -> Vector3 { tracks .iter() .find(|track| track.binding() == &ValueBinding::Position) @@ -416,7 +415,10 @@ impl Animation { .unwrap_or_default() } - fn fetch_rotation_at_time(tracks: &[Track], time: f32) -> UnitQuaternion { + fn fetch_rotation_at_time( + tracks: &[Track], + time: f32, + ) -> UnitQuaternion { tracks .iter() .find(|track| track.binding() == &ValueBinding::Rotation) @@ -550,17 +552,17 @@ impl Animation { } /// Sets new root motion settings. - pub fn set_root_motion_settings(&mut self, settings: Option) { + pub fn set_root_motion_settings(&mut self, settings: Option>) { self.root_motion_settings = settings; } /// Returns a reference to the root motion settings (if any). - pub fn root_motion_settings_ref(&self) -> Option<&RootMotionSettings> { + pub fn root_motion_settings_ref(&self) -> Option<&RootMotionSettings> { self.root_motion_settings.as_ref() } /// Returns a reference to the root motion settings (if any). - pub fn root_motion_settings_mut(&mut self) -> Option<&mut RootMotionSettings> { + pub fn root_motion_settings_mut(&mut self) -> Option<&mut RootMotionSettings> { self.root_motion_settings.as_mut() } @@ -639,7 +641,7 @@ impl Animation { } /// Returns a mutable reference to the track container. - pub fn tracks_mut(&mut self) -> &mut [Track] { + pub fn tracks_mut(&mut self) -> &mut [Track] { &mut self.tracks } @@ -678,44 +680,13 @@ impl Animation { /// to remove undesired animation tracks. pub fn retain_tracks(&mut self, filter: F) where - F: FnMut(&Track) -> bool, + F: FnMut(&Track) -> bool, { self.tracks.retain(filter) } - /// Enables or disables animation tracks for nodes in hierarchy starting from given root. Could be useful to enable - /// or disable animation for skeleton parts, i.e. you don't want legs to be animated and you know that legs starts - /// from torso bone, then you could do this. - /// - /// ``` - /// use fyrox::scene::node::Node; - /// use fyrox::animation::Animation; - /// use fyrox::core::pool::Handle; - /// use fyrox::scene::graph::Graph; - /// - /// fn disable_legs(torso_bone: Handle, aim_animation: &mut Animation, graph: &Graph) { - /// aim_animation.set_tracks_enabled_from(torso_bone, false, graph) - /// } - /// ``` - /// - /// After this legs won't be animated and animation could be blended together with run animation so it will produce - /// new animation - run and aim. - pub fn set_tracks_enabled_from(&mut self, handle: Handle, enabled: bool, graph: &Graph) { - let mut stack = vec![handle]; - while let Some(node) = stack.pop() { - for track in self.tracks.iter_mut() { - if track.target() == node { - track.set_enabled(enabled); - } - } - for child in graph[node].children() { - stack.push(*child); - } - } - } - /// Tries to find all tracks that refer to a given node and enables or disables them. - pub fn set_node_track_enabled(&mut self, handle: Handle, enabled: bool) { + pub fn set_node_track_enabled(&mut self, handle: T, enabled: bool) { for track in self.tracks.iter_mut() { if track.target() == handle { track.set_enabled(enabled); @@ -724,14 +695,14 @@ impl Animation { } /// Returns an iterator that yields a number of references to tracks that refer to a given node. - pub fn tracks_of(&self, handle: Handle) -> impl Iterator { + pub fn tracks_of(&self, handle: T) -> impl Iterator> { self.tracks .iter() .filter(move |track| track.target() == handle) } /// Returns an iterator that yields a number of references to tracks that refer to a given node. - pub fn tracks_of_mut(&mut self, handle: Handle) -> impl Iterator { + pub fn tracks_of_mut(&mut self, handle: T) -> impl Iterator> { self.tracks .iter_mut() .filter(move |track| track.target() == handle) @@ -743,7 +714,7 @@ impl Animation { &self, name: S, ) -> Option<(usize, &AnimationSignal)> { - utils::find_by_name_ref(self.signals.iter().enumerate(), name) + core::find_by_name_ref(self.signals.iter().enumerate(), name) } /// Tries to find a signal by its name. Returns index of the signal and its reference. @@ -752,7 +723,7 @@ impl Animation { &mut self, name: S, ) -> Option<(usize, &mut AnimationSignal)> { - utils::find_by_name_mut(self.signals.iter_mut().enumerate(), name) + core::find_by_name_mut(self.signals.iter_mut().enumerate(), name) } /// Returns `true` if there's a signal with given name and id. @@ -779,12 +750,12 @@ impl Animation { } /// Returns current pose of the animation (a final result that can be applied to a scene graph). - pub fn pose(&self) -> &AnimationPose { + pub fn pose(&self) -> &AnimationPose { &self.pose } } -impl Default for Animation { +impl Default for Animation { fn default() -> Self { Self { name: Default::default(), @@ -806,17 +777,17 @@ impl Default for Animation { /// A container for animations. It is a tiny wrapper around [`Pool`], you should never create the container yourself, /// it is managed by the engine. #[derive(Debug, Clone, Reflect, PartialEq)] -pub struct AnimationContainer { - pool: Pool, +pub struct AnimationContainer { + pool: Pool>, } -impl Default for AnimationContainer { +impl Default for AnimationContainer { fn default() -> Self { Self::new() } } -impl AnimationContainer { +impl AnimationContainer { /// Creates an empty animation container. pub fn new() -> Self { Self { pool: Pool::new() } @@ -830,57 +801,62 @@ impl AnimationContainer { /// Returns an iterator yielding a references to animations in the container. #[inline] - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator> { self.pool.iter() } /// Returns an iterator yielding a pair (handle, reference) to animations in the container. #[inline] - pub fn pair_iter(&self) -> impl Iterator, &Animation)> { + pub fn pair_iter(&self) -> impl Iterator>, &Animation)> { self.pool.pair_iter() } /// Returns an iterator yielding a pair (handle, reference) to animations in the container. #[inline] - pub fn pair_iter_mut(&mut self) -> impl Iterator, &mut Animation)> { + pub fn pair_iter_mut( + &mut self, + ) -> impl Iterator>, &mut Animation)> { self.pool.pair_iter_mut() } /// Returns an iterator yielding a references to animations in the container. #[inline] - pub fn iter_mut(&mut self) -> impl Iterator { + pub fn iter_mut(&mut self) -> impl Iterator> { self.pool.iter_mut() } /// Adds a new animation to the container and returns its handle. #[inline] - pub fn add(&mut self, animation: Animation) -> Handle { + pub fn add(&mut self, animation: Animation) -> Handle> { self.pool.spawn(animation) } /// Tries to remove an animation from the container by its handle. #[inline] - pub fn remove(&mut self, handle: Handle) -> Option { + pub fn remove(&mut self, handle: Handle>) -> Option> { self.pool.try_free(handle) } /// Extracts animation from container and reserves its handle. It is used to temporarily take /// ownership over animation, and then put animation back using given ticket. - pub fn take_reserve(&mut self, handle: Handle) -> (Ticket, Animation) { + pub fn take_reserve( + &mut self, + handle: Handle>, + ) -> (Ticket>, Animation) { self.pool.take_reserve(handle) } /// Puts animation back by given ticket. pub fn put_back( &mut self, - ticket: Ticket, - animation: Animation, - ) -> Handle { + ticket: Ticket>, + animation: Animation, + ) -> Handle> { self.pool.put_back(ticket, animation) } /// Makes animation handle vacant again. - pub fn forget_ticket(&mut self, ticket: Ticket) { + pub fn forget_ticket(&mut self, ticket: Ticket>) { self.pool.forget_ticket(ticket) } @@ -892,25 +868,25 @@ impl AnimationContainer { /// Tries to borrow a reference to an animation in the container. Panics if the handle is invalid. #[inline] - pub fn get(&self, handle: Handle) -> &Animation { + pub fn get(&self, handle: Handle>) -> &Animation { self.pool.borrow(handle) } /// Tries to borrow a mutable reference to an animation in the container. Panics if the handle is invalid. #[inline] - pub fn get_mut(&mut self, handle: Handle) -> &mut Animation { + pub fn get_mut(&mut self, handle: Handle>) -> &mut Animation { self.pool.borrow_mut(handle) } /// Tries to borrow a reference to an animation in the container. #[inline] - pub fn try_get(&self, handle: Handle) -> Option<&Animation> { + pub fn try_get(&self, handle: Handle>) -> Option<&Animation> { self.pool.try_borrow(handle) } /// Tries to borrow a mutable reference to an animation in the container. #[inline] - pub fn try_get_mut(&mut self, handle: Handle) -> Option<&mut Animation> { + pub fn try_get_mut(&mut self, handle: Handle>) -> Option<&mut Animation> { self.pool.try_borrow_mut(handle) } @@ -919,8 +895,8 @@ impl AnimationContainer { pub fn find_by_name_ref>( &self, name: S, - ) -> Option<(Handle, &Animation)> { - utils::find_by_name_ref(self.pool.pair_iter(), name) + ) -> Option<(Handle>, &Animation)> { + core::find_by_name_ref(self.pool.pair_iter(), name) } /// Tries to find an animation by its name in the container. @@ -928,8 +904,8 @@ impl AnimationContainer { pub fn find_by_name_mut>( &mut self, name: S, - ) -> Option<(Handle, &mut Animation)> { - utils::find_by_name_mut(self.pool.pair_iter_mut(), name) + ) -> Option<(Handle>, &mut Animation)> { + core::find_by_name_mut(self.pool.pair_iter_mut(), name) } /// Removes every animation from the container that does not satisfy a particular condition represented by the given @@ -937,22 +913,11 @@ impl AnimationContainer { #[inline] pub fn retain

(&mut self, pred: P) where - P: FnMut(&Animation) -> bool, + P: FnMut(&Animation) -> bool, { self.pool.retain(pred) } - /// Updates all animations in the container and applies their poses to respective nodes. This method is intended to - /// be used only by the internals of the engine! - pub fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32) { - for animation in self.pool.iter_mut().filter(|anim| anim.enabled) { - animation.tick(dt); - if apply { - animation.pose.apply_internal(nodes); - } - } - } - /// Removes queued animation events from every animation in the container. /// /// # Potential use cases @@ -968,7 +933,7 @@ impl AnimationContainer { } } -impl Visit for AnimationContainer { +impl Visit for AnimationContainer { fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult { if visitor.is_reading() && self.pool.get_capacity() != 0 { panic!("Animation pool must be empty on load!"); @@ -982,16 +947,16 @@ impl Visit for AnimationContainer { } } -impl Index> for AnimationContainer { - type Output = Animation; +impl Index>> for AnimationContainer { + type Output = Animation; - fn index(&self, index: Handle) -> &Self::Output { + fn index(&self, index: Handle>) -> &Self::Output { &self.pool[index] } } -impl IndexMut> for AnimationContainer { - fn index_mut(&mut self, index: Handle) -> &mut Self::Output { +impl IndexMut>> for AnimationContainer { + fn index_mut(&mut self, index: Handle>) -> &mut Self::Output { &mut self.pool[index] } } diff --git a/src/animation/machine/event.rs b/fyrox-animation/src/machine/event.rs similarity index 73% rename from src/animation/machine/event.rs rename to fyrox-animation/src/machine/event.rs index 7849c8610..db377ac2e 100644 --- a/src/animation/machine/event.rs +++ b/fyrox-animation/src/machine/event.rs @@ -2,42 +2,43 @@ //! needed to works with such events. use crate::{ - animation::machine::{State, Transition}, core::pool::Handle, + machine::{State, Transition}, + EntityId, }; use std::collections::VecDeque; /// Specific state machine event. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Event { +pub enum Event { /// Occurs when enter some state. See module docs for example. - StateEnter(Handle), + StateEnter(Handle>), /// Occurs when leaving some state. See module docs for example. - StateLeave(Handle), + StateLeave(Handle>), /// Occurs when a transition is done and a new active state was set. ActiveStateChanged { /// Previously active state. - prev: Handle, + prev: Handle>, /// New active state. - new: Handle, + new: Handle>, }, /// Occurs when active transition was changed. - ActiveTransitionChanged(Handle), + ActiveTransitionChanged(Handle>), } /// A simple event queue with fixed capacity. It is used to store a fixed amount of events and discard any /// events when the queue is full. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct FixedEventQueue { - queue: VecDeque, +pub struct FixedEventQueue { + queue: VecDeque>, limit: u32, } -impl Default for FixedEventQueue { +impl Default for FixedEventQueue { fn default() -> Self { Self { queue: Default::default(), @@ -46,7 +47,7 @@ impl Default for FixedEventQueue { } } -impl FixedEventQueue { +impl FixedEventQueue { /// Creates a new queue with given limit. pub fn new(limit: u32) -> Self { Self { @@ -56,14 +57,14 @@ impl FixedEventQueue { } /// Pushes an event to the queue. - pub fn push(&mut self, event: Event) { + pub fn push(&mut self, event: Event) { if self.queue.len() < (self.limit as usize) { self.queue.push_back(event); } } /// Pops an event from the queue. - pub fn pop(&mut self) -> Option { + pub fn pop(&mut self) -> Option> { self.queue.pop_front() } } diff --git a/src/animation/machine/layer.rs b/fyrox-animation/src/machine/layer.rs similarity index 84% rename from src/animation/machine/layer.rs rename to fyrox-animation/src/machine/layer.rs index 96b712632..b50092ea0 100644 --- a/src/animation/machine/layer.rs +++ b/fyrox-animation/src/machine/layer.rs @@ -1,25 +1,20 @@ //! Layer is a separate state graph that usually animates only a part of nodes from animations. See docs of [`MachineLayer`] //! for more info. -use crate::animation::machine::node::AnimationEventCollectionStrategy; -use crate::animation::machine::AnimationPoseSource; -use crate::animation::AnimationEvent; use crate::{ - animation::{ - machine::{ - event::FixedEventQueue, Event, LayerMask, ParameterContainer, PoseNode, State, - Transition, - }, - Animation, AnimationContainer, AnimationPose, - }, core::{ log::{Log, MessageKind}, pool::{Handle, Pool}, reflect::prelude::*, visitor::prelude::*, }, - utils::{self, NameProvider}, + machine::{ + event::FixedEventQueue, node::AnimationEventCollectionStrategy, AnimationPoseSource, Event, + LayerMask, ParameterContainer, PoseNode, State, Transition, + }, + Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId, }; +use fyrox_core::{find_by_name_mut, find_by_name_ref, NameProvider}; /// Layer is a separate state graph. Layers mainly used to animate different parts of humanoid (but not only) characters. For /// example there could a layer for upper body and a layer for lower body. Upper body layer could contain animations for aiming, @@ -30,20 +25,21 @@ use crate::{ /// # Example /// /// ```rust -/// use fyrox::{ -/// animation::machine::{ +/// use fyrox_animation::{ +/// machine::{ /// State, Transition, PoseNode, MachineLayer, /// Parameter, PlayAnimation, PoseWeight, BlendAnimations, BlendPose /// }, /// core::pool::Handle /// }; +/// use fyrox_core::pool::ErasedHandle; /// /// // Assume that these are correct handles. /// let idle_animation = Handle::default(); /// let walk_animation = Handle::default(); /// let aim_animation = Handle::default(); /// -/// let mut root_layer = MachineLayer::new(); +/// let mut root_layer = MachineLayer::::new(); /// /// let aim = root_layer.add_node(PoseNode::PlayAnimation(PlayAnimation::new(aim_animation))); /// let walk = root_layer.add_node(PoseNode::PlayAnimation(PlayAnimation::new(walk_animation))); @@ -66,45 +62,45 @@ use crate::{ /// /// ``` #[derive(Default, Debug, Visit, Reflect, Clone, PartialEq)] -pub struct MachineLayer { +pub struct MachineLayer { name: String, weight: f32, - mask: LayerMask, + mask: LayerMask, #[reflect(hidden)] - nodes: Pool, + nodes: Pool>, #[reflect(hidden)] - transitions: Pool, + transitions: Pool>, #[reflect(hidden)] - states: Pool, + states: Pool>, #[reflect(hidden)] - active_state: Handle, + active_state: Handle>, #[reflect(hidden)] - entry_state: Handle, + entry_state: Handle>, #[reflect(hidden)] - active_transition: Handle, + active_transition: Handle>, #[visit(skip)] #[reflect(hidden)] - final_pose: AnimationPose, + final_pose: AnimationPose, #[visit(skip)] #[reflect(hidden)] - events: FixedEventQueue, + events: FixedEventQueue, #[visit(skip)] #[reflect(hidden)] debug: bool, } -impl NameProvider for MachineLayer { +impl NameProvider for MachineLayer { fn name(&self) -> &str { &self.name } @@ -112,25 +108,25 @@ impl NameProvider for MachineLayer { /// A source of animation events coming from a layer. #[derive(Default)] -pub enum AnimationEventsSource { +pub enum AnimationEventsSource { /// Layer is malformed and no events were gathered. #[default] Unknown, /// Animation events were gathered from a state. State { /// A handle of a state, from which the events were collected. - handle: Handle, + handle: Handle>, /// A name of a state, from which the events were collected. name: String, }, /// Animation events were gathered from both states of a transition. Transition { /// A handle of an active transition. - handle: Handle, + handle: Handle>, /// A handle of a source state of an active transition. - source_state_handle: Handle, + source_state_handle: Handle>, /// A handle of a destination state of an active transition. - dest_state_handle: Handle, + dest_state_handle: Handle>, /// A name of a source state of an active transition. source_state_name: String, /// A name of a destination state of an active transition. @@ -141,14 +137,14 @@ pub enum AnimationEventsSource { /// A collection of events gathered from an active state (or a transition between states). See docs of [`MachineLayer::collect_active_animations_events`] /// for more info and usage examples. #[derive(Default)] -pub struct LayerAnimationEventsCollection { +pub struct LayerAnimationEventsCollection { /// A source of events. - pub source: AnimationEventsSource, + pub source: AnimationEventsSource, /// Actual animation events, defined as a tuple `(animation handle, event)`. - pub events: Vec<(Handle, AnimationEvent)>, + pub events: Vec<(Handle>, AnimationEvent)>, } -impl MachineLayer { +impl MachineLayer { /// Creates a new machine layer. See examples in [`MachineLayer`] docs. #[inline] pub fn new() -> Self { @@ -182,21 +178,21 @@ impl MachineLayer { /// Adds a new node to the layer and returns its handle. #[inline] - pub fn add_node(&mut self, node: PoseNode) -> Handle { + pub fn add_node(&mut self, node: PoseNode) -> Handle> { self.nodes.spawn(node) } /// Sets new entry state of the layer. Entry state will always be active on the first frame and will remain active /// until some transition won't change it. #[inline] - pub fn set_entry_state(&mut self, entry_state: Handle) { + pub fn set_entry_state(&mut self, entry_state: Handle>) { self.active_state = entry_state; self.entry_state = entry_state; } /// Returns a handle of current entry state. #[inline] - pub fn entry_state(&self) -> Handle { + pub fn entry_state(&self) -> Handle> { self.entry_state } @@ -209,7 +205,7 @@ impl MachineLayer { /// Adds a new state to the layer and returns its handle. #[inline] - pub fn add_state(&mut self, state: State) -> Handle { + pub fn add_state(&mut self, state: State) -> Handle> { let state = self.states.spawn(state); if self.active_state.is_none() { self.active_state = state; @@ -219,19 +215,19 @@ impl MachineLayer { /// Adds a new transition to the layer and returns its handle. #[inline] - pub fn add_transition(&mut self, transition: Transition) -> Handle { + pub fn add_transition(&mut self, transition: Transition) -> Handle> { self.transitions.spawn(transition) } /// Borrows a state using its handle, panics if the handle is invalid. #[inline] - pub fn get_state(&self, state: Handle) -> &State { + pub fn get_state(&self, state: Handle>) -> &State { &self.states[state] } /// Borrows a transition using its handle, panics if the handle is invalid. #[inline] - pub fn get_transition(&self, transition: Handle) -> &Transition { + pub fn get_transition(&self, transition: Handle>) -> &Transition { &self.transitions[transition] } @@ -241,9 +237,10 @@ impl MachineLayer { /// # Example /// /// ```rust - /// use fyrox::animation::machine::{Event, MachineLayer}; + /// use fyrox_animation::machine::{Event, MachineLayer}; + /// use fyrox_core::pool::ErasedHandle; /// - /// let mut layer = MachineLayer::new(); + /// let mut layer = MachineLayer::::new(); /// /// while let Some(event) = layer.pop_event() { /// match event { @@ -263,7 +260,7 @@ impl MachineLayer { /// } /// ``` #[inline] - pub fn pop_event(&mut self) -> Option { + pub fn pop_event(&mut self) -> Option> { self.events.pop() } @@ -290,9 +287,9 @@ impl MachineLayer { pub fn collect_active_animations_events( &self, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, strategy: AnimationEventCollectionStrategy, - ) -> LayerAnimationEventsCollection { + ) -> LayerAnimationEventsCollection { if let Some(state) = self.states.try_borrow(self.active_state) { return LayerAnimationEventsCollection { source: AnimationEventsSource::State { @@ -384,25 +381,25 @@ impl MachineLayer { /// Tries to borrow a node by its handle, panics if the handle is invalid. #[inline] - pub fn node(&self, handle: Handle) -> &PoseNode { + pub fn node(&self, handle: Handle>) -> &PoseNode { &self.nodes[handle] } /// Tries to borrow a node by its handle, panics if the handle is invalid. #[inline] - pub fn node_mut(&mut self, handle: Handle) -> &mut PoseNode { + pub fn node_mut(&mut self, handle: Handle>) -> &mut PoseNode { &mut self.nodes[handle] } /// Returns a reference to inner node container. #[inline] - pub fn nodes(&self) -> &Pool { + pub fn nodes(&self) -> &Pool> { &self.nodes } /// Returns a reference to inner node container. #[inline] - pub fn nodes_mut(&mut self) -> &mut Pool { + pub fn nodes_mut(&mut self) -> &mut Pool> { &mut self.nodes } @@ -410,38 +407,38 @@ impl MachineLayer { /// state is active. For example jumping could be done only from `idle` and `run` state, and not from /// `crouch` and other states. #[inline] - pub fn active_state(&self) -> Handle { + pub fn active_state(&self) -> Handle> { self.active_state } /// Returns a handle of active transition. It is not empty only while a transition is active (doing blending /// between states). #[inline] - pub fn active_transition(&self) -> Handle { + pub fn active_transition(&self) -> Handle> { self.active_transition } /// Tries to borrow a transition using its handle, panics if the handle is invalid. #[inline] - pub fn transition(&self, handle: Handle) -> &Transition { + pub fn transition(&self, handle: Handle>) -> &Transition { &self.transitions[handle] } /// Tries to borrow a transition using its handle, panics if the handle is invalid. #[inline] - pub fn transition_mut(&mut self, handle: Handle) -> &mut Transition { + pub fn transition_mut(&mut self, handle: Handle>) -> &mut Transition { &mut self.transitions[handle] } /// Returns a reference to inner transitions container. #[inline] - pub fn transitions(&self) -> &Pool { + pub fn transitions(&self) -> &Pool> { &self.transitions } /// Returns a reference to inner transitions container. #[inline] - pub fn transitions_mut(&mut self) -> &mut Pool { + pub fn transitions_mut(&mut self) -> &mut Pool> { &mut self.transitions } @@ -450,8 +447,8 @@ impl MachineLayer { pub fn find_transition_by_name_ref>( &self, name: S, - ) -> Option<(Handle, &Transition)> { - utils::find_by_name_ref(self.transitions.pair_iter(), name) + ) -> Option<(Handle>, &Transition)> { + find_by_name_ref(self.transitions.pair_iter(), name) } /// Tries to find a transition by its name. @@ -459,19 +456,19 @@ impl MachineLayer { pub fn find_transition_by_name_mut>( &mut self, name: S, - ) -> Option<(Handle, &mut Transition)> { - utils::find_by_name_mut(self.transitions.pair_iter_mut(), name) + ) -> Option<(Handle>, &mut Transition)> { + find_by_name_mut(self.transitions.pair_iter_mut(), name) } /// Tries to borrow a state using its handle, panics if the handle is invalid. #[inline] - pub fn state(&self, handle: Handle) -> &State { + pub fn state(&self, handle: Handle>) -> &State { &self.states[handle] } /// Tries to borrow a state using its handle, panics if the handle is invalid. #[inline] - pub fn state_mut(&mut self, handle: Handle) -> &mut State { + pub fn state_mut(&mut self, handle: Handle>) -> &mut State { &mut self.states[handle] } @@ -480,8 +477,8 @@ impl MachineLayer { pub fn find_state_by_name_ref>( &self, name: S, - ) -> Option<(Handle, &State)> { - utils::find_by_name_ref(self.states.pair_iter(), name) + ) -> Option<(Handle>, &State)> { + find_by_name_ref(self.states.pair_iter(), name) } /// Tries to find a state by its name. @@ -489,19 +486,19 @@ impl MachineLayer { pub fn find_state_by_name_mut>( &mut self, name: S, - ) -> Option<(Handle, &mut State)> { - utils::find_by_name_mut(self.states.pair_iter_mut(), name) + ) -> Option<(Handle>, &mut State)> { + find_by_name_mut(self.states.pair_iter_mut(), name) } /// Returns a reference to inner states container. #[inline] - pub fn states(&self) -> &Pool { + pub fn states(&self) -> &Pool> { &self.states } /// Returns a reference to inner states container. #[inline] - pub fn states_mut(&mut self) -> &mut Pool { + pub fn states_mut(&mut self) -> &mut Pool> { &mut self.states } @@ -520,19 +517,19 @@ impl MachineLayer { /// Sets new layer mask. See docs of [`LayerMask`] for more info about layer masks. #[inline] - pub fn set_mask(&mut self, mask: LayerMask) -> LayerMask { + pub fn set_mask(&mut self, mask: LayerMask) -> LayerMask { std::mem::replace(&mut self.mask, mask) } /// Returns a reference to current layer mask. #[inline] - pub fn mask(&self) -> &LayerMask { + pub fn mask(&self) -> &LayerMask { &self.mask } /// Returns final pose of the layer. #[inline] - pub fn pose(&self) -> &AnimationPose { + pub fn pose(&self) -> &AnimationPose { &self.final_pose } @@ -541,8 +538,8 @@ impl MachineLayer { /// to listen for animation events and react to them. pub fn animations_of_state( &self, - state: Handle, - ) -> impl Iterator> + '_ { + state: Handle>, + ) -> impl Iterator>> + '_ { self.nodes.iter().filter_map(move |node| { if node.parent_state == state { if let PoseNode::PlayAnimation(play_animation) = node { @@ -559,8 +556,8 @@ impl MachineLayer { /// Returns `true` if all animations of the given state has ended, `false` - otherwise. pub fn is_all_animations_of_state_ended( &self, - state: Handle, - animations: &AnimationContainer, + state: Handle>, + animations: &AnimationContainer, ) -> bool { self.animations_of_state(state) .filter_map(|a| animations.try_get(a)) @@ -570,10 +567,10 @@ impl MachineLayer { #[inline] pub(super) fn evaluate_pose( &mut self, - animations: &mut AnimationContainer, + animations: &mut AnimationContainer, parameters: &ParameterContainer, dt: f32, - ) -> &AnimationPose { + ) -> &AnimationPose { self.final_pose.reset(); if self.active_state.is_some() || self.active_transition.is_some() { diff --git a/src/animation/machine/mask.rs b/fyrox-animation/src/machine/mask.rs similarity index 52% rename from src/animation/machine/mask.rs rename to fyrox-animation/src/machine/mask.rs index 995d95034..64c29d2c0 100644 --- a/src/animation/machine/mask.rs +++ b/fyrox-animation/src/machine/mask.rs @@ -1,36 +1,27 @@ //! Layer mask is a sort of blacklist that prevents layer from animating certain nodes. See [`LayerMask`] docs //! for more info. -use crate::{ - core::{pool::Handle, reflect::prelude::*, visitor::prelude::*}, - scene::{graph::Graph, node::Node}, -}; +use crate::core::{reflect::prelude::*, visitor::prelude::*}; +use crate::EntityId; /// Layer mask is a sort of blacklist that prevents layer from animating certain nodes. Its main use case is to /// disable animation on animation layers for specific body parts of humanoid (but not only) characters. The /// mask holds handles of nodes that **will not** be animated. #[derive(Default, Debug, Visit, Reflect, Clone, PartialEq, Eq)] -pub struct LayerMask { - excluded_bones: Vec>, +pub struct LayerMask { + excluded_bones: Vec, } -impl From>> for LayerMask { - fn from(mut excluded_bones: Vec>) -> Self { - excluded_bones.sort_by_key(|h| h.index()); +impl From> for LayerMask { + fn from(mut excluded_bones: Vec) -> Self { + excluded_bones.sort(); Self { excluded_bones } } } -impl LayerMask { - /// Creates a layer mask for every descendant node starting from specified `root` (included). It could - /// be useful if you have an entire node hierarchy (for example, lower part of a body) that needs to - /// be filtered out. - pub fn from_hierarchy(graph: &Graph, root: Handle) -> Self { - Self::from(graph.traverse_handle_iter(root).collect::>()) - } - +impl LayerMask { /// Merges a given layer mask in the current mask, handles will be automatically de-duplicated. - pub fn merge(&mut self, other: LayerMask) { + pub fn merge(&mut self, other: LayerMask) { for handle in other.into_inner() { if !self.contains(handle) { self.add(handle); @@ -46,10 +37,8 @@ impl LayerMask { /// /// The method has O(log(n)) complexity, which means it is very fast for most use cases. #[inline] - pub fn add(&mut self, node: Handle) { - let index = self - .excluded_bones - .partition_point(|h| h.index() < node.index()); + pub fn add(&mut self, node: T) { + let index = self.excluded_bones.partition_point(|h| h < &node); self.excluded_bones.insert(index, node); } @@ -59,37 +48,14 @@ impl LayerMask { /// # Performance /// /// The method has O(log(n)) complexity, which means it is very fast for most use cases. - pub fn remove(&mut self, node: Handle) { + pub fn remove(&mut self, node: T) { if let Some(index) = self.index_of(node) { self.excluded_bones.remove(index); } } - fn index_of(&self, node: Handle) -> Option { - if let Ok(mut index) = self - .excluded_bones - .binary_search_by(|h| h.index().cmp(&node.index())) - { - // We could have multiple handles with the same index, but different generation. - // In this case we check every handle. - loop { - if let Some(current) = self.excluded_bones.get(index) { - if current.index() == node.index() { - if current.generation() == node.generation() { - return Some(index); - } - } else { - return None; - } - } else { - return None; - } - - index += 1; - } - } - - None + fn index_of(&self, id: T) -> Option { + self.excluded_bones.binary_search(&id).ok() } /// Checks if the mask contains a given node handle or not. @@ -98,7 +64,7 @@ impl LayerMask { /// /// The method has O(log(n)) complexity, which means it is very fast for most use cases. #[inline] - pub fn contains(&self, node: Handle) -> bool { + pub fn contains(&self, node: T) -> bool { self.index_of(node).is_some() } @@ -108,20 +74,20 @@ impl LayerMask { /// /// The method has O(log(n)) complexity, which means it is very fast for most use cases. #[inline] - pub fn should_animate(&self, node: Handle) -> bool { + pub fn should_animate(&self, node: T) -> bool { !self.contains(node) } /// Return a reference to inner container. There's only non-mutable version because inner container must always /// be sorted. #[inline] - pub fn inner(&self) -> &Vec> { + pub fn inner(&self) -> &Vec { &self.excluded_bones } /// Converts the mask into inner container. #[inline] - pub fn into_inner(self) -> Vec> { + pub fn into_inner(self) -> Vec { self.excluded_bones } } diff --git a/src/animation/machine/mod.rs b/fyrox-animation/src/machine/mod.rs similarity index 90% rename from src/animation/machine/mod.rs rename to fyrox-animation/src/machine/mod.rs index ac782ab04..2060ea564 100644 --- a/src/animation/machine/mod.rs +++ b/fyrox-animation/src/machine/mod.rs @@ -6,15 +6,15 @@ #![warn(missing_docs)] use crate::{ - animation::{AnimationContainer, AnimationPose}, core::{ reflect::prelude::*, visitor::{Visit, VisitResult, Visitor}, }, - utils, + AnimationContainer, AnimationPose, EntityId, }; pub use event::Event; +use fyrox_core::{find_by_name_mut, find_by_name_ref}; pub use layer::MachineLayer; pub use mask::LayerMask; pub use node::{ @@ -122,20 +122,21 @@ pub mod transition; /// using code like so: /// /// ```no_run -/// use fyrox::{ -/// animation::machine::{ +/// use fyrox_animation::{ +/// machine::{ /// Machine, State, Transition, PoseNode, /// Parameter, PlayAnimation, PoseWeight, BlendAnimations, BlendPose /// }, /// core::pool::Handle /// }; +/// use fyrox_core::pool::ErasedHandle; /// /// // Assume that these are correct handles. /// let idle_animation = Handle::default(); /// let walk_animation = Handle::default(); /// let aim_animation = Handle::default(); /// -/// let mut machine = Machine::new(); +/// let mut machine = Machine::::new(); /// /// let root_layer = &mut machine.layers_mut()[0]; /// @@ -167,18 +168,18 @@ pub mod transition; /// /// Complex state machines quite hard to create from code, you should use ABSM editor instead whenever possible. #[derive(Default, Debug, Visit, Reflect, Clone, PartialEq)] -pub struct Machine { +pub struct Machine { parameters: ParameterContainer, #[visit(optional)] - layers: Vec, + layers: Vec>, #[visit(skip)] #[reflect(hidden)] - final_pose: AnimationPose, + final_pose: AnimationPose, } -impl Machine { +impl Machine { /// Creates a new animation blending state machine with a single animation layer. #[inline] pub fn new() -> Self { @@ -193,9 +194,10 @@ impl Machine { /// The method returns a reference to the machine, so the calls could be chained: /// /// ```rust - /// use fyrox::animation::machine::{Machine, Parameter}; + /// use fyrox_animation::machine::{Machine, Parameter}; + /// use fyrox_core::pool::ErasedHandle; /// - /// let mut machine = Machine::new(); + /// let mut machine = Machine::::new(); /// /// machine /// .set_parameter("Run", Parameter::Rule(true)) @@ -229,44 +231,47 @@ impl Machine { /// Adds a new layer to the animation blending state machine. #[inline] - pub fn add_layer(&mut self, layer: MachineLayer) { + pub fn add_layer(&mut self, layer: MachineLayer) { self.layers.push(layer) } /// Removes a layer at given index. Panics if index is out-of-bounds. #[inline] - pub fn remove_layer(&mut self, index: usize) -> MachineLayer { + pub fn remove_layer(&mut self, index: usize) -> MachineLayer { self.layers.remove(index) } /// Inserts a layer at given position, panics in index is out-of-bounds. #[inline] - pub fn insert_layer(&mut self, index: usize, layer: MachineLayer) { + pub fn insert_layer(&mut self, index: usize, layer: MachineLayer) { self.layers.insert(index, layer) } /// Removes last layer from the list. #[inline] - pub fn pop_layer(&mut self) -> Option { + pub fn pop_layer(&mut self) -> Option> { self.layers.pop() } /// Returns a shared reference to the list of layers. #[inline] - pub fn layers(&self) -> &[MachineLayer] { + pub fn layers(&self) -> &[MachineLayer] { &self.layers } /// Returns a mutable reference to the list of layers. #[inline] - pub fn layers_mut(&mut self) -> &mut [MachineLayer] { + pub fn layers_mut(&mut self) -> &mut [MachineLayer] { &mut self.layers } /// Tries to find a layer by its name. Returns index of the layer and its reference. #[inline] - pub fn find_layer_by_name_ref>(&self, name: S) -> Option<(usize, &MachineLayer)> { - utils::find_by_name_ref(self.layers.iter().enumerate(), name) + pub fn find_layer_by_name_ref>( + &self, + name: S, + ) -> Option<(usize, &MachineLayer)> { + find_by_name_ref(self.layers.iter().enumerate(), name) } /// Tries to find a layer by its name. Returns index of the layer and its reference. @@ -274,23 +279,23 @@ impl Machine { pub fn find_by_name_mut>( &mut self, name: S, - ) -> Option<(usize, &mut MachineLayer)> { - utils::find_by_name_mut(self.layers.iter_mut().enumerate(), name) + ) -> Option<(usize, &mut MachineLayer)> { + find_by_name_mut(self.layers.iter_mut().enumerate(), name) } /// Returns final pose of the machine. #[inline] - pub fn pose(&self) -> &AnimationPose { + pub fn pose(&self) -> &AnimationPose { &self.final_pose } - /// Computes final animation pose that could be then applied to a scene graph. + /// Computes final animation pose that could be then applied to a set of entities graph. #[inline] pub fn evaluate_pose( &mut self, - animations: &mut AnimationContainer, + animations: &mut AnimationContainer, dt: f32, - ) -> &AnimationPose { + ) -> &AnimationPose { self.final_pose.reset(); for layer in self.layers.iter_mut() { diff --git a/src/animation/machine/node/blend.rs b/fyrox-animation/src/machine/node/blend.rs similarity index 84% rename from src/animation/machine/node/blend.rs rename to fyrox-animation/src/machine/node/blend.rs index 954bfa760..51889ae7c 100644 --- a/src/animation/machine/node/blend.rs +++ b/fyrox-animation/src/machine/node/blend.rs @@ -1,22 +1,19 @@ //! Various animation blending nodes. -use crate::animation::machine::node::AnimationEventCollectionStrategy; -use crate::animation::{Animation, AnimationEvent}; use crate::{ - animation::{ - machine::{ - node::BasePoseNode, AnimationPoseSource, Parameter, ParameterContainer, PoseNode, - PoseWeight, - }, - AnimationContainer, AnimationPose, - }, core::{ pool::{Handle, Pool}, reflect::prelude::*, visitor::{Visit, VisitResult, Visitor}, }, + machine::{ + node::AnimationEventCollectionStrategy, node::BasePoseNode, AnimationPoseSource, Parameter, + ParameterContainer, PoseNode, PoseWeight, + }, + Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId, }; -use fyrox_core::uuid_provider; +use fyrox_core::uuid::{uuid, Uuid}; +use fyrox_core::TypeUuidProvider; use std::cmp::Ordering; use std::{ cell::{Cell, Ref, RefCell}, @@ -26,20 +23,24 @@ use std::{ /// Weighted proxy for animation pose. It has an input pose source and a weight, that tells in which proportion /// the pose should be blended into final pose. #[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)] -pub struct BlendPose { +pub struct BlendPose { /// Weight of the pose. pub weight: PoseWeight, /// A source of animation pose. #[reflect(hidden)] - pub pose_source: Handle, + pub pose_source: Handle>, } -uuid_provider!(BlendPose = "b01d7639-7b39-4eaf-87e6-29fd5221951b"); +impl TypeUuidProvider for BlendPose { + fn type_uuid() -> Uuid { + uuid!("b01d7639-7b39-4eaf-87e6-29fd5221951b") + } +} -impl BlendPose { +impl BlendPose { /// Creates new instance of blend pose with given weight and animation pose. - pub fn new(weight: PoseWeight, pose_source: Handle) -> Self { + pub fn new(weight: PoseWeight, pose_source: Handle>) -> Self { Self { weight, pose_source, @@ -48,7 +49,7 @@ impl BlendPose { /// Specialized constructor that creates blend pose with constant weight. /// `weight` should be positive. - pub fn with_constant_weight(weight: f32, pose_source: Handle) -> Self { + pub fn with_constant_weight(weight: f32, pose_source: Handle>) -> Self { Self { weight: PoseWeight::Constant(weight), pose_source, @@ -57,7 +58,7 @@ impl BlendPose { /// Specialized constructor that creates blend pose with parametrized weight. /// `param_id` must be name of Weight parameter in machine. - pub fn with_param_weight(param_id: &str, pose_source: Handle) -> Self { + pub fn with_param_weight(param_id: &str, pose_source: Handle>) -> Self { Self { weight: PoseWeight::Parameter(param_id.to_owned()), pose_source, @@ -73,36 +74,36 @@ impl BlendPose { /// can decrease weight of hit animation over time and increase weight of run animation, so character will recover /// from his wounds. #[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)] -pub struct BlendAnimations { +pub struct BlendAnimations { /// Base node. - pub base: BasePoseNode, + pub base: BasePoseNode, /// A list of pose sources. See [`BlendPose`] docs for more info. - pub pose_sources: Vec, + pub pose_sources: Vec>, /// Output pose of the node, contains final result of blending all input poses. #[visit(skip)] #[reflect(hidden)] - pub output_pose: RefCell, + pub output_pose: RefCell>, } -impl Deref for BlendAnimations { - type Target = BasePoseNode; +impl Deref for BlendAnimations { + type Target = BasePoseNode; fn deref(&self) -> &Self::Target { &self.base } } -impl DerefMut for BlendAnimations { +impl DerefMut for BlendAnimations { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.base } } -impl BlendAnimations { +impl BlendAnimations { /// Creates new animation blend node with given poses. - pub fn new(poses: Vec) -> Self { + pub fn new(poses: Vec>) -> Self { Self { base: Default::default(), pose_sources: poses, @@ -111,19 +112,19 @@ impl BlendAnimations { } /// Returns a set of handles to children pose nodes. - pub fn children(&self) -> Vec> { + pub fn children(&self) -> Vec>> { self.pose_sources.iter().map(|s| s.pose_source).collect() } } -impl AnimationPoseSource for BlendAnimations { +impl AnimationPoseSource for BlendAnimations { fn eval_pose( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, dt: f32, - ) -> Ref { + ) -> Ref> { self.output_pose.borrow_mut().reset(); for blend_pose in self.pose_sources.iter() { let weight = match blend_pose.weight { @@ -149,17 +150,17 @@ impl AnimationPoseSource for BlendAnimations { self.output_pose.borrow() } - fn pose(&self) -> Ref { + fn pose(&self) -> Ref> { self.output_pose.borrow() } fn collect_animation_events( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, strategy: AnimationEventCollectionStrategy, - ) -> Vec<(Handle, AnimationEvent)> { + ) -> Vec<(Handle>, AnimationEvent)> { match strategy { AnimationEventCollectionStrategy::All => { let mut events = Vec::new(); @@ -209,16 +210,20 @@ impl AnimationPoseSource for BlendAnimations { /// An animation pose with specific blend time. Blend time tells the engine how many time it should use to perform /// blending to this pose. #[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)] -pub struct IndexedBlendInput { +pub struct IndexedBlendInput { /// Blend time tells the engine how many time it should use to perform blending to this pose. pub blend_time: f32, /// A handle to pose node source. #[reflect(hidden)] - pub pose_source: Handle, + pub pose_source: Handle>, } -uuid_provider!(IndexedBlendInput = "92fcc992-9a68-4152-8449-657546faa286"); +impl TypeUuidProvider for IndexedBlendInput { + fn type_uuid() -> Uuid { + uuid!("92fcc992-9a68-4152-8449-657546faa286") + } +} /// A node that switches between given animations using index and smoothly blends from one animation to another /// while switching. It is very useful for situations when you need to switch between different animations. For @@ -229,15 +234,15 @@ uuid_provider!(IndexedBlendInput = "92fcc992-9a68-4152-8449-657546faa286"); /// parameter in the machine parameters. The node will automatically perform smooth transition between different /// animations. #[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)] -pub struct BlendAnimationsByIndex { +pub struct BlendAnimationsByIndex { /// Base node. - pub base: BasePoseNode, + pub base: BasePoseNode, /// A name of index parameter that will be used to switch between input poses. pub index_parameter: String, /// A set of input poses. - pub inputs: Vec, + pub inputs: Vec>, /// Index of a previously active input pose. #[reflect(hidden)] @@ -250,26 +255,26 @@ pub struct BlendAnimationsByIndex { /// Output pose of the node. #[visit(skip)] #[reflect(hidden)] - pub output_pose: RefCell, + pub output_pose: RefCell>, } -impl Deref for BlendAnimationsByIndex { - type Target = BasePoseNode; +impl Deref for BlendAnimationsByIndex { + type Target = BasePoseNode; fn deref(&self) -> &Self::Target { &self.base } } -impl DerefMut for BlendAnimationsByIndex { +impl DerefMut for BlendAnimationsByIndex { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.base } } -impl BlendAnimationsByIndex { +impl BlendAnimationsByIndex { /// Creates new [`BlendAnimationsByIndex`] node using given index parameter name and a set of inputs. - pub fn new(index_parameter: String, inputs: Vec) -> Self { + pub fn new(index_parameter: String, inputs: Vec>) -> Self { Self { base: Default::default(), index_parameter, @@ -281,19 +286,19 @@ impl BlendAnimationsByIndex { } /// Return a set of handle of children nodes. - pub fn children(&self) -> Vec> { + pub fn children(&self) -> Vec>> { self.inputs.iter().map(|s| s.pose_source).collect() } } -impl AnimationPoseSource for BlendAnimationsByIndex { +impl AnimationPoseSource for BlendAnimationsByIndex { fn eval_pose( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, dt: f32, - ) -> Ref { + ) -> Ref> { self.output_pose.borrow_mut().reset(); if let Some(&Parameter::Index(current_index)) = params.get(&self.index_parameter) { @@ -347,17 +352,17 @@ impl AnimationPoseSource for BlendAnimationsByIndex { self.output_pose.borrow() } - fn pose(&self) -> Ref { + fn pose(&self) -> Ref> { self.output_pose.borrow() } fn collect_animation_events( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, strategy: AnimationEventCollectionStrategy, - ) -> Vec<(Handle, AnimationEvent)> { + ) -> Vec<(Handle>, AnimationEvent)> { if let Some(&Parameter::Index(current_index)) = params.get(&self.index_parameter) { if let Some(prev_index) = self.prev_index.get() { if prev_index != current_index { diff --git a/src/animation/machine/node/blendspace.rs b/fyrox-animation/src/machine/node/blendspace.rs similarity index 86% rename from src/animation/machine/node/blendspace.rs rename to fyrox-animation/src/machine/node/blendspace.rs index bf92552eb..f5dbb065d 100644 --- a/src/animation/machine/node/blendspace.rs +++ b/fyrox-animation/src/machine/node/blendspace.rs @@ -1,14 +1,6 @@ #![allow(missing_docs)] // TODO -use crate::animation::machine::node::AnimationEventCollectionStrategy; -use crate::animation::{Animation, AnimationEvent}; use crate::{ - animation::{ - machine::{ - node::BasePoseNode, AnimationPoseSource, Parameter, ParameterContainer, PoseNode, - }, - AnimationContainer, AnimationPose, - }, core::{ algebra::Vector2, math::{self, TriangleDefinition}, @@ -16,8 +8,14 @@ use crate::{ reflect::prelude::*, visitor::prelude::*, }, + machine::{ + node::AnimationEventCollectionStrategy, node::BasePoseNode, AnimationPoseSource, Parameter, + ParameterContainer, PoseNode, + }, + Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId, }; -use fyrox_core::uuid_provider; +use fyrox_core::uuid::{uuid, Uuid}; +use fyrox_core::TypeUuidProvider; use spade::{DelaunayTriangulation, Point2, Triangulation}; use std::cmp::Ordering; use std::{ @@ -26,18 +24,23 @@ use std::{ }; #[derive(Debug, Visit, Clone, Reflect, PartialEq, Default)] -pub struct BlendSpacePoint { +pub struct BlendSpacePoint { pub position: Vector2, - pub pose_source: Handle, + pub pose_source: Handle>, +} + +impl TypeUuidProvider for BlendSpacePoint { + fn type_uuid() -> Uuid { + uuid!("d163b4b9-aed6-447f-bb93-b7e539099417") + } } -uuid_provider!(BlendSpacePoint = "d163b4b9-aed6-447f-bb93-b7e539099417"); #[derive(Debug, Visit, Clone, Reflect, PartialEq)] -pub struct BlendSpace { - base: BasePoseNode, +pub struct BlendSpace { + base: BasePoseNode, #[reflect(hidden)] - points: Vec, + points: Vec>, #[reflect(hidden)] triangles: Vec, @@ -62,10 +65,10 @@ pub struct BlendSpace { #[reflect(hidden)] #[visit(skip)] - pose: RefCell, + pose: RefCell>, } -impl Default for BlendSpace { +impl Default for BlendSpace { fn default() -> Self { Self { base: Default::default(), @@ -82,28 +85,28 @@ impl Default for BlendSpace { } } -impl Deref for BlendSpace { - type Target = BasePoseNode; +impl Deref for BlendSpace { + type Target = BasePoseNode; fn deref(&self) -> &Self::Target { &self.base } } -impl DerefMut for BlendSpace { +impl DerefMut for BlendSpace { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.base } } -impl AnimationPoseSource for BlendSpace { +impl AnimationPoseSource for BlendSpace { fn eval_pose( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, dt: f32, - ) -> Ref { + ) -> Ref> { let mut pose = self.pose.borrow_mut(); pose.reset(); @@ -132,17 +135,17 @@ impl AnimationPoseSource for BlendSpace { self.pose.borrow() } - fn pose(&self) -> Ref { + fn pose(&self) -> Ref> { self.pose.borrow() } fn collect_animation_events( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, strategy: AnimationEventCollectionStrategy, - ) -> Vec<(Handle, AnimationEvent)> { + ) -> Vec<(Handle>, AnimationEvent)> { if let Some(Parameter::SamplingPoint(sampling_point)) = params.get(&self.sampling_parameter) { if let Some(weights) = self.fetch_weights(*sampling_point) { @@ -200,38 +203,38 @@ impl AnimationPoseSource for BlendSpace { } } -pub struct PointsMut<'a> { - blend_space: &'a mut BlendSpace, +pub struct PointsMut<'a, T: EntityId> { + blend_space: &'a mut BlendSpace, } -impl<'a> Deref for PointsMut<'a> { - type Target = Vec; +impl<'a, T: EntityId> Deref for PointsMut<'a, T> { + type Target = Vec>; fn deref(&self) -> &Self::Target { &self.blend_space.points } } -impl<'a> DerefMut for PointsMut<'a> { +impl<'a, T: EntityId> DerefMut for PointsMut<'a, T> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.blend_space.points } } -impl<'a> Drop for PointsMut<'a> { +impl<'a, T: EntityId> Drop for PointsMut<'a, T> { fn drop(&mut self) { self.blend_space.triangulate(); } } -impl BlendSpace { - pub fn add_point(&mut self, point: BlendSpacePoint) -> bool { +impl BlendSpace { + pub fn add_point(&mut self, point: BlendSpacePoint) -> bool { self.points.push(point); self.triangulate() } /// Sets new points to the blend space. - pub fn set_points(&mut self, points: Vec) -> bool { + pub fn set_points(&mut self, points: Vec>) -> bool { self.points = points; self.triangulate() } @@ -241,11 +244,11 @@ impl BlendSpace { self.triangles.clear(); } - pub fn points(&self) -> &[BlendSpacePoint] { + pub fn points(&self) -> &[BlendSpacePoint] { &self.points } - pub fn points_mut(&mut self) -> PointsMut { + pub fn points_mut(&mut self) -> PointsMut { PointsMut { blend_space: self } } @@ -253,7 +256,7 @@ impl BlendSpace { &self.triangles } - pub fn children(&self) -> Vec> { + pub fn children(&self) -> Vec>> { self.points.iter().map(|p| p.pose_source).collect() } @@ -429,13 +432,14 @@ impl BlendSpace { #[cfg(test)] mod test { use crate::{ - animation::machine::node::blendspace::{BlendSpace, BlendSpacePoint}, core::{algebra::Vector2, math::TriangleDefinition}, + machine::node::blendspace::{BlendSpace, BlendSpacePoint}, }; + use fyrox_core::pool::ErasedHandle; #[test] fn test_blend_space_triangulation() { - let mut blend_space = BlendSpace::default(); + let mut blend_space = BlendSpace::::default(); blend_space.set_points(vec![ BlendSpacePoint { @@ -466,14 +470,14 @@ mod test { #[test] fn test_empty_blend_space_sampling() { - assert!(BlendSpace::default() + assert!(BlendSpace::::default() .fetch_weights(Default::default()) .is_none()) } #[test] fn test_single_point_blend_space_sampling() { - let mut blend_space = BlendSpace::default(); + let mut blend_space = BlendSpace::::default(); blend_space.set_points(vec![BlendSpacePoint { position: Vector2::new(0.0, 0.0), @@ -488,7 +492,7 @@ mod test { #[test] fn test_two_points_blend_space_sampling() { - let mut blend_space = BlendSpace::default(); + let mut blend_space = BlendSpace::::default(); blend_space.set_points(vec![ BlendSpacePoint { diff --git a/src/animation/machine/node/mod.rs b/fyrox-animation/src/machine/node/mod.rs similarity index 70% rename from src/animation/machine/node/mod.rs rename to fyrox-animation/src/machine/node/mod.rs index 7c9adbaee..46de06343 100644 --- a/src/animation/machine/node/mod.rs +++ b/fyrox-animation/src/machine/node/mod.rs @@ -1,21 +1,18 @@ //! Node is a part of animation blending tree, that backs a state with animation data. See [`PoseNode`] docs for //! more info. -use crate::animation::AnimationEvent; use crate::{ - animation::{ - machine::{ - node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation}, - BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State, - }, - Animation, AnimationContainer, AnimationPose, - }, core::{ algebra::Vector2, pool::{Handle, Pool}, reflect::prelude::*, visitor::prelude::*, }, + machine::{ + node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation}, + BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State, + }, + Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId, }; use std::{ cell::Ref, @@ -28,45 +25,45 @@ pub mod play; /// A set of common data fields that is used in every node. #[derive(Debug, Visit, Clone, Default, Reflect, PartialEq)] -pub struct BasePoseNode { +pub struct BasePoseNode { /// Position on the canvas, it is editor-specific data. pub position: Vector2, /// A handle of parent state that "owns" the node. #[reflect(hidden)] - pub parent_state: Handle, + pub parent_state: Handle>, } /// Specialized node that provides animation pose. See documentation for each variant. #[derive(Debug, Visit, Clone, Reflect, PartialEq)] -pub enum PoseNode { +pub enum PoseNode { /// See docs for [`PlayAnimation`]. - PlayAnimation(PlayAnimation), + PlayAnimation(PlayAnimation), /// See docs for [`BlendAnimations`]. - BlendAnimations(BlendAnimations), + BlendAnimations(BlendAnimations), /// See docs for [`BlendAnimationsByIndex`]. - BlendAnimationsByIndex(BlendAnimationsByIndex), + BlendAnimationsByIndex(BlendAnimationsByIndex), /// See doc for [`BlendSpace`] - BlendSpace(BlendSpace), + BlendSpace(BlendSpace), } -impl Default for PoseNode { +impl Default for PoseNode { fn default() -> Self { Self::PlayAnimation(Default::default()) } } -impl PoseNode { +impl PoseNode { /// Creates new node that plays an animation. - pub fn make_play_animation(animation: Handle) -> Self { + pub fn make_play_animation(animation: Handle>) -> Self { Self::PlayAnimation(PlayAnimation::new(animation)) } /// Creates new node that blends multiple poses into one. - pub fn make_blend_animations(poses: Vec) -> Self { + pub fn make_blend_animations(poses: Vec>) -> Self { Self::BlendAnimations(BlendAnimations::new(poses)) } @@ -74,13 +71,13 @@ impl PoseNode { /// one animation to another while switching. pub fn make_blend_animations_by_index( index_parameter: String, - inputs: Vec, + inputs: Vec>, ) -> Self { Self::BlendAnimationsByIndex(BlendAnimationsByIndex::new(index_parameter, inputs)) } /// Returns a set of handles to children pose nodes. - pub fn children(&self) -> Vec> { + pub fn children(&self) -> Vec>> { match self { Self::PlayAnimation(_) => { // No children nodes. @@ -104,15 +101,15 @@ macro_rules! static_dispatch { }; } -impl Deref for PoseNode { - type Target = BasePoseNode; +impl Deref for PoseNode { + type Target = BasePoseNode; fn deref(&self) -> &Self::Target { static_dispatch!(self, deref,) } } -impl DerefMut for PoseNode { +impl DerefMut for PoseNode { fn deref_mut(&mut self) -> &mut Self::Target { static_dispatch!(self, deref_mut,) } @@ -130,51 +127,51 @@ pub enum AnimationEventCollectionStrategy { } /// A trait that responsible for animation pose evaluation. -pub trait AnimationPoseSource { +pub trait AnimationPoseSource { /// Evaluates animation pose and returns a reference to it. fn eval_pose( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, dt: f32, - ) -> Ref; + ) -> Ref>; /// Returns a reference to inner pose of a node. - fn pose(&self) -> Ref; + fn pose(&self) -> Ref>; /// Collects animation events from internals. fn collect_animation_events( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, strategy: AnimationEventCollectionStrategy, - ) -> Vec<(Handle, AnimationEvent)>; + ) -> Vec<(Handle>, AnimationEvent)>; } -impl AnimationPoseSource for PoseNode { +impl AnimationPoseSource for PoseNode { fn eval_pose( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, dt: f32, - ) -> Ref { + ) -> Ref> { static_dispatch!(self, eval_pose, nodes, params, animations, dt) } - fn pose(&self) -> Ref { + fn pose(&self) -> Ref> { static_dispatch!(self, pose,) } fn collect_animation_events( &self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, strategy: AnimationEventCollectionStrategy, - ) -> Vec<(Handle, AnimationEvent)> { + ) -> Vec<(Handle>, AnimationEvent)> { static_dispatch!( self, collect_animation_events, diff --git a/src/animation/machine/node/play.rs b/fyrox-animation/src/machine/node/play.rs similarity index 65% rename from src/animation/machine/node/play.rs rename to fyrox-animation/src/machine/node/play.rs index e130eafe9..6941e18d9 100644 --- a/src/animation/machine/node/play.rs +++ b/fyrox-animation/src/machine/node/play.rs @@ -1,20 +1,17 @@ //! A simplest pose node that extracts pose from a specific animation and prepares it for further use. -use crate::animation::machine::node::AnimationEventCollectionStrategy; -use crate::animation::AnimationEvent; use crate::{ - animation::{ - machine::{ - node::{AnimationPoseSource, BasePoseNode}, - ParameterContainer, PoseNode, - }, - Animation, AnimationContainer, AnimationPose, - }, core::{ pool::{Handle, Pool}, reflect::prelude::*, visitor::prelude::*, }, + machine::{ + node::AnimationEventCollectionStrategy, + node::{AnimationPoseSource, BasePoseNode}, + ParameterContainer, PoseNode, + }, + Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId, }; use std::{ cell::{Ref, RefCell}, @@ -25,37 +22,37 @@ use std::{ /// Animation handle should point to an animation in some animation container see [`AnimationContainer`] docs /// for more info. #[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)] -pub struct PlayAnimation { +pub struct PlayAnimation { /// Base node. - pub base: BasePoseNode, + pub base: BasePoseNode, /// A handle to animation. - pub animation: Handle, + pub animation: Handle>, - /// Output pose, it contains a filtered (see [`crate::animation::machine::LayerMask`] for more info) pose from + /// Output pose, it contains a filtered (see [`crate::machine::LayerMask`] for more info) pose from /// the animation specified by the `animation` field. #[visit(skip)] #[reflect(hidden)] - pub output_pose: RefCell, + pub output_pose: RefCell>, } -impl Deref for PlayAnimation { - type Target = BasePoseNode; +impl Deref for PlayAnimation { + type Target = BasePoseNode; fn deref(&self) -> &Self::Target { &self.base } } -impl DerefMut for PlayAnimation { +impl DerefMut for PlayAnimation { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.base } } -impl PlayAnimation { +impl PlayAnimation { /// Creates new PlayAnimation node with given animation handle. - pub fn new(animation: Handle) -> Self { + pub fn new(animation: Handle>) -> Self { Self { base: Default::default(), animation, @@ -64,14 +61,14 @@ impl PlayAnimation { } } -impl AnimationPoseSource for PlayAnimation { +impl AnimationPoseSource for PlayAnimation { fn eval_pose( &self, - _nodes: &Pool, + _nodes: &Pool>, _params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, _dt: f32, - ) -> Ref { + ) -> Ref> { if let Some(animation) = animations.try_get(self.animation) { let mut output_pose = self.output_pose.borrow_mut(); animation.pose().clone_into(&mut output_pose); @@ -81,17 +78,17 @@ impl AnimationPoseSource for PlayAnimation { self.output_pose.borrow() } - fn pose(&self) -> Ref { + fn pose(&self) -> Ref> { self.output_pose.borrow() } fn collect_animation_events( &self, - _nodes: &Pool, + _nodes: &Pool>, _params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, _strategy: AnimationEventCollectionStrategy, - ) -> Vec<(Handle, AnimationEvent)> { + ) -> Vec<(Handle>, AnimationEvent)> { animations .try_get(self.animation) .map(|a| { diff --git a/src/animation/machine/parameter.rs b/fyrox-animation/src/machine/parameter.rs similarity index 100% rename from src/animation/machine/parameter.rs rename to fyrox-animation/src/machine/parameter.rs diff --git a/src/animation/machine/state.rs b/fyrox-animation/src/machine/state.rs similarity index 73% rename from src/animation/machine/state.rs rename to fyrox-animation/src/machine/state.rs index 8c440297f..430c74a90 100644 --- a/src/animation/machine/state.rs +++ b/fyrox-animation/src/machine/state.rs @@ -1,20 +1,18 @@ //! State is a final "container" for animation pose. See [`State`] docs for more info. use crate::{ - animation::{ - machine::{AnimationPoseSource, ParameterContainer, PoseNode}, - Animation, AnimationContainer, AnimationPose, - }, core::{ algebra::Vector2, pool::{Handle, Pool}, + rand::{self, seq::IteratorRandom}, reflect::prelude::*, visitor::prelude::*, }, - rand::{self, seq::IteratorRandom}, - utils::NameProvider, + machine::{AnimationPoseSource, ParameterContainer, PoseNode}, + Animation, AnimationContainer, AnimationPose, EntityId, }; -use fyrox_core::uuid_provider; +use fyrox_core::uuid::{uuid, Uuid}; +use fyrox_core::{NameProvider, TypeUuidProvider}; use std::{ cell::Ref, ops::{Deref, DerefMut}, @@ -23,19 +21,23 @@ use strum_macros::{AsRefStr, EnumString, EnumVariantNames}; #[doc(hidden)] #[derive(Default, Debug, Visit, Reflect, Clone, PartialEq)] -pub struct StateActionWrapper(pub StateAction); +pub struct StateActionWrapper(pub StateAction); -uuid_provider!(StateActionWrapper = "d686fac8-5cc1-46b1-82a4-7f4438cc078d"); +impl TypeUuidProvider for StateActionWrapper { + fn type_uuid() -> Uuid { + uuid!("d686fac8-5cc1-46b1-82a4-7f4438cc078d") + } +} -impl Deref for StateActionWrapper { - type Target = StateAction; +impl Deref for StateActionWrapper { + type Target = StateAction; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for StateActionWrapper { +impl DerefMut for StateActionWrapper { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } @@ -50,28 +52,32 @@ impl DerefMut for StateActionWrapper { #[derive( Default, Debug, Visit, Reflect, Clone, PartialEq, EnumVariantNames, EnumString, AsRefStr, )] -pub enum StateAction { +pub enum StateAction { /// No action. #[default] None, /// Rewinds the animation. - RewindAnimation(Handle), + RewindAnimation(Handle>), /// Enables the animation. - EnableAnimation(Handle), + EnableAnimation(Handle>), /// Disables the animation. - DisableAnimation(Handle), + DisableAnimation(Handle>), /// Enables random animation from the list. It could be useful if you want to add randomization /// to your state machine. For example, you may have few melee attack animations and all of them /// are suitable for every situation, in this case you can add randomization to make attacks less /// predictable. - EnableRandomAnimation(Vec>), + EnableRandomAnimation(Vec>>), } -uuid_provider!(StateAction = "c50a15cc-0f63-4409-bbe0-74b9d3e94755"); +impl TypeUuidProvider for StateAction { + fn type_uuid() -> Uuid { + uuid!("c50a15cc-0f63-4409-bbe0-74b9d3e94755") + } +} -impl StateAction { +impl StateAction { /// Applies the action to the given animation container. - pub fn apply(&self, animations: &mut AnimationContainer) { + pub fn apply(&self, animations: &mut AnimationContainer) { match self { StateAction::None => {} StateAction::RewindAnimation(animation) => { @@ -103,7 +109,7 @@ impl StateAction { /// State is a final "container" for animation pose. It has backing pose node which provides a set of values. /// States can be connected with each other using _transitions_, states with transitions form a state graph. #[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)] -pub struct State { +pub struct State { /// Position of state on the canvas. It is editor-specific data. pub position: Vector2, @@ -112,26 +118,26 @@ pub struct State { /// A set of actions that will be executed when entering the state. #[visit(optional)] - pub on_enter_actions: Vec, + pub on_enter_actions: Vec>, /// A set of actions that will be executed when leaving the state. #[visit(optional)] - pub on_leave_actions: Vec, + pub on_leave_actions: Vec>, /// Root node of the state that provides the state with animation data. #[reflect(read_only)] - pub root: Handle, + pub root: Handle>, } -impl NameProvider for State { +impl NameProvider for State { fn name(&self) -> &str { &self.name } } -impl State { +impl State { /// Creates new instance of state with a given pose. - pub fn new(name: &str, root: Handle) -> Self { + pub fn new(name: &str, root: Handle>) -> Self { Self { position: Default::default(), name: name.to_owned(), @@ -142,15 +148,15 @@ impl State { } /// Returns a final pose of the state. - pub fn pose<'a>(&self, nodes: &'a Pool) -> Option> { + pub fn pose<'a>(&self, nodes: &'a Pool>) -> Option>> { nodes.try_borrow(self.root).map(|root| root.pose()) } pub(super) fn update( &mut self, - nodes: &Pool, + nodes: &Pool>, params: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, dt: f32, ) { if let Some(root) = nodes.try_borrow(self.root) { diff --git a/src/animation/machine/transition.rs b/fyrox-animation/src/machine/transition.rs similarity index 88% rename from src/animation/machine/transition.rs rename to fyrox-animation/src/machine/transition.rs index f0ea05b72..1900268c6 100644 --- a/src/animation/machine/transition.rs +++ b/fyrox-animation/src/machine/transition.rs @@ -1,14 +1,12 @@ //! Transition is a connection between two states with a rule that defines possibility of actual transition with blending. use crate::{ - animation::{ - machine::{Parameter, ParameterContainer, State}, - Animation, AnimationContainer, - }, core::{pool::Handle, reflect::prelude::*, visitor::prelude::*}, - utils::NameProvider, + machine::{Parameter, ParameterContainer, State}, + Animation, AnimationContainer, EntityId, }; -use fyrox_core::uuid_provider; +use fyrox_core::uuid::{uuid, Uuid}; +use fyrox_core::{NameProvider, TypeUuidProvider}; use std::any::{type_name, Any, TypeId}; use strum_macros::{AsRefStr, EnumString, EnumVariantNames}; @@ -16,14 +14,14 @@ macro_rules! define_two_args_node { ($(#[$meta:meta])* $name:ident) => { $(#[$meta])* #[derive(Debug, Clone, PartialEq)] - pub struct $name { + pub struct $name { /// Left argument. - pub lhs: Box, + pub lhs: Box>, /// Right argument. - pub rhs: Box, + pub rhs: Box>, } - impl Default for $name { + impl Default for $name { fn default() -> Self { Self { lhs: Box::new(LogicNode::Parameter(Default::default())), @@ -32,7 +30,7 @@ macro_rules! define_two_args_node { } } - impl Visit for $name { + impl Visit for $name { fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult { let mut guard = visitor.enter_region(name)?; @@ -43,7 +41,7 @@ macro_rules! define_two_args_node { } } - impl Reflect for $name { + impl Reflect for $name { fn type_name(&self) -> &'static str { type_name::() } @@ -162,12 +160,12 @@ define_two_args_node!( /// Calculates logical NOT of an argument. Output value will be `true` if the value of the argument is `false`. #[derive(Debug, Clone, PartialEq)] -pub struct NotNode { +pub struct NotNode { /// Argument to be negated. - pub lhs: Box, + pub lhs: Box>, } -impl Default for NotNode { +impl Default for NotNode { fn default() -> Self { Self { lhs: Box::new(LogicNode::Parameter(Default::default())), @@ -175,7 +173,7 @@ impl Default for NotNode { } } -impl Visit for NotNode { +impl Visit for NotNode { fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult { let mut guard = visitor.enter_region(name)?; @@ -185,7 +183,7 @@ impl Visit for NotNode { } } -impl Reflect for NotNode { +impl Reflect for NotNode { fn type_name(&self) -> &'static str { type_name::() } @@ -266,18 +264,19 @@ impl Reflect for NotNode { /// # Examples /// /// ```rust -/// use fyrox::animation::AnimationContainer; -/// use fyrox::animation::machine::{ +/// use fyrox_animation::AnimationContainer; +/// use fyrox_animation::machine::{ /// transition::{AndNode, LogicNode, NotNode}, /// Parameter, ParameterContainer, /// }; +/// use fyrox_core::pool::ErasedHandle; /// /// let mut parameters = ParameterContainer::default(); /// parameters.add("Run", Parameter::Rule(false)); /// parameters.add("Jump", Parameter::Rule(true)); /// /// // !Run && Jump -/// let transition_logic = LogicNode::And(AndNode { +/// let transition_logic = LogicNode::::And(AndNode { /// lhs: Box::new(LogicNode::Not(NotNode { /// lhs: Box::new(LogicNode::Parameter("Run".to_string())), /// })), @@ -287,35 +286,39 @@ impl Reflect for NotNode { /// assert_eq!(transition_logic.calculate_value(¶meters, &AnimationContainer::default()), true); /// ``` #[derive(Debug, Visit, Clone, Reflect, PartialEq, AsRefStr, EnumString, EnumVariantNames)] -pub enum LogicNode { +pub enum LogicNode { /// Fetches a value of `Rule` parameter and returns its value. `false` if the parameter is not found. Parameter(String), /// Calculates logical AND between two arguments. Output value will be `true` iff both of the arguments is `true`. - And(AndNode), + And(AndNode), /// Calculates logical OR between two arguments. Output value will be `true` iff any of the arguments is `true`. - Or(OrNode), + Or(OrNode), /// Calculates logical XOR (excluding OR) between two arguments. Output value will be `true` iff the arguments differ. - Xor(XorNode), + Xor(XorNode), /// Calculates logical NOT of an argument. Output value will be `true` if the value of the argument is `false`. - Not(NotNode), + Not(NotNode), /// Returns `true` if the animation has ended, `false` - otherwise. - IsAnimationEnded(Handle), + IsAnimationEnded(Handle>), } -uuid_provider!(LogicNode = "98a5b767-5560-4ed7-ad40-1625a8868e39"); +impl TypeUuidProvider for LogicNode { + fn type_uuid() -> Uuid { + uuid!("98a5b767-5560-4ed7-ad40-1625a8868e39") + } +} -impl Default for LogicNode { +impl Default for LogicNode { fn default() -> Self { Self::Parameter(Default::default()) } } -impl LogicNode { +impl LogicNode { /// Calculates final value of the logic node. pub fn calculate_value( &self, parameters: &ParameterContainer, - animations: &AnimationContainer, + animations: &AnimationContainer, ) -> bool { match self { LogicNode::Parameter(rule_name) => parameters.get(rule_name).map_or(false, |p| { @@ -350,7 +353,7 @@ impl LogicNode { /// Transition is a connection between two states with a rule that defines possibility of actual transition with blending. #[derive(Default, Debug, Clone, Reflect, PartialEq)] -pub struct Transition { +pub struct Transition { /// The name of the transition, it is used for debug output. #[reflect(description = "The name of the transition, it is used for debug output.")] pub(crate) name: String, @@ -363,21 +366,21 @@ pub struct Transition { pub(crate) elapsed_time: f32, #[reflect(read_only)] - pub(crate) source: Handle, + pub(crate) source: Handle>, #[reflect(read_only)] - pub(crate) dest: Handle, + pub(crate) dest: Handle>, #[reflect( description = "Computational graph that can use any amount of Rule parameters to calculate transition value." )] - pub(crate) condition: LogicNode, + pub(crate) condition: LogicNode, /// 0 - evaluates `src` pose, 1 - `dest`, 0..1 - blends `src` and `dest` pub(crate) blend_factor: f32, } -impl Visit for Transition { +impl Visit for Transition { fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult { let mut guard = visitor.enter_region(name)?; @@ -412,22 +415,22 @@ impl Visit for Transition { } } -impl NameProvider for Transition { +impl NameProvider for Transition { fn name(&self) -> &str { &self.name } } -impl Transition { +impl Transition { /// Creates a new named transition between two states with a given time and a name of a parameter that /// will be used to check if it is possible to activate the transition. pub fn new( name: &str, - src: Handle, - dest: Handle, + src: Handle>, + dest: Handle>, time: f32, rule: &str, - ) -> Transition { + ) -> Transition { Self { name: name.to_owned(), transition_time: time, @@ -453,23 +456,23 @@ impl Transition { /// Returns a handle to source state. #[inline] - pub fn source(&self) -> Handle { + pub fn source(&self) -> Handle> { self.source } /// Returns a handle to destination state. #[inline] - pub fn dest(&self) -> Handle { + pub fn dest(&self) -> Handle> { self.dest } /// Sets new condition for the transition. - pub fn set_condition(&mut self, condition: LogicNode) { + pub fn set_condition(&mut self, condition: LogicNode) { self.condition = condition; } /// Returns a reference to the current condition of the transition. - pub fn condition(&self) -> &LogicNode { + pub fn condition(&self) -> &LogicNode { &self.condition } diff --git a/src/animation/pose.rs b/fyrox-animation/src/pose.rs similarity index 51% rename from src/animation/pose.rs rename to fyrox-animation/src/pose.rs index 266162a18..243da4794 100644 --- a/src/animation/pose.rs +++ b/fyrox-animation/src/pose.rs @@ -1,54 +1,38 @@ //! Pose is a set of property values of a node ([`NodePose`]) or a set of nodes ([`AnimationPose`]). -use crate::{ - animation::{value::BoundValue, value::BoundValueCollection, RootMotion}, - core::{ - log::{Log, MessageKind}, - pool::Handle, - }, - scene::{graph::Graph, graph::NodePool, node::Node}, -}; +use crate::{value::BoundValue, value::BoundValueCollection, EntityId, RootMotion}; use fxhash::FxHashMap; use std::collections::hash_map::Entry; /// A "captured" state of properties of some animated scene node. The pose can be considered as container of values of some /// properties. -#[derive(Clone, Debug, PartialEq)] -pub struct NodePose { +#[derive(Clone, Debug, PartialEq, Default)] +pub struct NodePose { /// A handle of an animated node. - pub node: Handle, + pub node: T, /// A set of property values. pub values: BoundValueCollection, } -impl Default for NodePose { - fn default() -> Self { - Self { - node: Handle::NONE, - values: Default::default(), - } - } -} - -impl NodePose { +impl NodePose { /// Performs a blending of the current with some other pose. See [`super::value::TrackValue::blend_with`] docs for more /// info. - pub fn blend_with(&mut self, other: &NodePose, weight: f32) { + pub fn blend_with(&mut self, other: &NodePose, weight: f32) { self.values.blend_with(&other.values, weight) } } /// Animations pose is a set of node poses. See [`NodePose`] docs for more info. #[derive(Default, Debug, Clone, PartialEq)] -pub struct AnimationPose { - poses: FxHashMap, NodePose>, +pub struct AnimationPose { + poses: FxHashMap>, root_motion: Option, } -impl AnimationPose { +impl AnimationPose { /// Clears the set of node poses in the given animation pose and clones poses from the current animation pose to the given. - pub fn clone_into(&self, dest: &mut AnimationPose) { + pub fn clone_into(&self, dest: &mut AnimationPose) { dest.reset(); for (handle, local_pose) in self.poses.iter() { dest.poses.insert(*handle, local_pose.clone()); @@ -69,7 +53,7 @@ impl AnimationPose { /// Blends current animation pose with another using a weight coefficient. Missing node poses (from either animation poses) /// will become a simple copies of a respective node pose. - pub fn blend_with(&mut self, other: &AnimationPose, weight: f32) { + pub fn blend_with(&mut self, other: &AnimationPose, weight: f32) { for (handle, other_pose) in other.poses.iter() { if let Some(current_pose) = self.poses.get_mut(handle) { current_pose.blend_with(other_pose, weight); @@ -83,11 +67,11 @@ impl AnimationPose { .blend_with(&other.root_motion.clone().unwrap_or_default(), weight); } - fn add_node_pose(&mut self, local_pose: NodePose) { + fn add_node_pose(&mut self, local_pose: NodePose) { self.poses.insert(local_pose.node, local_pose); } - pub(super) fn add_to_node_pose(&mut self, node: Handle, bound_value: BoundValue) { + pub(super) fn add_to_node_pose(&mut self, node: T, bound_value: BoundValue) { match self.poses.entry(node) { Entry::Occupied(entry) => { entry.into_mut().values.values.push(bound_value); @@ -109,48 +93,12 @@ impl AnimationPose { } /// Returns a reference to inner node pose map. - pub fn poses(&self) -> &FxHashMap, NodePose> { + pub fn poses(&self) -> &FxHashMap> { &self.poses } /// Returns a reference to inner node pose map. - pub fn poses_mut(&mut self) -> &mut FxHashMap, NodePose> { + pub fn poses_mut(&mut self) -> &mut FxHashMap> { &mut self.poses } - - pub(crate) fn apply_internal(&self, nodes: &mut NodePool) { - for (node, local_pose) in self.poses.iter() { - if node.is_none() { - Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!"); - } else if let Some(node) = nodes.try_borrow_mut(*node) { - local_pose.values.apply(node); - } - } - } - - /// Tries to set each value to the each property from the animation pose to respective scene nodes. - pub fn apply(&self, graph: &mut Graph) { - for (node, local_pose) in self.poses.iter() { - if node.is_none() { - Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!"); - } else if let Some(node) = graph.try_get_mut(*node) { - local_pose.values.apply(node); - } - } - } - - /// Calls given callback function for each node and allows you to apply pose with your own - /// rules. This could be useful if you need to ignore transform some part of pose for a node. - pub fn apply_with(&self, graph: &mut Graph, mut callback: C) - where - C: FnMut(&mut Node, Handle, &NodePose), - { - for (node, local_pose) in self.poses.iter() { - if node.is_none() { - Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!"); - } else if let Some(node_ref) = graph.try_get_mut(*node) { - callback(node_ref, *node, local_pose); - } - } - } } diff --git a/src/animation/signal.rs b/fyrox-animation/src/signal.rs similarity index 95% rename from src/animation/signal.rs rename to fyrox-animation/src/signal.rs index 41a669f98..0b0923c42 100644 --- a/src/animation/signal.rs +++ b/fyrox-animation/src/signal.rs @@ -1,9 +1,7 @@ //! Signal is a named marker on specific time position on the animation timeline. See [`AnimationSignal`] docs for more info. -use crate::{ - core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*}, - utils::NameProvider, -}; +use crate::core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*}; +use fyrox_core::NameProvider; /// An event happened in an animation. #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/src/animation/spritesheet/mod.rs b/fyrox-animation/src/spritesheet/mod.rs similarity index 97% rename from src/animation/spritesheet/mod.rs rename to fyrox-animation/src/spritesheet/mod.rs index dd8360ad0..9677d4e99 100644 --- a/src/animation/spritesheet/mod.rs +++ b/fyrox-animation/src/spritesheet/mod.rs @@ -4,11 +4,11 @@ #![warn(missing_docs)] use crate::{ - animation::spritesheet::signal::Signal, core::{algebra::Vector2, math::Rect, reflect::prelude::*, visitor::prelude::*}, - resource::texture::TextureResource, + spritesheet::signal::Signal, }; use fyrox_core::uuid_provider; +use fyrox_resource::untyped::UntypedResource; use std::collections::vec_deque::VecDeque; use strum_macros::{AsRefStr, EnumString, EnumVariantNames}; @@ -58,7 +58,7 @@ pub struct SpriteSheetFramesContainer { size: Vector2, frames: Vec>, #[visit(optional)] - texture: Option, + texture: Option, } impl SpriteSheetFramesContainer { @@ -115,7 +115,7 @@ impl SpriteSheetFramesContainer { } /// Returns current texture of the container. To set a texture use sprite sheet animation methods. - pub fn texture(&self) -> Option { + pub fn texture(&self) -> Option { self.texture.clone() } } @@ -143,7 +143,7 @@ pub struct SpriteSheetAnimation { signals: Vec, #[visit(optional)] #[reflect(setter = "set_texture")] - texture: Option, + texture: Option, #[reflect(hidden)] #[visit(skip)] events: VecDeque, @@ -221,8 +221,8 @@ impl SpriteSheetAnimation { /// like this: /// /// ```rust - /// # use fyrox::{ - /// # animation::spritesheet::{ImageParameters, SpriteSheetAnimation}, + /// # use fyrox_animation::{ + /// # spritesheet::{ImageParameters, SpriteSheetAnimation}, /// # core::math::Rect, /// # }; /// fn extract_animations() { @@ -310,13 +310,13 @@ impl SpriteSheetAnimation { } /// Sets new texture for the animation. - pub fn set_texture(&mut self, texture: Option) -> Option { + pub fn set_texture(&mut self, texture: Option) -> Option { self.frames_container.texture = texture.clone(); std::mem::replace(&mut self.texture, texture) } /// Returns current texture of the animation. - pub fn texture(&self) -> Option { + pub fn texture(&self) -> Option { self.texture.clone() } @@ -510,7 +510,7 @@ impl SpriteSheetAnimation { #[cfg(test)] mod test { - use crate::animation::spritesheet::{ + use crate::spritesheet::{ signal::Signal, Event, ImageParameters, SpriteSheetAnimation, Status, }; use fyrox_core::algebra::Vector2; diff --git a/src/animation/spritesheet/signal.rs b/fyrox-animation/src/spritesheet/signal.rs similarity index 100% rename from src/animation/spritesheet/signal.rs rename to fyrox-animation/src/spritesheet/signal.rs diff --git a/src/animation/track.rs b/fyrox-animation/src/track.rs similarity index 90% rename from src/animation/track.rs rename to fyrox-animation/src/track.rs index 62648401c..6d7d160b0 100644 --- a/src/animation/track.rs +++ b/fyrox-animation/src/track.rs @@ -1,12 +1,10 @@ //! Track is responsible in animating a property of a single scene node. See [`Track`] docs for more info. use crate::{ - animation::{ - container::{TrackDataContainer, TrackValueKind}, - value::{BoundValue, ValueBinding}, - }, - core::{pool::Handle, reflect::prelude::*, uuid::Uuid, visitor::prelude::*}, - scene::node::Node, + container::{TrackDataContainer, TrackValueKind}, + core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*}, + value::{BoundValue, ValueBinding}, + EntityId, }; use std::fmt::Debug; @@ -14,15 +12,15 @@ use std::fmt::Debug; /// that contains the actual property data. Parametric curves allows the engine to perform various interpolations between /// key values. #[derive(Debug, Reflect, Clone, PartialEq)] -pub struct Track { +pub struct Track { binding: ValueBinding, frames: TrackDataContainer, enabled: bool, - target: Handle, + target: T, id: Uuid, } -impl Visit for Track { +impl Visit for Track { fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult { let mut region = visitor.enter_region(name)?; @@ -37,7 +35,7 @@ impl Visit for Track { } } -impl Default for Track { +impl Default for Track { fn default() -> Self { Self { binding: ValueBinding::Position, @@ -49,7 +47,7 @@ impl Default for Track { } } -impl Track { +impl Track { /// Creates a new track that will animate a property in the given binding. The `container` must have enough parametric /// curves to be able to produces property values. pub fn new(container: TrackDataContainer, binding: ValueBinding) -> Self { @@ -88,7 +86,7 @@ impl Track { } /// Sets target of the track. - pub fn with_target(mut self, target: Handle) -> Self { + pub fn with_target(mut self, target: T) -> Self { self.target = target; self } @@ -104,12 +102,12 @@ impl Track { } /// Sets a handle of a node that will be animated. - pub fn set_target(&mut self, target: Handle) { + pub fn set_target(&mut self, target: T) { self.target = target; } /// Returns a handle of a node that will be animated. - pub fn target(&self) -> Handle { + pub fn target(&self) -> T { self.target } diff --git a/src/animation/value.rs b/fyrox-animation/src/value.rs similarity index 77% rename from src/animation/value.rs rename to fyrox-animation/src/value.rs index 6ced615ae..d0c4de915 100644 --- a/src/animation/value.rs +++ b/fyrox-animation/src/value.rs @@ -1,16 +1,12 @@ //! A module that contains everything related to numeric values of animation tracks. See [`TrackValue`] docs //! for more info. -use crate::{ - core::{ - algebra::{UnitQuaternion, Vector2, Vector3, Vector4}, - log::Log, - math::lerpf, - num_traits::AsPrimitive, - reflect::{prelude::*, SetFieldByPathError}, - visitor::prelude::*, - }, - scene::node::Node, +use crate::core::{ + algebra::{UnitQuaternion, Vector2, Vector3, Vector4}, + math::lerpf, + num_traits::AsPrimitive, + reflect::prelude::*, + visitor::prelude::*, }; use std::fmt::{Debug, Display, Formatter}; @@ -327,67 +323,4 @@ impl BoundValueCollection { } } } - - /// Tries to set each value from the collection to the respective property (by binding) of the given scene node. - pub fn apply(&self, node_ref: &mut Node) { - for bound_value in self.values.iter() { - match bound_value.binding { - ValueBinding::Position => { - if let TrackValue::Vector3(v) = bound_value.value { - node_ref.local_transform_mut().set_position(v); - } else { - Log::err( - "Unable to apply position, because underlying type is not Vector3!", - ) - } - } - ValueBinding::Scale => { - if let TrackValue::Vector3(v) = bound_value.value { - node_ref.local_transform_mut().set_scale(v); - } else { - Log::err("Unable to apply scaling, because underlying type is not Vector3!") - } - } - ValueBinding::Rotation => { - if let TrackValue::UnitQuaternion(v) = bound_value.value { - node_ref.local_transform_mut().set_rotation(v); - } else { - Log::err("Unable to apply rotation, because underlying type is not UnitQuaternion!") - } - } - ValueBinding::Property { - name: ref property_name, - value_type, - } => { - if let Some(casted) = bound_value.value.numeric_type_cast(value_type) { - let mut casted = Some(casted); - node_ref.as_reflect_mut(&mut |node_ref| { - node_ref.set_field_by_path( - property_name, - casted.take().unwrap(), - &mut |result| { - if let Err(err) = result { - match err { - SetFieldByPathError::InvalidPath { reason, .. } => { - Log::err(format!( - "Failed to set property {}! Invalid path: {}", - property_name, reason - )); - } - SetFieldByPathError::InvalidValue(_) => { - Log::err(format!( - "Failed to set property {}! Types mismatch!", - property_name - )); - } - } - } - }, - ) - }) - } - } - } - } - } } diff --git a/fyrox-core/src/lib.rs b/fyrox-core/src/lib.rs index 561dc134c..6642bbc4b 100644 --- a/fyrox-core/src/lib.rs +++ b/fyrox-core/src/lib.rs @@ -306,8 +306,8 @@ pub trait TypeUuidProvider: Sized { #[macro_export] macro_rules! uuid_provider { - ($type:ty = $uuid:expr) => { - impl $crate::TypeUuidProvider for $type { + ($type:ident $(<$($generics:tt),*>)? = $uuid:expr) => { + impl$(<$($generics),*>)? $crate::TypeUuidProvider for $type $(<$($generics),*>)? { fn type_uuid() -> $crate::uuid::Uuid { $crate::uuid::uuid!($uuid) } @@ -455,6 +455,32 @@ impl Default for PhantomDataSendSync { } } +/// A trait for entities that have name. +pub trait NameProvider { + /// Returns a reference to the name of the entity. + fn name(&self) -> &str; +} + +/// Tries to find an entity by its name in a series of entities produced by an iterator. +pub fn find_by_name_ref<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a T)> +where + T: NameProvider, + I: Iterator, + S: AsRef, +{ + iter.find(|(_, value)| value.name() == name.as_ref()) +} + +/// Tries to find an entity by its name in a series of entities produced by an iterator. +pub fn find_by_name_mut<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a mut T)> +where + T: NameProvider, + I: Iterator, + S: AsRef, +{ + iter.find(|(_, value)| value.name() == name.as_ref()) +} + #[cfg(test)] mod test { use std::path::Path; diff --git a/fyrox-core/src/pool.rs b/fyrox-core/src/pool.rs index ebb7bc1c3..b7e78e123 100644 --- a/fyrox-core/src/pool.rs +++ b/fyrox-core/src/pool.rs @@ -33,6 +33,7 @@ use crate::{ use arrayvec::ArrayVec; use serde::{Deserialize, Serialize}; use std::any::Any; +use std::cmp::Ordering; use std::{ fmt::{Debug, Display, Formatter}, future::Future, @@ -215,6 +216,18 @@ impl TypeUuidProvider for Handle { } } +impl PartialOrd for Handle { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Handle { + fn cmp(&self, other: &Self) -> Ordering { + self.index.cmp(&other.index) + } +} + unsafe impl Send for Handle {} unsafe impl Sync for Handle {} diff --git a/src/lib.rs b/src/lib.rs index 8ba3f2a60..38c021295 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ #![allow(clippy::from_over_into)] #![allow(clippy::approx_constant)] -pub mod animation; +pub use fyrox_animation as animation; pub mod engine; pub mod material; pub mod plugin; diff --git a/src/resource/fbx/mod.rs b/src/resource/fbx/mod.rs index 0948448bb..9c5c27433 100644 --- a/src/resource/fbx/mod.rs +++ b/src/resource/fbx/mod.rs @@ -638,7 +638,7 @@ async fn convert_model( model: &FbxModel, resource_manager: ResourceManager, graph: &mut Graph, - animation: &mut Animation, + animation: &mut Animation>, model_path: &Path, model_import_options: &ModelImportOptions, ) -> Result, FbxError> { @@ -682,7 +682,7 @@ async fn convert_model( } fn fill_track f32>( - track: &mut Track, + track: &mut Track>, fbx_scene: &FbxScene, fbx_track: &FbxAnimationCurveNode, default: Vector3, @@ -730,7 +730,7 @@ async fn convert_model( } } - fn add_vec3_key(track: &mut Track, value: Vector3) { + fn add_vec3_key(track: &mut Track>, value: Vector3) { let curves = track.data_container_mut().curves_mut(); curves[0].add_key(CurveKey::new(0.0, value.x, CurveKeyKind::Constant)); curves[1].add_key(CurveKey::new(0.0, value.y, CurveKeyKind::Constant)); diff --git a/src/resource/model/mod.rs b/src/resource/model/mod.rs index 899058098..01c137487 100644 --- a/src/resource/model/mod.rs +++ b/src/resource/model/mod.rs @@ -123,7 +123,11 @@ pub trait ModelResourceExtension: Sized { /// /// Most of the 3d model formats can contain only one animation, so in most cases /// this function will return vector with only one animation. - fn retarget_animations_directly(&self, root: Handle, graph: &Graph) -> Vec; + fn retarget_animations_directly( + &self, + root: Handle, + graph: &Graph, + ) -> Vec>>; /// Tries to retarget animations from given model resource to a node hierarchy starting /// from `root` on a given scene. Unlike [`Self::retarget_animations_directly`], it automatically @@ -138,7 +142,7 @@ pub trait ModelResourceExtension: Sized { root: Handle, dest_animation_player: Handle, graph: &mut Graph, - ) -> Vec>; + ) -> Vec>>>; /// Tries to retarget animations from given model resource to a node hierarchy starting /// from `root` on a given scene. Unlike [`Self::retarget_animations_directly`], it automatically @@ -147,7 +151,11 @@ pub trait ModelResourceExtension: Sized { /// # Panic /// /// Panics if there's no animation player in the given hierarchy (descendant nodes of `root`). - fn retarget_animations(&self, root: Handle, graph: &mut Graph) -> Vec>; + fn retarget_animations( + &self, + root: Handle, + graph: &mut Graph, + ) -> Vec>>>; } impl ModelResourceExtension for ModelResource { @@ -208,7 +216,11 @@ impl ModelResourceExtension for ModelResource { root } - fn retarget_animations_directly(&self, root: Handle, graph: &Graph) -> Vec { + fn retarget_animations_directly( + &self, + root: Handle, + graph: &Graph, + ) -> Vec>> { let mut retargetted_animations = Vec::new(); let mut header = self.state(); @@ -232,7 +244,7 @@ impl ModelResourceExtension for ModelResource { track.set_target(instance_node); } None => { - track.set_target(Handle::NONE); + track.set_target(Default::default()); Log::writeln( MessageKind::Error, format!( @@ -259,7 +271,7 @@ impl ModelResourceExtension for ModelResource { root: Handle, dest_animation_player: Handle, graph: &mut Graph, - ) -> Vec> { + ) -> Vec>>> { let mut animation_handles = Vec::new(); let animations = self.retarget_animations_directly(root, graph); @@ -275,7 +287,11 @@ impl ModelResourceExtension for ModelResource { animation_handles } - fn retarget_animations(&self, root: Handle, graph: &mut Graph) -> Vec> { + fn retarget_animations( + &self, + root: Handle, + graph: &mut Graph, + ) -> Vec>>> { if let Some((animation_player, _)) = graph.find(root, &mut |n| { n.query_component_ref::().is_some() }) { diff --git a/src/scene/animation/absm.rs b/src/scene/animation/absm.rs index d7675105f..5b369b41b 100644 --- a/src/scene/animation/absm.rs +++ b/src/scene/animation/absm.rs @@ -13,7 +13,7 @@ use crate::{ TypeUuidProvider, }, scene::{ - animation::AnimationPlayer, + animation::{AnimationPlayer, AnimationPoseExt}, base::{Base, BaseBuilder}, graph::Graph, node::{Node, NodeTrait, UpdateContext}, @@ -106,23 +106,23 @@ use std::ops::{Deref, DerefMut}; #[derive(Visit, Reflect, Clone, Debug, Default)] pub struct AnimationBlendingStateMachine { base: Base, - machine: InheritableVariable, + machine: InheritableVariable>>, animation_player: InheritableVariable>, } impl AnimationBlendingStateMachine { /// Sets new state machine to the node. - pub fn set_machine(&mut self, machine: Machine) { + pub fn set_machine(&mut self, machine: Machine>) { self.machine.set_value_and_mark_modified(machine); } /// Returns a reference to the state machine used by the node. - pub fn machine(&self) -> &InheritableVariable { + pub fn machine(&self) -> &InheritableVariable>> { &self.machine } /// Returns a mutable reference to the state machine used by the node. - pub fn machine_mut(&mut self) -> &mut InheritableVariable { + pub fn machine_mut(&mut self) -> &mut InheritableVariable>> { &mut self.machine } @@ -214,7 +214,7 @@ impl NodeTrait for AnimationBlendingStateMachine { /// Animation blending state machine builder allows you to create state machines in declarative manner. pub struct AnimationBlendingStateMachineBuilder { base_builder: BaseBuilder, - machine: Machine, + machine: Machine>, animation_player: Handle, } @@ -229,7 +229,7 @@ impl AnimationBlendingStateMachineBuilder { } /// Sets the desired state machine. - pub fn with_machine(mut self, machine: Machine) -> Self { + pub fn with_machine(mut self, machine: Machine>) -> Self { self.machine = machine; self } diff --git a/src/scene/animation/mod.rs b/src/scene/animation/mod.rs index 5f77e0199..bb1ea1902 100644 --- a/src/scene/animation/mod.rs +++ b/src/scene/animation/mod.rs @@ -2,8 +2,12 @@ //! See [`AnimationPlayer`] docs for more info. use crate::{ - animation::AnimationContainer, + animation::{ + value::{BoundValueCollection, TrackValue, ValueBinding}, + AnimationContainer, AnimationPose, NodePose, + }, core::{ + log::{Log, MessageKind}, math::aabb::AxisAlignedBoundingBox, pool::Handle, reflect::prelude::*, @@ -14,14 +18,168 @@ use crate::{ }, scene::{ base::{Base, BaseBuilder}, - graph::Graph, + graph::{Graph, NodePool}, node::{Node, NodeTrait, UpdateContext}, }, }; +use fyrox_animation::machine::LayerMask; +use fyrox_core::pool::ErasedHandle; use std::ops::{Deref, DerefMut}; pub mod absm; +/// Extension trait for [`AnimationContainer`]. +pub trait AnimationContainerExt { + /// Updates all animations in the container and applies their poses to respective nodes. This method is intended to + /// be used only by the internals of the engine! + fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32); +} + +impl AnimationContainerExt for AnimationContainer> { + fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32) { + for animation in self.iter_mut().filter(|anim| anim.is_enabled()) { + animation.tick(dt); + if apply { + animation.pose().apply_internal(nodes); + } + } + } +} + +/// Extension trait for [`AnimationPose`]. +pub trait AnimationPoseExt { + /// Tries to set each value to the each property from the animation pose to respective scene nodes. + fn apply_internal(&self, nodes: &mut NodePool); + + /// Tries to set each value to the each property from the animation pose to respective scene nodes. + fn apply(&self, graph: &mut Graph); + + /// Calls given callback function for each node and allows you to apply pose with your own + /// rules. This could be useful if you need to ignore transform some part of pose for a node. + fn apply_with(&self, graph: &mut Graph, callback: C) + where + C: FnMut(&mut Node, Handle, &NodePose>); +} + +impl AnimationPoseExt for AnimationPose> { + fn apply_internal(&self, nodes: &mut NodePool) { + for (node, local_pose) in self.poses() { + if node.is_none() { + Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!"); + } else if let Some(node) = nodes.try_borrow_mut(*node) { + local_pose.values.apply(node); + } + } + } + + fn apply(&self, graph: &mut Graph) { + for (node, local_pose) in self.poses() { + if node.is_none() { + Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!"); + } else if let Some(node) = graph.try_get_mut(*node) { + local_pose.values.apply(node); + } + } + } + + fn apply_with(&self, graph: &mut Graph, mut callback: C) + where + C: FnMut(&mut Node, Handle, &NodePose>), + { + for (node, local_pose) in self.poses() { + if node.is_none() { + Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!"); + } else if let Some(node_ref) = graph.try_get_mut(*node) { + callback(node_ref, *node, local_pose); + } + } + } +} + +/// Extension trait for [`BoundValueCollection`]. +pub trait BoundValueCollectionExt { + /// Tries to set each value from the collection to the respective property (by binding) of the given scene node. + fn apply(&self, node_ref: &mut Node); +} + +impl BoundValueCollectionExt for BoundValueCollection { + fn apply(&self, node_ref: &mut Node) { + for bound_value in self.values.iter() { + match bound_value.binding { + ValueBinding::Position => { + if let TrackValue::Vector3(v) = bound_value.value { + node_ref.local_transform_mut().set_position(v); + } else { + Log::err( + "Unable to apply position, because underlying type is not Vector3!", + ) + } + } + ValueBinding::Scale => { + if let TrackValue::Vector3(v) = bound_value.value { + node_ref.local_transform_mut().set_scale(v); + } else { + Log::err("Unable to apply scaling, because underlying type is not Vector3!") + } + } + ValueBinding::Rotation => { + if let TrackValue::UnitQuaternion(v) = bound_value.value { + node_ref.local_transform_mut().set_rotation(v); + } else { + Log::err("Unable to apply rotation, because underlying type is not UnitQuaternion!") + } + } + ValueBinding::Property { + name: ref property_name, + value_type, + } => { + if let Some(casted) = bound_value.value.numeric_type_cast(value_type) { + let mut casted = Some(casted); + node_ref.as_reflect_mut(&mut |node_ref| { + node_ref.set_field_by_path( + property_name, + casted.take().unwrap(), + &mut |result| { + if let Err(err) = result { + match err { + SetFieldByPathError::InvalidPath { reason, .. } => { + Log::err(format!( + "Failed to set property {}! Invalid path: {}", + property_name, reason + )); + } + SetFieldByPathError::InvalidValue(_) => { + Log::err(format!( + "Failed to set property {}! Types mismatch!", + property_name + )); + } + } + } + }, + ) + }) + } + } + } + } + } +} + +/// Extension trait for [`LayerMask`]. +pub trait LayerMaskExt { + /// Creates a layer mask for every descendant node starting from specified `root` (included). It could + /// be useful if you have an entire node hierarchy (for example, lower part of a body) that needs to + /// be filtered out. + fn from_hierarchy(graph: &Graph, root: ErasedHandle) -> Self; +} + +impl LayerMaskExt for LayerMask> { + fn from_hierarchy(graph: &Graph, root: ErasedHandle) -> Self { + Self::from(graph.traverse_handle_iter(root.into()).collect::>()) + } +} + /// Animation player is a node that contains multiple animations. It updates and plays all the animations. /// The node could be a source of animations for animation blending state machines. To learn more about /// animations, see [`crate::animation::Animation`] docs. @@ -47,7 +205,7 @@ pub mod absm; /// scene::{animation::AnimationPlayerBuilder, base::BaseBuilder, graph::Graph, node::Node}, /// }; /// -/// fn create_bounce_animation(animated_node: Handle) -> Animation { +/// fn create_bounce_animation(animated_node: Handle) -> Animation> { /// let mut frames_container = TrackDataContainer::new(TrackValueKind::Vector3); /// /// // We'll animate only Y coordinate (at index 1). @@ -94,7 +252,7 @@ pub mod absm; #[derive(Visit, Reflect, Clone, Debug)] pub struct AnimationPlayer { base: Base, - animations: InheritableVariable, + animations: InheritableVariable>>, auto_apply: bool, } @@ -124,18 +282,18 @@ impl AnimationPlayer { } /// Returns a reference to internal animations container. - pub fn animations(&self) -> &InheritableVariable { + pub fn animations(&self) -> &InheritableVariable>> { &self.animations } /// Returns a reference to internal animations container. Keep in mind that mutable access to [`InheritableVariable`] /// may have side effects if used inappropriately. Checks docs for [`InheritableVariable`] for more info. - pub fn animations_mut(&mut self) -> &mut InheritableVariable { + pub fn animations_mut(&mut self) -> &mut InheritableVariable>> { &mut self.animations } /// Sets new animations container of the animation player. - pub fn set_animations(&mut self, animations: AnimationContainer) { + pub fn set_animations(&mut self, animations: AnimationContainer>) { self.animations.set_value_and_mark_modified(animations); } } @@ -187,7 +345,7 @@ impl NodeTrait for AnimationPlayer { /// A builder for [`AnimationPlayer`] node. pub struct AnimationPlayerBuilder { base_builder: BaseBuilder, - animations: AnimationContainer, + animations: AnimationContainer>, auto_apply: bool, } @@ -202,7 +360,7 @@ impl AnimationPlayerBuilder { } /// Sets a container with desired animations. - pub fn with_animations(mut self, animations: AnimationContainer) -> Self { + pub fn with_animations(mut self, animations: AnimationContainer>) -> Self { self.animations = animations; self } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 629fa3fa1..5d3f1f160 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -782,32 +782,6 @@ pub fn into_any_arc( } } -/// A trait for entities that have name. -pub trait NameProvider { - /// Returns a reference to the name of the entity. - fn name(&self) -> &str; -} - -/// Tries to find an entity by its name in a series of entities produced by an iterator. -pub fn find_by_name_ref<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a T)> -where - T: NameProvider, - I: Iterator, - S: AsRef, -{ - iter.find(|(_, value)| value.name() == name.as_ref()) -} - -/// Tries to find an entity by its name in a series of entities produced by an iterator. -pub fn find_by_name_mut<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a mut T)> -where - T: NameProvider, - I: Iterator, - S: AsRef, -{ - iter.find(|(_, value)| value.name() == name.as_ref()) -} - /// Converts `Vector3` -> `Vector3`. pub fn vec3_f16_from_f32(v: Vector3) -> Vector3 { v.map(f16::from_f32) diff --git a/src/utils/navmesh.rs b/src/utils/navmesh.rs index a472e4030..bacc089e2 100644 --- a/src/utils/navmesh.rs +++ b/src/utils/navmesh.rs @@ -965,7 +965,7 @@ mod test { #[test] fn test_navmesh() { - let mut navmesh = Navmesh::new( + let navmesh = Navmesh::new( vec![ TriangleDefinition([0, 1, 3]), TriangleDefinition([1, 2, 3]), @@ -989,7 +989,7 @@ mod test { let mut agent = NavmeshAgent::new(); agent.set_target(Vector3::new(3.0, 0.0, 1.0)); - agent.update(1.0 / 60.0, &mut navmesh).unwrap(); + agent.update(1.0 / 60.0, &navmesh).unwrap(); let graph = &navmesh.graph;