mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
use abstract EntityId instead of ErasedHandle in animation entities
This commit is contained in:
@@ -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<Handle<Node>>,
|
||||
selection: &AbsmSelection,
|
||||
ui: &mut UserInterface,
|
||||
) {
|
||||
@@ -893,7 +894,7 @@ impl BlendSpaceEditor {
|
||||
selection: &AbsmSelection,
|
||||
message: &UiMessage,
|
||||
sender: &MessageSender,
|
||||
machine: &mut Machine,
|
||||
machine: &mut Machine<Handle<Node>>,
|
||||
is_preview_mode_active: bool,
|
||||
) {
|
||||
if let Some(SelectedEntity::PoseNode(first)) = selection.entities.first() {
|
||||
|
||||
@@ -13,7 +13,7 @@ use fyrox::{
|
||||
scene::node::Node,
|
||||
};
|
||||
|
||||
define_push_element_to_collection_command!(AddInputCommand<Handle<PoseNode>, IndexedBlendInput>(self, context) {
|
||||
define_push_element_to_collection_command!(AddInputCommand<Handle<PoseNode<Handle<Node>>>, IndexedBlendInput<Handle<Node>>>(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<Handle<PoseNode>, Ind
|
||||
}
|
||||
});
|
||||
|
||||
define_push_element_to_collection_command!(AddPoseSourceCommand<Handle<PoseNode>, BlendPose>(self, context) {
|
||||
define_push_element_to_collection_command!(AddPoseSourceCommand<Handle<PoseNode<Handle<Node>>>, BlendPose<Handle<Node>>>(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<Handle<PoseNode>
|
||||
}
|
||||
});
|
||||
|
||||
define_push_element_to_collection_command!(AddBlendSpacePointCommand<Handle<PoseNode>, BlendSpacePoint>(self, context) {
|
||||
define_push_element_to_collection_command!(AddBlendSpacePointCommand<Handle<PoseNode<Handle<Node>>>, BlendSpacePoint<Handle<Node>>>(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<Pose
|
||||
});
|
||||
|
||||
define_set_collection_element_command!(
|
||||
SetBlendAnimationByIndexInputPoseSourceCommand<Handle<PoseNode>, Handle<PoseNode>>(self, context) {
|
||||
SetBlendAnimationByIndexInputPoseSourceCommand<Handle<PoseNode<Handle<Node>>>, Handle<PoseNode<Handle<Node>>>>(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<PoseNode>, Handle<PoseNode>>(self, context) {
|
||||
SetBlendAnimationsPoseSourceCommand<Handle<PoseNode<Handle<Node>>>, Handle<PoseNode<Handle<Node>>>>(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<PoseNode>, Handle<PoseNode>>(self, context) {
|
||||
SetBlendSpacePoseSourceCommand<Handle<PoseNode<Handle<Node>>>, Handle<PoseNode<Handle<Node>>>>(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<Handle<PoseNode>, Vector2<f32>>(self, context) {
|
||||
SetBlendSpacePointPositionCommand<Handle<PoseNode<Handle<Node>>>, Vector2<f32>>(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<Node>,
|
||||
pub layer_index: usize,
|
||||
pub node_handle: Handle<PoseNode>,
|
||||
pub node_handle: Handle<PoseNode<Handle<Node>>>,
|
||||
pub point_index: usize,
|
||||
pub point: Option<BlendSpacePoint>,
|
||||
pub point: Option<BlendSpacePoint<Handle<Node>>>,
|
||||
}
|
||||
|
||||
impl GameSceneCommandTrait for RemoveBlendSpacePointCommand {
|
||||
|
||||
@@ -126,7 +126,11 @@ macro_rules! define_spawn_command {
|
||||
};
|
||||
}
|
||||
|
||||
define_spawn_command!(AddTransitionCommand, Transition, transitions_mut);
|
||||
define_spawn_command!(
|
||||
AddTransitionCommand,
|
||||
Transition<Handle<Node>>,
|
||||
transitions_mut
|
||||
);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AddStateCommand {
|
||||
@@ -134,24 +138,24 @@ pub enum AddStateCommand {
|
||||
NonExecuted {
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
state: State,
|
||||
state: State<Handle<Node>>,
|
||||
},
|
||||
Executed {
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
handle: Handle<State>,
|
||||
prev_entry_state: Handle<State>,
|
||||
handle: Handle<State<Handle<Node>>>,
|
||||
prev_entry_state: Handle<State<Handle<Node>>>,
|
||||
},
|
||||
Reverted {
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
ticket: Ticket<State>,
|
||||
state: State,
|
||||
ticket: Ticket<State<Handle<Node>>>,
|
||||
state: State<Handle<Node>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl AddStateCommand {
|
||||
pub fn new(node_handle: Handle<Node>, layer_index: usize, state: State) -> Self {
|
||||
pub fn new(node_handle: Handle<Node>, layer_index: usize, state: State<Handle<Node>>) -> Self {
|
||||
Self::NonExecuted {
|
||||
node_handle,
|
||||
layer_index,
|
||||
@@ -163,7 +167,7 @@ impl AddStateCommand {
|
||||
fn fetch_machine<'a>(
|
||||
context: &'a mut GameSceneContext,
|
||||
node_handle: Handle<Node>,
|
||||
) -> &'a mut Machine {
|
||||
) -> &'a mut Machine<Handle<Node>> {
|
||||
context.scene.graph[node_handle]
|
||||
.query_component_mut::<AnimationBlendingStateMachine>()
|
||||
.unwrap()
|
||||
@@ -279,24 +283,28 @@ pub enum AddPoseNodeCommand {
|
||||
NonExecuted {
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
node: PoseNode,
|
||||
node: PoseNode<Handle<Node>>,
|
||||
},
|
||||
Executed {
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
handle: Handle<PoseNode>,
|
||||
prev_root_node: Handle<PoseNode>,
|
||||
handle: Handle<PoseNode<Handle<Node>>>,
|
||||
prev_root_node: Handle<PoseNode<Handle<Node>>>,
|
||||
},
|
||||
Reverted {
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
ticket: Ticket<PoseNode>,
|
||||
node: PoseNode,
|
||||
ticket: Ticket<PoseNode<Handle<Node>>>,
|
||||
node: PoseNode<Handle<Node>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl AddPoseNodeCommand {
|
||||
pub fn new(node_handle: Handle<Node>, layer_index: usize, node: PoseNode) -> Self {
|
||||
pub fn new(
|
||||
node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
node: PoseNode<Handle<Node>>,
|
||||
) -> 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<Handle<Node>>, states_mut);
|
||||
define_move_command!(MovePoseNodeCommand, PoseNode<Handle<Node>>, 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<Handle<Node>>, states_mut);
|
||||
define_free_command!(DeletePoseNodeCommand, PoseNode<Handle<Node>>, nodes_mut);
|
||||
define_free_command!(
|
||||
DeleteTransitionCommand,
|
||||
Transition<Handle<Node>>,
|
||||
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<Node>,
|
||||
pub layer: usize,
|
||||
pub entry: Handle<State>,
|
||||
pub entry: Handle<State<Handle<Node>>>,
|
||||
}
|
||||
|
||||
impl SetMachineEntryStateCommand {
|
||||
@@ -765,7 +777,7 @@ macro_rules! define_absm_swap_command {
|
||||
};
|
||||
}
|
||||
|
||||
define_absm_swap_command!(SetStateRootPoseCommand<Handle<State>, Handle<PoseNode>>[layer_index: usize](self, context) {
|
||||
define_absm_swap_command!(SetStateRootPoseCommand<Handle<State<Handle<Node>>>, Handle<PoseNode<Handle<Node>>>>[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<Node>,
|
||||
pub layer: Option<MachineLayer>,
|
||||
pub layer: Option<MachineLayer<Handle<Node>>>,
|
||||
}
|
||||
|
||||
impl GameSceneCommandTrait for AddLayerCommand {
|
||||
@@ -825,7 +837,7 @@ impl GameSceneCommandTrait for AddLayerCommand {
|
||||
pub struct RemoveLayerCommand {
|
||||
pub absm_node_handle: Handle<Node>,
|
||||
pub layer_index: usize,
|
||||
pub layer: Option<MachineLayer>,
|
||||
pub layer: Option<MachineLayer<Handle<Node>>>,
|
||||
}
|
||||
|
||||
impl RemoveLayerCommand {
|
||||
@@ -858,7 +870,7 @@ impl GameSceneCommandTrait for RemoveLayerCommand {
|
||||
pub struct SetLayerMaskCommand {
|
||||
pub absm_node_handle: Handle<Node>,
|
||||
pub layer_index: usize,
|
||||
pub mask: LayerMask,
|
||||
pub mask: LayerMask<Handle<Node>>,
|
||||
}
|
||||
|
||||
impl SetLayerMaskCommand {
|
||||
|
||||
@@ -15,7 +15,7 @@ define_universal_commands! {
|
||||
GameSceneCommandTrait,
|
||||
GameSceneCommand,
|
||||
GameSceneContext,
|
||||
Handle<PoseNode>,
|
||||
Handle<PoseNode<Handle<Node>>>,
|
||||
ctx,
|
||||
handle,
|
||||
self,
|
||||
|
||||
@@ -15,7 +15,7 @@ define_universal_commands!(
|
||||
GameSceneCommandTrait,
|
||||
GameSceneCommand,
|
||||
GameSceneContext,
|
||||
Handle<State>,
|
||||
Handle<State<Handle<Node>>>,
|
||||
ctx,
|
||||
handle,
|
||||
self,
|
||||
|
||||
@@ -15,7 +15,7 @@ define_universal_commands!(
|
||||
GameSceneCommandTrait,
|
||||
GameSceneCommand,
|
||||
GameSceneContext,
|
||||
Handle<Transition>,
|
||||
Handle<Transition<Handle<Node>>>,
|
||||
ctx,
|
||||
handle,
|
||||
self,
|
||||
|
||||
@@ -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<Handle<Node>>,
|
||||
nodes: Vec<(Handle<Node>, Node)>,
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ impl AbsmEditor {
|
||||
|
||||
fn enter_preview_mode(
|
||||
&mut self,
|
||||
machine: Machine,
|
||||
machine: Machine<Handle<Node>>,
|
||||
animation_targets: FxHashSet<Handle<Node>>,
|
||||
scene: &Scene,
|
||||
ui: &UserInterface,
|
||||
@@ -525,7 +525,7 @@ impl AbsmEditor {
|
||||
AbsmNodeMessage::Enter => {
|
||||
if let Some(node) = ui
|
||||
.node(message.destination())
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
{
|
||||
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::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
{
|
||||
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::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
{
|
||||
if let Some(layer_index) = selection.layer {
|
||||
let model_ref = &absm_node.machine().layers()[layer_index].nodes()
|
||||
|
||||
@@ -6,9 +6,9 @@ use fyrox::{
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
pub enum SelectedEntity {
|
||||
Transition(Handle<Transition>),
|
||||
State(Handle<State>),
|
||||
PoseNode(Handle<PoseNode>),
|
||||
Transition(Handle<Transition<Handle<Node>>>),
|
||||
State(Handle<State<Handle<Node>>>),
|
||||
PoseNode(Handle<PoseNode<Handle<Node>>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
|
||||
@@ -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<Vector2<f32>>,
|
||||
pub parent_node: Handle<PoseNode>,
|
||||
pub parent_node: Handle<PoseNode<Handle<Node>>>,
|
||||
pub direction: SocketDirection,
|
||||
#[allow(dead_code)] // TODO
|
||||
editor: Handle<UiNode>,
|
||||
@@ -124,7 +125,7 @@ impl Control for Socket {
|
||||
|
||||
pub struct SocketBuilder {
|
||||
widget_builder: WidgetBuilder,
|
||||
parent_node: Handle<PoseNode>,
|
||||
parent_node: Handle<PoseNode<Handle<Node>>>,
|
||||
direction: SocketDirection,
|
||||
editor: Handle<UiNode>,
|
||||
index: usize,
|
||||
@@ -143,7 +144,7 @@ impl SocketBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_parent_node(mut self, parent_node: Handle<PoseNode>) -> Self {
|
||||
pub fn with_parent_node(mut self, parent_node: Handle<PoseNode<Handle<Node>>>) -> Self {
|
||||
self.parent_node = parent_node;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ impl NodeContextMenu {
|
||||
layer: layer_index,
|
||||
entry: ui
|
||||
.node(self.placement_target)
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle,
|
||||
});
|
||||
@@ -296,7 +296,7 @@ impl NodeContextMenu {
|
||||
.children()
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|c| ui.node(*c).has_component::<AbsmNode<State>>())
|
||||
.filter(|c| ui.node(*c).has_component::<AbsmNode<State<Handle<Node>>>>())
|
||||
.collect::<Vec<_>>();
|
||||
ui.send_message(AbsmCanvasMessage::commit_transition_to_all_nodes(
|
||||
self.canvas,
|
||||
|
||||
@@ -41,9 +41,12 @@ pub struct StateGraphViewer {
|
||||
last_selection: AbsmSelection,
|
||||
}
|
||||
|
||||
fn fetch_state_node_model_handle(handle: Handle<UiNode>, ui: &UserInterface) -> Handle<State> {
|
||||
fn fetch_state_node_model_handle(
|
||||
handle: Handle<UiNode>,
|
||||
ui: &UserInterface,
|
||||
) -> Handle<State<Handle<Node>>> {
|
||||
ui.node(handle)
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle
|
||||
}
|
||||
@@ -93,7 +96,11 @@ impl StateGraphViewer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn activate_transition(&self, ui: &UserInterface, transition: Handle<Transition>) {
|
||||
pub fn activate_transition(
|
||||
&self,
|
||||
ui: &UserInterface,
|
||||
transition: Handle<Transition<Handle<Node>>>,
|
||||
) {
|
||||
if let Some(view_handle) = ui.node(self.canvas).children().iter().cloned().find(|c| {
|
||||
ui.node(*c)
|
||||
.query_component::<TransitionView>()
|
||||
@@ -108,7 +115,7 @@ impl StateGraphViewer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn activate_state(&self, ui: &UserInterface, state: Handle<State>) {
|
||||
pub fn activate_state(&self, ui: &UserInterface, state: Handle<State<Handle<Node>>>) {
|
||||
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::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.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::<AbsmNode<State>>()
|
||||
if let Some(state_node) = node_ref
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
{
|
||||
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<Handle<Node>>,
|
||||
ui: &mut UserInterface,
|
||||
editor_selection: &Selection,
|
||||
) {
|
||||
@@ -287,7 +294,7 @@ impl StateGraphViewer {
|
||||
.children()
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|c| ui.node(*c).has_component::<AbsmNode<State>>())
|
||||
.filter(|c| ui.node(*c).has_component::<AbsmNode<State<Handle<Node>>>>())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle
|
||||
!= state_handle
|
||||
@@ -351,7 +358,7 @@ impl StateGraphViewer {
|
||||
(
|
||||
state_view,
|
||||
ui.node(state_view)
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle,
|
||||
)
|
||||
@@ -381,7 +388,7 @@ impl StateGraphViewer {
|
||||
for state in states.iter() {
|
||||
let state_node = ui
|
||||
.node(*state)
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.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>,
|
||||
state_handle: Handle<State<Handle<Node>>>,
|
||||
states: &[Handle<UiNode>],
|
||||
ui: &UserInterface,
|
||||
) -> Handle<UiNode> {
|
||||
@@ -459,7 +466,7 @@ impl StateGraphViewer {
|
||||
.iter()
|
||||
.find(|s| {
|
||||
ui.node(**s)
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle
|
||||
== state_handle
|
||||
@@ -547,7 +554,7 @@ impl StateGraphViewer {
|
||||
}),
|
||||
SelectedEntity::State(state) => states.iter().cloned().find(|s| {
|
||||
ui.node(*s)
|
||||
.query_component::<AbsmNode<State>>()
|
||||
.query_component::<AbsmNode<State<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle
|
||||
== *state
|
||||
|
||||
@@ -99,7 +99,7 @@ impl CanvasContextMenu {
|
||||
&mut self,
|
||||
sender: &MessageSender,
|
||||
message: &UiMessage,
|
||||
current_state: Handle<State>,
|
||||
current_state: Handle<State<Handle<Node>>>,
|
||||
ui: &mut UserInterface,
|
||||
absm_node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
@@ -221,7 +221,7 @@ impl NodeContextMenu {
|
||||
pub fn handle_ui_message(
|
||||
&mut self,
|
||||
message: &UiMessage,
|
||||
machine_layer: &MachineLayer,
|
||||
machine_layer: &MachineLayer<Handle<Node>>,
|
||||
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::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle;
|
||||
|
||||
@@ -307,7 +307,7 @@ impl ConnectionContextMenu {
|
||||
message: &UiMessage,
|
||||
ui: &mut UserInterface,
|
||||
sender: &MessageSender,
|
||||
machine_layer: &MachineLayer,
|
||||
machine_layer: &MachineLayer<Handle<Node>>,
|
||||
absm_node_handle: Handle<Node>,
|
||||
layer_index: usize,
|
||||
) {
|
||||
@@ -320,7 +320,7 @@ impl ConnectionContextMenu {
|
||||
|
||||
let dest_node_ref = ui
|
||||
.node(connection_ref.dest_node)
|
||||
.query_component::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.unwrap();
|
||||
|
||||
let index = dest_node_ref
|
||||
|
||||
@@ -49,7 +49,7 @@ mod context;
|
||||
pub struct StateViewer {
|
||||
pub window: Handle<UiNode>,
|
||||
canvas: Handle<UiNode>,
|
||||
state: Handle<State>,
|
||||
state: Handle<State<Handle<Node>>>,
|
||||
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<PoseNode>,
|
||||
parent_node: Handle<PoseNode<Handle<Node>>>,
|
||||
ui: &mut UserInterface,
|
||||
) -> Handle<UiNode> {
|
||||
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<PoseNode>,
|
||||
parent_node: Handle<PoseNode<Handle<Node>>>,
|
||||
ui: &mut UserInterface,
|
||||
) -> Vec<Handle<UiNode>> {
|
||||
(0..count)
|
||||
@@ -82,9 +82,12 @@ fn create_sockets(
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn fetch_pose_node_model_handle(handle: Handle<UiNode>, ui: &UserInterface) -> Handle<PoseNode> {
|
||||
fn fetch_pose_node_model_handle(
|
||||
handle: Handle<UiNode>,
|
||||
ui: &UserInterface,
|
||||
) -> Handle<PoseNode<Handle<Node>>> {
|
||||
ui.node(handle)
|
||||
.query_component::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle
|
||||
}
|
||||
@@ -92,7 +95,7 @@ fn fetch_pose_node_model_handle(handle: Handle<UiNode>, ui: &UserInterface) -> H
|
||||
fn fetch_socket_pose_node_model_handle(
|
||||
handle: Handle<UiNode>,
|
||||
ui: &UserInterface,
|
||||
) -> Handle<PoseNode> {
|
||||
) -> Handle<PoseNode<Handle<Node>>> {
|
||||
ui.node(handle)
|
||||
.query_component::<Socket>()
|
||||
.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>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
) -> String {
|
||||
if let Some(animation) = graph
|
||||
.try_get_of_type::<AnimationPlayer>(absm_node.animation_player())
|
||||
@@ -115,7 +118,7 @@ fn make_play_animation_name(
|
||||
}
|
||||
|
||||
fn make_pose_node_name(
|
||||
model_ref: &PoseNode,
|
||||
model_ref: &PoseNode<Handle<Node>>,
|
||||
graph: &Graph,
|
||||
absm_node: &AnimationBlendingStateMachine,
|
||||
) -> String {
|
||||
@@ -177,7 +180,7 @@ impl StateViewer {
|
||||
|
||||
pub fn set_state(
|
||||
&mut self,
|
||||
state: Handle<State>,
|
||||
state: Handle<State<Handle<Node>>>,
|
||||
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::<AbsmNode<PoseNode>>().map(
|
||||
node_ref.query_component::<AbsmNode<PoseNode<Handle<Node>>>>().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<Handle<Node>>,
|
||||
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::<AbsmNode<PoseNode>>()
|
||||
if let Some(pose_node) = ui
|
||||
.node(*h)
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
{
|
||||
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::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.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::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.unwrap();
|
||||
|
||||
if machine_layer
|
||||
@@ -553,7 +558,7 @@ impl StateViewer {
|
||||
for &view in &views {
|
||||
let view_ref = ui
|
||||
.node(view)
|
||||
.query_component::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.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::<AbsmNode<PoseNode>>())
|
||||
.filter_map(|v| {
|
||||
ui.node(*v)
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
})
|
||||
.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::<AbsmNode<PoseNode>>())
|
||||
.filter_map(|v| {
|
||||
ui.node(*v)
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
})
|
||||
.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::<AbsmNode<PoseNode>>()
|
||||
.query_component::<AbsmNode<PoseNode<Handle<Node>>>>()
|
||||
.unwrap()
|
||||
.model_handle
|
||||
== *pose_node
|
||||
|
||||
@@ -14,6 +14,8 @@ use crate::{
|
||||
},
|
||||
send_sync_message,
|
||||
};
|
||||
use fyrox::core::pool::ErasedHandle;
|
||||
use fyrox::scene::node::Node;
|
||||
use fyrox::{
|
||||
animation::machine::{LayerMask, MachineLayer},
|
||||
core::pool::Handle,
|
||||
@@ -250,8 +252,8 @@ impl Toolbar {
|
||||
.cloned()
|
||||
.filter(|n| {
|
||||
graph
|
||||
.try_get((*n).into())
|
||||
.map_or(false, |n| !unique_nodes.contains(&(n.parent().into())))
|
||||
.try_get(*n)
|
||||
.map_or(false, |n| !unique_nodes.contains(&n.parent()))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -281,8 +283,13 @@ impl Toolbar {
|
||||
|
||||
if let Some(layer_index) = selection.layer {
|
||||
if let Some(layer) = absm_node.machine().layers().get(layer_index) {
|
||||
let selection =
|
||||
layer.mask().inner().iter().cloned().collect::<Vec<_>>();
|
||||
let selection = layer
|
||||
.mask()
|
||||
.inner()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(ErasedHandle::from)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ui.send_message(NodeSelectorMessage::selection(
|
||||
self.node_selector,
|
||||
@@ -326,7 +333,12 @@ impl Toolbar {
|
||||
&& message.direction() == MessageDirection::FromWidget
|
||||
{
|
||||
if let Some(layer_index) = selection.layer {
|
||||
let new_mask = LayerMask::from(mask_selection.clone());
|
||||
let new_mask = LayerMask::from(
|
||||
mask_selection
|
||||
.iter()
|
||||
.map(|h| Handle::<Node>::from(*h))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
sender.do_scene_command(SetLayerMaskCommand {
|
||||
absm_node_handle: selection.absm_node_handle,
|
||||
layer_index,
|
||||
|
||||
@@ -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<Transition>,
|
||||
pub model_handle: Handle<Transition<Handle<Node>>>,
|
||||
selectable: Selectable,
|
||||
activity_factor: f32,
|
||||
}
|
||||
@@ -182,7 +183,11 @@ impl TransitionBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, model_handle: Handle<Transition>, ctx: &mut BuildContext) -> Handle<UiNode> {
|
||||
pub fn build(
|
||||
self,
|
||||
model_handle: Handle<Transition<Handle<Node>>>,
|
||||
ctx: &mut BuildContext,
|
||||
) -> Handle<UiNode> {
|
||||
let transition = TransitionView {
|
||||
widget: self
|
||||
.widget_builder
|
||||
|
||||
@@ -34,12 +34,16 @@ fn fetch_animation_player<'a>(
|
||||
#[derive(Debug)]
|
||||
pub struct AddTrackCommand {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
track: Option<Track>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
track: Option<Track<Handle<Node>>>,
|
||||
}
|
||||
|
||||
impl AddTrackCommand {
|
||||
pub fn new(animation_player: Handle<Node>, animation: Handle<Animation>, track: Track) -> Self {
|
||||
pub fn new(
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
track: Track<Handle<Node>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
animation_player,
|
||||
animation,
|
||||
@@ -68,13 +72,17 @@ impl GameSceneCommandTrait for AddTrackCommand {
|
||||
#[derive(Debug)]
|
||||
pub struct RemoveTrackCommand {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
index: usize,
|
||||
track: Option<Track>,
|
||||
track: Option<Track<Handle<Node>>>,
|
||||
}
|
||||
|
||||
impl RemoveTrackCommand {
|
||||
pub fn new(animation_player: Handle<Node>, animation: Handle<Animation>, index: usize) -> Self {
|
||||
pub fn new(
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
index: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
animation_player,
|
||||
animation,
|
||||
@@ -105,7 +113,7 @@ impl GameSceneCommandTrait for RemoveTrackCommand {
|
||||
#[derive(Debug)]
|
||||
pub struct ReplaceTrackCurveCommand {
|
||||
pub animation_player: Handle<Node>,
|
||||
pub animation: Handle<Animation>,
|
||||
pub animation: Handle<Animation<Handle<Node>>>,
|
||||
pub curve: Curve,
|
||||
}
|
||||
|
||||
@@ -146,23 +154,23 @@ pub enum AddAnimationCommand {
|
||||
Unknown,
|
||||
NonExecuted {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Animation,
|
||||
animation: Animation<Handle<Node>>,
|
||||
},
|
||||
Executed {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
selection: Selection,
|
||||
},
|
||||
Reverted {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Animation,
|
||||
ticket: Ticket<Animation>,
|
||||
animation: Animation<Handle<Node>>,
|
||||
ticket: Ticket<Animation<Handle<Node>>>,
|
||||
selection: Selection,
|
||||
},
|
||||
}
|
||||
|
||||
impl AddAnimationCommand {
|
||||
pub fn new(animation_player: Handle<Node>, animation: Animation) -> Self {
|
||||
pub fn new(animation_player: Handle<Node>, animation: Animation<Handle<Node>>) -> Self {
|
||||
Self::NonExecuted {
|
||||
animation_player,
|
||||
animation,
|
||||
@@ -265,21 +273,21 @@ pub enum RemoveAnimationCommand {
|
||||
Unknown,
|
||||
NonExecuted {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
},
|
||||
Executed {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Animation,
|
||||
ticket: Ticket<Animation>,
|
||||
animation: Animation<Handle<Node>>,
|
||||
ticket: Ticket<Animation<Handle<Node>>>,
|
||||
},
|
||||
Reverted {
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl RemoveAnimationCommand {
|
||||
pub fn new(animation_player: Handle<Node>, animation: Handle<Animation>) -> Self {
|
||||
pub fn new(animation_player: Handle<Node>, animation: Handle<Animation<Handle<Node>>>) -> Self {
|
||||
Self::NonExecuted {
|
||||
animation_player,
|
||||
animation,
|
||||
@@ -353,8 +361,8 @@ impl GameSceneCommandTrait for RemoveAnimationCommand {
|
||||
#[derive(Debug)]
|
||||
pub struct ReplaceAnimationCommand {
|
||||
pub animation_player: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation: Animation,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub animation: Animation<Handle<Node>>,
|
||||
}
|
||||
|
||||
impl ReplaceAnimationCommand {
|
||||
@@ -388,7 +396,7 @@ macro_rules! define_animation_swap_command {
|
||||
#[derive(Debug)]
|
||||
pub struct $name {
|
||||
pub node_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub value: $value_type,
|
||||
}
|
||||
|
||||
@@ -416,9 +424,9 @@ macro_rules! define_animation_swap_command {
|
||||
|
||||
fn fetch_animation<'a>(
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
ctx: &'a mut GameSceneContext,
|
||||
) -> &'a mut Animation {
|
||||
) -> &'a mut Animation<Handle<Node>> {
|
||||
fetch_animation_player(animation_player, ctx)
|
||||
.animations_mut()
|
||||
.index_mut(animation)
|
||||
@@ -459,7 +467,7 @@ define_animation_swap_command!(SetAnimationEnabledCommand<bool>(self, context) {
|
||||
self.value = old;
|
||||
});
|
||||
|
||||
define_animation_swap_command!(SetAnimationRootMotionSettingsCommand<Option<RootMotionSettings>>(self, context) {
|
||||
define_animation_swap_command!(SetAnimationRootMotionSettingsCommand<Option<RootMotionSettings<Handle<Node>>>>(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<Option<Root
|
||||
#[derive(Debug)]
|
||||
pub struct AddAnimationSignal {
|
||||
pub animation_player_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub signal: Option<AnimationSignal>,
|
||||
}
|
||||
|
||||
@@ -492,7 +500,7 @@ impl GameSceneCommandTrait for AddAnimationSignal {
|
||||
#[derive(Debug)]
|
||||
pub struct MoveAnimationSignal {
|
||||
pub animation_player_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub signal: Uuid,
|
||||
pub time: f32,
|
||||
}
|
||||
@@ -528,7 +536,7 @@ impl GameSceneCommandTrait for MoveAnimationSignal {
|
||||
#[derive(Debug)]
|
||||
pub struct RemoveAnimationSignal {
|
||||
pub animation_player_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub signal_index: usize,
|
||||
pub signal: Option<AnimationSignal>,
|
||||
}
|
||||
@@ -554,7 +562,7 @@ impl GameSceneCommandTrait for RemoveAnimationSignal {
|
||||
#[derive(Debug)]
|
||||
pub struct SetTrackEnabledCommand {
|
||||
pub animation_player_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub track: Uuid,
|
||||
pub enabled: bool,
|
||||
}
|
||||
@@ -590,7 +598,7 @@ impl GameSceneCommandTrait for SetTrackEnabledCommand {
|
||||
#[derive(Debug)]
|
||||
pub struct SetTrackTargetCommand {
|
||||
pub animation_player_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub track: Uuid,
|
||||
pub target: Handle<Node>,
|
||||
}
|
||||
@@ -626,7 +634,7 @@ impl GameSceneCommandTrait for SetTrackTargetCommand {
|
||||
#[derive(Debug)]
|
||||
pub struct SetTrackBindingCommand {
|
||||
pub animation_player_handle: Handle<Node>,
|
||||
pub animation_handle: Handle<Animation>,
|
||||
pub animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
pub track: Uuid,
|
||||
pub binding: ValueBinding,
|
||||
}
|
||||
|
||||
@@ -27,5 +27,5 @@ define_universal_commands!(
|
||||
.unwrap()
|
||||
},
|
||||
node_handle: Handle<Node>,
|
||||
animation_handle: Handle<Animation>
|
||||
animation_handle: Handle<Animation<Handle<Node>>>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@ pub enum SelectedEntity {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct AnimationSelection {
|
||||
pub animation_player: Handle<Node>,
|
||||
pub animation: Handle<Animation>,
|
||||
pub animation: Handle<Animation<Handle<Node>>>,
|
||||
pub entities: Vec<SelectedEntity>,
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ impl RootMotionDropdownArea {
|
||||
game_scene: &GameScene,
|
||||
selection: &AnimationSelection,
|
||||
) {
|
||||
let send_command = |settings: Option<RootMotionSettings>| {
|
||||
let send_command = |settings: Option<RootMotionSettings<Handle<Node>>>| {
|
||||
sender.do_scene_command(SetAnimationRootMotionSettingsCommand {
|
||||
node_handle: selection.animation_player,
|
||||
animation_handle: selection.animation,
|
||||
@@ -263,7 +263,7 @@ impl RootMotionDropdownArea {
|
||||
self.node_selector,
|
||||
MessageDirection::ToWidget,
|
||||
if settings.node.is_some() {
|
||||
vec![settings.node]
|
||||
vec![settings.node.into()]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
@@ -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(),
|
||||
node: node_selection
|
||||
.first()
|
||||
.cloned()
|
||||
.map(Handle::from)
|
||||
.unwrap_or_default(),
|
||||
..*settings
|
||||
}),
|
||||
});
|
||||
@@ -365,7 +369,7 @@ pub enum ToolbarAction {
|
||||
None,
|
||||
EnterPreviewMode,
|
||||
LeavePreviewMode,
|
||||
SelectAnimation(Handle<Animation>),
|
||||
SelectAnimation(Handle<Animation<Handle<Node>>>),
|
||||
PlayPause,
|
||||
Stop,
|
||||
}
|
||||
@@ -863,7 +867,7 @@ impl Toolbar {
|
||||
.items()[*index];
|
||||
let animation = ui
|
||||
.node(item)
|
||||
.user_data_cloned::<Handle<Animation>>()
|
||||
.user_data_cloned::<Handle<Animation<Handle<Node>>>>()
|
||||
.unwrap();
|
||||
sender.do_scene_command(ChangeSelectionCommand::new(
|
||||
Selection::Animation(AnimationSelection {
|
||||
|
||||
@@ -584,7 +584,7 @@ pub struct TrackList {
|
||||
context_menu: TrackContextMenu,
|
||||
property_binding_mode: PropertyBindingMode,
|
||||
scroll_viewer: Handle<UiNode>,
|
||||
selected_animation: Handle<Animation>,
|
||||
selected_animation: Handle<Animation<Handle<Node>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -735,7 +735,7 @@ impl TrackList {
|
||||
game_scene: &GameScene,
|
||||
sender: &MessageSender,
|
||||
animation_player: Handle<Node>,
|
||||
animation: Handle<Animation>,
|
||||
animation: Handle<Animation<Handle<Node>>>,
|
||||
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<Node>>,
|
||||
animation_handle: Handle<Animation<Handle<Node>>>,
|
||||
graph: &Graph,
|
||||
editor_selection: &Selection,
|
||||
ui: &mut UserInterface,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Animation selector for `Handle<Animation>` 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::<Handle<Animation>>()
|
||||
TypeId::of::<Handle<Animation<Handle<Node>>>>()
|
||||
}
|
||||
|
||||
fn create_instance(
|
||||
&self,
|
||||
ctx: PropertyEditorBuildContext,
|
||||
) -> Result<PropertyEditorInstance, InspectorError> {
|
||||
let value = ctx.property_info.cast_value::<Handle<Animation>>()?;
|
||||
let value = ctx
|
||||
.property_info
|
||||
.cast_value::<Handle<Animation<Handle<Node>>>>()?;
|
||||
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<Option<UiMessage>, InspectorError> {
|
||||
let value = ctx.property_info.cast_value::<Handle<Animation>>()?;
|
||||
let value = ctx
|
||||
.property_info
|
||||
.cast_value::<Handle<Animation<Handle<Node>>>>()?;
|
||||
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::<AnimationContainer>()
|
||||
TypeId::of::<AnimationContainer<Handle<Node>>>()
|
||||
}
|
||||
|
||||
fn create_instance(
|
||||
@@ -151,7 +156,7 @@ pub struct MachinePropertyEditorDefinition;
|
||||
|
||||
impl PropertyEditorDefinition for MachinePropertyEditorDefinition {
|
||||
fn value_type_id(&self) -> TypeId {
|
||||
TypeId::of::<Machine>()
|
||||
TypeId::of::<Machine<Handle<Node>>>()
|
||||
}
|
||||
|
||||
fn create_instance(
|
||||
|
||||
@@ -365,39 +365,71 @@ pub fn make_property_editors_container(sender: MessageSender) -> PropertyEditorD
|
||||
container.insert(InheritablePropertyEditorDefinition::<SurfaceSharedData>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<Status>::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::<BlendPose>::new());
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<BlendPose>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
BasePoseNode<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
IndexedBlendInput<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<
|
||||
IndexedBlendInput<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
BlendSpacePoint<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<
|
||||
BlendSpacePoint<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<BlendPose<Handle<Node>>>::new());
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<
|
||||
BlendPose<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(EnumPropertyEditorDefinition::<PoseWeight>::new());
|
||||
container.insert(EnumPropertyEditorDefinition::<StateAction>::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(EnumPropertyEditorDefinition::<StateAction<Handle<Node>>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
StateActionWrapper<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<
|
||||
StateActionWrapper<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
BlendAnimationsByIndex<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
BlendAnimations<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
BlendSpace<Handle<Node>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
PlayAnimation<Handle<Node>>,
|
||||
>::new());
|
||||
|
||||
container.insert(InspectablePropertyEditorDefinition::<Handle<PoseNode>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<Handle<State>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
Handle<PoseNode<Handle<Node>>>,
|
||||
>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<
|
||||
Handle<State<Handle<Node>>>,
|
||||
>::new());
|
||||
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<Handle<Animation>>::new());
|
||||
container.insert(VecCollectionPropertyEditorDefinition::<
|
||||
Handle<Animation<Handle<Node>>>,
|
||||
>::new());
|
||||
container.insert(AnimationPropertyEditorDefinition);
|
||||
|
||||
container.insert(AnimationContainerPropertyEditorDefinition);
|
||||
container.insert(InheritablePropertyEditorDefinition::<AnimationContainer>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<
|
||||
AnimationContainer<Handle<Node>>,
|
||||
>::new());
|
||||
|
||||
container.insert(MachinePropertyEditorDefinition);
|
||||
container.insert(InheritablePropertyEditorDefinition::<Machine>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<Machine<Handle<Node>>>::new());
|
||||
|
||||
container.insert(EnumPropertyEditorDefinition::<LogicNode>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<AndNode>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<OrNode>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<XorNode>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<NotNode>::new());
|
||||
container.insert(EnumPropertyEditorDefinition::<LogicNode<Handle<Node>>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<AndNode<Handle<Node>>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<OrNode<Handle<Node>>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<XorNode<Handle<Node>>>::new());
|
||||
container.insert(InspectablePropertyEditorDefinition::<NotNode<Handle<Node>>>::new());
|
||||
|
||||
container.insert(InspectablePropertyEditorDefinition::<ParticleSystemRng>::new());
|
||||
container.insert(EnumPropertyEditorDefinition::<PolygonFillMode>::new());
|
||||
|
||||
@@ -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<Animation>,
|
||||
handle: Handle<Animation<Handle<Node>>>,
|
||||
}
|
||||
|
||||
pub struct EditorEnvironment {
|
||||
|
||||
+80
-57
@@ -14,7 +14,8 @@ use crate::{
|
||||
},
|
||||
track::Track,
|
||||
};
|
||||
use fyrox_core::{uuid_provider, NameProvider};
|
||||
use fyrox_core::{NameProvider, TypeUuidProvider};
|
||||
use std::hash::Hash;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
fmt::Debug,
|
||||
@@ -23,6 +24,7 @@ use std::{
|
||||
|
||||
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};
|
||||
@@ -127,7 +129,7 @@ pub mod value;
|
||||
/// };
|
||||
/// use fyrox_core::pool::ErasedHandle;
|
||||
///
|
||||
/// fn create_animation(target: ErasedHandle) -> Animation {
|
||||
/// fn create_animation(target: ErasedHandle) -> Animation<T> {
|
||||
/// let mut frames_container = TrackDataContainer::new(TrackValueKind::Vector3);
|
||||
///
|
||||
/// // We'll animate only X coordinate (at index 0).
|
||||
@@ -163,10 +165,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<T: EntityId> {
|
||||
#[visit(optional)]
|
||||
name: String,
|
||||
tracks: Vec<Track>,
|
||||
tracks: Vec<Track<T>>,
|
||||
time_position: f32,
|
||||
#[visit(optional)]
|
||||
time_slice: Range<f32>,
|
||||
@@ -176,7 +178,7 @@ pub struct Animation {
|
||||
signals: Vec<AnimationSignal>,
|
||||
|
||||
#[visit(optional)]
|
||||
root_motion_settings: Option<RootMotionSettings>,
|
||||
root_motion_settings: Option<RootMotionSettings<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
@@ -185,23 +187,36 @@ pub struct Animation {
|
||||
// Non-serialized
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
pose: AnimationPose,
|
||||
pose: AnimationPose<T>,
|
||||
// Non-serialized
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
events: VecDeque<AnimationEvent>,
|
||||
}
|
||||
|
||||
uuid_provider!(Animation = "aade8e9d-e2cf-401d-a4d1-59c6943645f3");
|
||||
impl<T: EntityId> TypeUuidProvider for Animation<T> {
|
||||
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<T: 'static> EntityId for Handle<T> {}
|
||||
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<T: EntityId> {
|
||||
/// 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: ErasedHandle,
|
||||
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.
|
||||
@@ -234,13 +249,13 @@ impl RootMotion {
|
||||
}
|
||||
}
|
||||
|
||||
impl NameProvider for Animation {
|
||||
impl<T: EntityId> NameProvider for Animation<T> {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Animation {
|
||||
impl<T: EntityId> Clone for Animation<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
name: self.name.clone(),
|
||||
@@ -259,7 +274,7 @@ impl Clone for Animation {
|
||||
}
|
||||
}
|
||||
|
||||
impl Animation {
|
||||
impl<T: EntityId> Animation<T> {
|
||||
/// Sets a new name for the animation. The name then could be used to find the animation in a container.
|
||||
pub fn set_name<S: AsRef<str>>(&mut self, name: S) {
|
||||
self.name = name.as_ref().to_owned();
|
||||
@@ -272,22 +287,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<T>) {
|
||||
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<T> {
|
||||
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<T>) {
|
||||
self.tracks.insert(index, track)
|
||||
}
|
||||
|
||||
/// Removes last track from the list of tracks of the animation.
|
||||
pub fn pop_track(&mut self) -> Option<Track> {
|
||||
pub fn pop_track(&mut self) -> Option<Track<T>> {
|
||||
self.tracks.pop()
|
||||
}
|
||||
|
||||
@@ -305,7 +320,7 @@ impl Animation {
|
||||
}
|
||||
|
||||
/// Returns a reference to tracks container.
|
||||
pub fn tracks(&self) -> &[Track] {
|
||||
pub fn tracks(&self) -> &[Track<T>] {
|
||||
&self.tracks
|
||||
}
|
||||
|
||||
@@ -387,7 +402,7 @@ impl Animation {
|
||||
}
|
||||
|
||||
fn update_root_motion(&mut self, prev_time_position: f32) {
|
||||
fn fetch_position_at_time(tracks: &[Track], time: f32) -> Vector3<f32> {
|
||||
fn fetch_position_at_time<T: EntityId>(tracks: &[Track<T>], time: f32) -> Vector3<f32> {
|
||||
tracks
|
||||
.iter()
|
||||
.find(|track| track.binding() == &ValueBinding::Position)
|
||||
@@ -402,7 +417,10 @@ impl Animation {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn fetch_rotation_at_time(tracks: &[Track], time: f32) -> UnitQuaternion<f32> {
|
||||
fn fetch_rotation_at_time<T: EntityId>(
|
||||
tracks: &[Track<T>],
|
||||
time: f32,
|
||||
) -> UnitQuaternion<f32> {
|
||||
tracks
|
||||
.iter()
|
||||
.find(|track| track.binding() == &ValueBinding::Rotation)
|
||||
@@ -536,17 +554,17 @@ impl Animation {
|
||||
}
|
||||
|
||||
/// Sets new root motion settings.
|
||||
pub fn set_root_motion_settings(&mut self, settings: Option<RootMotionSettings>) {
|
||||
pub fn set_root_motion_settings(&mut self, settings: Option<RootMotionSettings<T>>) {
|
||||
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<T>> {
|
||||
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<T>> {
|
||||
self.root_motion_settings.as_mut()
|
||||
}
|
||||
|
||||
@@ -625,7 +643,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<T>] {
|
||||
&mut self.tracks
|
||||
}
|
||||
|
||||
@@ -664,13 +682,13 @@ impl Animation {
|
||||
/// to remove undesired animation tracks.
|
||||
pub fn retain_tracks<F>(&mut self, filter: F)
|
||||
where
|
||||
F: FnMut(&Track) -> bool,
|
||||
F: FnMut(&Track<T>) -> bool,
|
||||
{
|
||||
self.tracks.retain(filter)
|
||||
}
|
||||
|
||||
/// 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: ErasedHandle, 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);
|
||||
@@ -679,14 +697,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: ErasedHandle) -> impl Iterator<Item = &Track> {
|
||||
pub fn tracks_of(&self, handle: T) -> impl Iterator<Item = &Track<T>> {
|
||||
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: ErasedHandle) -> impl Iterator<Item = &mut Track> {
|
||||
pub fn tracks_of_mut(&mut self, handle: T) -> impl Iterator<Item = &mut Track<T>> {
|
||||
self.tracks
|
||||
.iter_mut()
|
||||
.filter(move |track| track.target() == handle)
|
||||
@@ -734,12 +752,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<T> {
|
||||
&self.pose
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Animation {
|
||||
impl<T: EntityId> Default for Animation<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: Default::default(),
|
||||
@@ -761,17 +779,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<Animation>,
|
||||
pub struct AnimationContainer<T: EntityId> {
|
||||
pool: Pool<Animation<T>>,
|
||||
}
|
||||
|
||||
impl Default for AnimationContainer {
|
||||
impl<T: EntityId> Default for AnimationContainer<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimationContainer {
|
||||
impl<T: EntityId> AnimationContainer<T> {
|
||||
/// Creates an empty animation container.
|
||||
pub fn new() -> Self {
|
||||
Self { pool: Pool::new() }
|
||||
@@ -785,57 +803,62 @@ impl AnimationContainer {
|
||||
|
||||
/// Returns an iterator yielding a references to animations in the container.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Animation> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Animation<T>> {
|
||||
self.pool.iter()
|
||||
}
|
||||
|
||||
/// Returns an iterator yielding a pair (handle, reference) to animations in the container.
|
||||
#[inline]
|
||||
pub fn pair_iter(&self) -> impl Iterator<Item = (Handle<Animation>, &Animation)> {
|
||||
pub fn pair_iter(&self) -> impl Iterator<Item = (Handle<Animation<T>>, &Animation<T>)> {
|
||||
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<Item = (Handle<Animation>, &mut Animation)> {
|
||||
pub fn pair_iter_mut(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (Handle<Animation<T>>, &mut Animation<T>)> {
|
||||
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<Item = &mut Animation> {
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Animation<T>> {
|
||||
self.pool.iter_mut()
|
||||
}
|
||||
|
||||
/// Adds a new animation to the container and returns its handle.
|
||||
#[inline]
|
||||
pub fn add(&mut self, animation: Animation) -> Handle<Animation> {
|
||||
pub fn add(&mut self, animation: Animation<T>) -> Handle<Animation<T>> {
|
||||
self.pool.spawn(animation)
|
||||
}
|
||||
|
||||
/// Tries to remove an animation from the container by its handle.
|
||||
#[inline]
|
||||
pub fn remove(&mut self, handle: Handle<Animation>) -> Option<Animation> {
|
||||
pub fn remove(&mut self, handle: Handle<Animation<T>>) -> Option<Animation<T>> {
|
||||
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<Animation>) -> (Ticket<Animation>, Animation) {
|
||||
pub fn take_reserve(
|
||||
&mut self,
|
||||
handle: Handle<Animation<T>>,
|
||||
) -> (Ticket<Animation<T>>, Animation<T>) {
|
||||
self.pool.take_reserve(handle)
|
||||
}
|
||||
|
||||
/// Puts animation back by given ticket.
|
||||
pub fn put_back(
|
||||
&mut self,
|
||||
ticket: Ticket<Animation>,
|
||||
animation: Animation,
|
||||
) -> Handle<Animation> {
|
||||
ticket: Ticket<Animation<T>>,
|
||||
animation: Animation<T>,
|
||||
) -> Handle<Animation<T>> {
|
||||
self.pool.put_back(ticket, animation)
|
||||
}
|
||||
|
||||
/// Makes animation handle vacant again.
|
||||
pub fn forget_ticket(&mut self, ticket: Ticket<Animation>) {
|
||||
pub fn forget_ticket(&mut self, ticket: Ticket<Animation<T>>) {
|
||||
self.pool.forget_ticket(ticket)
|
||||
}
|
||||
|
||||
@@ -847,25 +870,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>) -> &Animation {
|
||||
pub fn get(&self, handle: Handle<Animation<T>>) -> &Animation<T> {
|
||||
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<Animation>) -> &mut Animation {
|
||||
pub fn get_mut(&mut self, handle: Handle<Animation<T>>) -> &mut Animation<T> {
|
||||
self.pool.borrow_mut(handle)
|
||||
}
|
||||
|
||||
/// Tries to borrow a reference to an animation in the container.
|
||||
#[inline]
|
||||
pub fn try_get(&self, handle: Handle<Animation>) -> Option<&Animation> {
|
||||
pub fn try_get(&self, handle: Handle<Animation<T>>) -> Option<&Animation<T>> {
|
||||
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<Animation>) -> Option<&mut Animation> {
|
||||
pub fn try_get_mut(&mut self, handle: Handle<Animation<T>>) -> Option<&mut Animation<T>> {
|
||||
self.pool.try_borrow_mut(handle)
|
||||
}
|
||||
|
||||
@@ -874,7 +897,7 @@ impl AnimationContainer {
|
||||
pub fn find_by_name_ref<S: AsRef<str>>(
|
||||
&self,
|
||||
name: S,
|
||||
) -> Option<(Handle<Animation>, &Animation)> {
|
||||
) -> Option<(Handle<Animation<T>>, &Animation<T>)> {
|
||||
core::find_by_name_ref(self.pool.pair_iter(), name)
|
||||
}
|
||||
|
||||
@@ -883,7 +906,7 @@ impl AnimationContainer {
|
||||
pub fn find_by_name_mut<S: AsRef<str>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
) -> Option<(Handle<Animation>, &mut Animation)> {
|
||||
) -> Option<(Handle<Animation<T>>, &mut Animation<T>)> {
|
||||
core::find_by_name_mut(self.pool.pair_iter_mut(), name)
|
||||
}
|
||||
|
||||
@@ -892,7 +915,7 @@ impl AnimationContainer {
|
||||
#[inline]
|
||||
pub fn retain<P>(&mut self, pred: P)
|
||||
where
|
||||
P: FnMut(&Animation) -> bool,
|
||||
P: FnMut(&Animation<T>) -> bool,
|
||||
{
|
||||
self.pool.retain(pred)
|
||||
}
|
||||
@@ -912,7 +935,7 @@ impl AnimationContainer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for AnimationContainer {
|
||||
impl<T: EntityId> Visit for AnimationContainer<T> {
|
||||
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!");
|
||||
@@ -926,16 +949,16 @@ impl Visit for AnimationContainer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Handle<Animation>> for AnimationContainer {
|
||||
type Output = Animation;
|
||||
impl<T: EntityId> Index<Handle<Animation<T>>> for AnimationContainer<T> {
|
||||
type Output = Animation<T>;
|
||||
|
||||
fn index(&self, index: Handle<Animation>) -> &Self::Output {
|
||||
fn index(&self, index: Handle<Animation<T>>) -> &Self::Output {
|
||||
&self.pool[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<Handle<Animation>> for AnimationContainer {
|
||||
fn index_mut(&mut self, index: Handle<Animation>) -> &mut Self::Output {
|
||||
impl<T: EntityId> IndexMut<Handle<Animation<T>>> for AnimationContainer<T> {
|
||||
fn index_mut(&mut self, index: Handle<Animation<T>>) -> &mut Self::Output {
|
||||
&mut self.pool[index]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,40 +4,41 @@
|
||||
use crate::{
|
||||
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<T: EntityId> {
|
||||
/// Occurs when enter some state. See module docs for example.
|
||||
StateEnter(Handle<State>),
|
||||
StateEnter(Handle<State<T>>),
|
||||
|
||||
/// Occurs when leaving some state. See module docs for example.
|
||||
StateLeave(Handle<State>),
|
||||
StateLeave(Handle<State<T>>),
|
||||
|
||||
/// Occurs when a transition is done and a new active state was set.
|
||||
ActiveStateChanged {
|
||||
/// Previously active state.
|
||||
prev: Handle<State>,
|
||||
prev: Handle<State<T>>,
|
||||
|
||||
/// New active state.
|
||||
new: Handle<State>,
|
||||
new: Handle<State<T>>,
|
||||
},
|
||||
|
||||
/// Occurs when active transition was changed.
|
||||
ActiveTransitionChanged(Handle<Transition>),
|
||||
ActiveTransitionChanged(Handle<Transition<T>>),
|
||||
}
|
||||
|
||||
/// 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<Event>,
|
||||
pub struct FixedEventQueue<T: EntityId> {
|
||||
queue: VecDeque<Event<T>>,
|
||||
limit: u32,
|
||||
}
|
||||
|
||||
impl Default for FixedEventQueue {
|
||||
impl<T: EntityId> Default for FixedEventQueue<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
queue: Default::default(),
|
||||
@@ -46,7 +47,7 @@ impl Default for FixedEventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
impl FixedEventQueue {
|
||||
impl<T: EntityId> FixedEventQueue<T> {
|
||||
/// 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<T>) {
|
||||
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<Event> {
|
||||
pub fn pop(&mut self) -> Option<Event<T>> {
|
||||
self.queue.pop_front()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
event::FixedEventQueue, node::AnimationEventCollectionStrategy, AnimationPoseSource, Event,
|
||||
LayerMask, ParameterContainer, PoseNode, State, Transition,
|
||||
},
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose,
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId,
|
||||
};
|
||||
use fyrox_core::{find_by_name_mut, find_by_name_ref, NameProvider};
|
||||
|
||||
@@ -61,45 +61,45 @@ use fyrox_core::{find_by_name_mut, find_by_name_ref, NameProvider};
|
||||
///
|
||||
/// ```
|
||||
#[derive(Default, Debug, Visit, Reflect, Clone, PartialEq)]
|
||||
pub struct MachineLayer {
|
||||
pub struct MachineLayer<T: EntityId> {
|
||||
name: String,
|
||||
|
||||
weight: f32,
|
||||
|
||||
mask: LayerMask,
|
||||
mask: LayerMask<T>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
nodes: Pool<PoseNode>,
|
||||
nodes: Pool<PoseNode<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
transitions: Pool<Transition>,
|
||||
transitions: Pool<Transition<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
states: Pool<State>,
|
||||
states: Pool<State<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
active_state: Handle<State>,
|
||||
active_state: Handle<State<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
entry_state: Handle<State>,
|
||||
entry_state: Handle<State<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
active_transition: Handle<Transition>,
|
||||
active_transition: Handle<Transition<T>>,
|
||||
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
final_pose: AnimationPose,
|
||||
final_pose: AnimationPose<T>,
|
||||
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
events: FixedEventQueue,
|
||||
events: FixedEventQueue<T>,
|
||||
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
impl NameProvider for MachineLayer {
|
||||
impl<T: EntityId> NameProvider for MachineLayer<T> {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
@@ -107,25 +107,25 @@ impl NameProvider for MachineLayer {
|
||||
|
||||
/// A source of animation events coming from a layer.
|
||||
#[derive(Default)]
|
||||
pub enum AnimationEventsSource {
|
||||
pub enum AnimationEventsSource<T: EntityId> {
|
||||
/// 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<State>,
|
||||
handle: Handle<State<T>>,
|
||||
/// 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<Transition>,
|
||||
handle: Handle<Transition<T>>,
|
||||
/// A handle of a source state of an active transition.
|
||||
source_state_handle: Handle<State>,
|
||||
source_state_handle: Handle<State<T>>,
|
||||
/// A handle of a destination state of an active transition.
|
||||
dest_state_handle: Handle<State>,
|
||||
dest_state_handle: Handle<State<T>>,
|
||||
/// A name of a source state of an active transition.
|
||||
source_state_name: String,
|
||||
/// A name of a destination state of an active transition.
|
||||
@@ -136,14 +136,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<T: EntityId> {
|
||||
/// A source of events.
|
||||
pub source: AnimationEventsSource,
|
||||
pub source: AnimationEventsSource<T>,
|
||||
/// Actual animation events, defined as a tuple `(animation handle, event)`.
|
||||
pub events: Vec<(Handle<Animation>, AnimationEvent)>,
|
||||
pub events: Vec<(Handle<Animation<T>>, AnimationEvent)>,
|
||||
}
|
||||
|
||||
impl MachineLayer {
|
||||
impl<T: EntityId> MachineLayer<T> {
|
||||
/// Creates a new machine layer. See examples in [`MachineLayer`] docs.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
@@ -177,21 +177,21 @@ impl MachineLayer {
|
||||
|
||||
/// Adds a new node to the layer and returns its handle.
|
||||
#[inline]
|
||||
pub fn add_node(&mut self, node: PoseNode) -> Handle<PoseNode> {
|
||||
pub fn add_node(&mut self, node: PoseNode<T>) -> Handle<PoseNode<T>> {
|
||||
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<State>) {
|
||||
pub fn set_entry_state(&mut self, entry_state: Handle<State<T>>) {
|
||||
self.active_state = entry_state;
|
||||
self.entry_state = entry_state;
|
||||
}
|
||||
|
||||
/// Returns a handle of current entry state.
|
||||
#[inline]
|
||||
pub fn entry_state(&self) -> Handle<State> {
|
||||
pub fn entry_state(&self) -> Handle<State<T>> {
|
||||
self.entry_state
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ impl MachineLayer {
|
||||
|
||||
/// Adds a new state to the layer and returns its handle.
|
||||
#[inline]
|
||||
pub fn add_state(&mut self, state: State) -> Handle<State> {
|
||||
pub fn add_state(&mut self, state: State<T>) -> Handle<State<T>> {
|
||||
let state = self.states.spawn(state);
|
||||
if self.active_state.is_none() {
|
||||
self.active_state = state;
|
||||
@@ -214,19 +214,19 @@ impl MachineLayer {
|
||||
|
||||
/// Adds a new transition to the layer and returns its handle.
|
||||
#[inline]
|
||||
pub fn add_transition(&mut self, transition: Transition) -> Handle<Transition> {
|
||||
pub fn add_transition(&mut self, transition: Transition<T>) -> Handle<Transition<T>> {
|
||||
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>) -> &State {
|
||||
pub fn get_state(&self, state: Handle<State<T>>) -> &State<T> {
|
||||
&self.states[state]
|
||||
}
|
||||
|
||||
/// Borrows a transition using its handle, panics if the handle is invalid.
|
||||
#[inline]
|
||||
pub fn get_transition(&self, transition: Handle<Transition>) -> &Transition {
|
||||
pub fn get_transition(&self, transition: Handle<Transition<T>>) -> &Transition<T> {
|
||||
&self.transitions[transition]
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ impl MachineLayer {
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn pop_event(&mut self) -> Option<Event> {
|
||||
pub fn pop_event(&mut self) -> Option<Event<T>> {
|
||||
self.events.pop()
|
||||
}
|
||||
|
||||
@@ -285,9 +285,9 @@ impl MachineLayer {
|
||||
pub fn collect_active_animations_events(
|
||||
&self,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
strategy: AnimationEventCollectionStrategy,
|
||||
) -> LayerAnimationEventsCollection {
|
||||
) -> LayerAnimationEventsCollection<T> {
|
||||
if let Some(state) = self.states.try_borrow(self.active_state) {
|
||||
return LayerAnimationEventsCollection {
|
||||
source: AnimationEventsSource::State {
|
||||
@@ -379,25 +379,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>) -> &PoseNode {
|
||||
pub fn node(&self, handle: Handle<PoseNode<T>>) -> &PoseNode<T> {
|
||||
&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<PoseNode>) -> &mut PoseNode {
|
||||
pub fn node_mut(&mut self, handle: Handle<PoseNode<T>>) -> &mut PoseNode<T> {
|
||||
&mut self.nodes[handle]
|
||||
}
|
||||
|
||||
/// Returns a reference to inner node container.
|
||||
#[inline]
|
||||
pub fn nodes(&self) -> &Pool<PoseNode> {
|
||||
pub fn nodes(&self) -> &Pool<PoseNode<T>> {
|
||||
&self.nodes
|
||||
}
|
||||
|
||||
/// Returns a reference to inner node container.
|
||||
#[inline]
|
||||
pub fn nodes_mut(&mut self) -> &mut Pool<PoseNode> {
|
||||
pub fn nodes_mut(&mut self) -> &mut Pool<PoseNode<T>> {
|
||||
&mut self.nodes
|
||||
}
|
||||
|
||||
@@ -405,38 +405,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<State> {
|
||||
pub fn active_state(&self) -> Handle<State<T>> {
|
||||
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<Transition> {
|
||||
pub fn active_transition(&self) -> Handle<Transition<T>> {
|
||||
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>) -> &Transition {
|
||||
pub fn transition(&self, handle: Handle<Transition<T>>) -> &Transition<T> {
|
||||
&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<Transition>) -> &mut Transition {
|
||||
pub fn transition_mut(&mut self, handle: Handle<Transition<T>>) -> &mut Transition<T> {
|
||||
&mut self.transitions[handle]
|
||||
}
|
||||
|
||||
/// Returns a reference to inner transitions container.
|
||||
#[inline]
|
||||
pub fn transitions(&self) -> &Pool<Transition> {
|
||||
pub fn transitions(&self) -> &Pool<Transition<T>> {
|
||||
&self.transitions
|
||||
}
|
||||
|
||||
/// Returns a reference to inner transitions container.
|
||||
#[inline]
|
||||
pub fn transitions_mut(&mut self) -> &mut Pool<Transition> {
|
||||
pub fn transitions_mut(&mut self) -> &mut Pool<Transition<T>> {
|
||||
&mut self.transitions
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ impl MachineLayer {
|
||||
pub fn find_transition_by_name_ref<S: AsRef<str>>(
|
||||
&self,
|
||||
name: S,
|
||||
) -> Option<(Handle<Transition>, &Transition)> {
|
||||
) -> Option<(Handle<Transition<T>>, &Transition<T>)> {
|
||||
find_by_name_ref(self.transitions.pair_iter(), name)
|
||||
}
|
||||
|
||||
@@ -454,19 +454,19 @@ impl MachineLayer {
|
||||
pub fn find_transition_by_name_mut<S: AsRef<str>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
) -> Option<(Handle<Transition>, &mut Transition)> {
|
||||
) -> Option<(Handle<Transition<T>>, &mut Transition<T>)> {
|
||||
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>) -> &State {
|
||||
pub fn state(&self, handle: Handle<State<T>>) -> &State<T> {
|
||||
&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<State>) -> &mut State {
|
||||
pub fn state_mut(&mut self, handle: Handle<State<T>>) -> &mut State<T> {
|
||||
&mut self.states[handle]
|
||||
}
|
||||
|
||||
@@ -475,7 +475,7 @@ impl MachineLayer {
|
||||
pub fn find_state_by_name_ref<S: AsRef<str>>(
|
||||
&self,
|
||||
name: S,
|
||||
) -> Option<(Handle<State>, &State)> {
|
||||
) -> Option<(Handle<State<T>>, &State<T>)> {
|
||||
find_by_name_ref(self.states.pair_iter(), name)
|
||||
}
|
||||
|
||||
@@ -484,19 +484,19 @@ impl MachineLayer {
|
||||
pub fn find_state_by_name_mut<S: AsRef<str>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
) -> Option<(Handle<State>, &mut State)> {
|
||||
) -> Option<(Handle<State<T>>, &mut State<T>)> {
|
||||
find_by_name_mut(self.states.pair_iter_mut(), name)
|
||||
}
|
||||
|
||||
/// Returns a reference to inner states container.
|
||||
#[inline]
|
||||
pub fn states(&self) -> &Pool<State> {
|
||||
pub fn states(&self) -> &Pool<State<T>> {
|
||||
&self.states
|
||||
}
|
||||
|
||||
/// Returns a reference to inner states container.
|
||||
#[inline]
|
||||
pub fn states_mut(&mut self) -> &mut Pool<State> {
|
||||
pub fn states_mut(&mut self) -> &mut Pool<State<T>> {
|
||||
&mut self.states
|
||||
}
|
||||
|
||||
@@ -515,19 +515,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<T>) -> LayerMask<T> {
|
||||
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<T> {
|
||||
&self.mask
|
||||
}
|
||||
|
||||
/// Returns final pose of the layer.
|
||||
#[inline]
|
||||
pub fn pose(&self) -> &AnimationPose {
|
||||
pub fn pose(&self) -> &AnimationPose<T> {
|
||||
&self.final_pose
|
||||
}
|
||||
|
||||
@@ -536,8 +536,8 @@ impl MachineLayer {
|
||||
/// to listen for animation events and react to them.
|
||||
pub fn animations_of_state(
|
||||
&self,
|
||||
state: Handle<State>,
|
||||
) -> impl Iterator<Item = Handle<Animation>> + '_ {
|
||||
state: Handle<State<T>>,
|
||||
) -> impl Iterator<Item = Handle<Animation<T>>> + '_ {
|
||||
self.nodes.iter().filter_map(move |node| {
|
||||
if node.parent_state == state {
|
||||
if let PoseNode::PlayAnimation(play_animation) = node {
|
||||
@@ -554,8 +554,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<State>,
|
||||
animations: &AnimationContainer,
|
||||
state: Handle<State<T>>,
|
||||
animations: &AnimationContainer<T>,
|
||||
) -> bool {
|
||||
self.animations_of_state(state)
|
||||
.filter_map(|a| animations.try_get(a))
|
||||
@@ -565,10 +565,10 @@ impl MachineLayer {
|
||||
#[inline]
|
||||
pub(super) fn evaluate_pose(
|
||||
&mut self,
|
||||
animations: &mut AnimationContainer,
|
||||
animations: &mut AnimationContainer<T>,
|
||||
parameters: &ParameterContainer,
|
||||
dt: f32,
|
||||
) -> &AnimationPose {
|
||||
) -> &AnimationPose<T> {
|
||||
self.final_pose.reset();
|
||||
|
||||
if self.active_state.is_some() || self.active_transition.is_some() {
|
||||
|
||||
@@ -1,26 +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::ErasedHandle, reflect::prelude::*, visitor::prelude::*};
|
||||
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<ErasedHandle>,
|
||||
pub struct LayerMask<T: EntityId> {
|
||||
excluded_bones: Vec<T>,
|
||||
}
|
||||
|
||||
impl From<Vec<ErasedHandle>> for LayerMask {
|
||||
fn from(mut excluded_bones: Vec<ErasedHandle>) -> Self {
|
||||
excluded_bones.sort_by_key(|h| h.index());
|
||||
impl<T: EntityId> From<Vec<T>> for LayerMask<T> {
|
||||
fn from(mut excluded_bones: Vec<T>) -> Self {
|
||||
excluded_bones.sort();
|
||||
Self { excluded_bones }
|
||||
}
|
||||
}
|
||||
|
||||
impl LayerMask {
|
||||
impl<T: EntityId> LayerMask<T> {
|
||||
/// 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<T>) {
|
||||
for handle in other.into_inner() {
|
||||
if !self.contains(handle) {
|
||||
self.add(handle);
|
||||
@@ -36,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: ErasedHandle) {
|
||||
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);
|
||||
}
|
||||
@@ -49,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: ErasedHandle) {
|
||||
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: ErasedHandle) -> Option<usize> {
|
||||
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<usize> {
|
||||
self.excluded_bones.binary_search(&id).ok()
|
||||
}
|
||||
|
||||
/// Checks if the mask contains a given node handle or not.
|
||||
@@ -88,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: ErasedHandle) -> bool {
|
||||
pub fn contains(&self, node: T) -> bool {
|
||||
self.index_of(node).is_some()
|
||||
}
|
||||
|
||||
@@ -98,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: ErasedHandle) -> 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<ErasedHandle> {
|
||||
pub fn inner(&self) -> &Vec<T> {
|
||||
&self.excluded_bones
|
||||
}
|
||||
|
||||
/// Converts the mask into inner container.
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> Vec<ErasedHandle> {
|
||||
pub fn into_inner(self) -> Vec<T> {
|
||||
self.excluded_bones
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
reflect::prelude::*,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
AnimationContainer, AnimationPose,
|
||||
AnimationContainer, AnimationPose, EntityId,
|
||||
};
|
||||
|
||||
pub use event::Event;
|
||||
@@ -167,18 +167,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<T: EntityId> {
|
||||
parameters: ParameterContainer,
|
||||
|
||||
#[visit(optional)]
|
||||
layers: Vec<MachineLayer>,
|
||||
layers: Vec<MachineLayer<T>>,
|
||||
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
final_pose: AnimationPose,
|
||||
final_pose: AnimationPose<T>,
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
impl<T: EntityId> Machine<T> {
|
||||
/// Creates a new animation blending state machine with a single animation layer.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
@@ -229,43 +229,46 @@ 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<T>) {
|
||||
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<T> {
|
||||
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<T>) {
|
||||
self.layers.insert(index, layer)
|
||||
}
|
||||
|
||||
/// Removes last layer from the list.
|
||||
#[inline]
|
||||
pub fn pop_layer(&mut self) -> Option<MachineLayer> {
|
||||
pub fn pop_layer(&mut self) -> Option<MachineLayer<T>> {
|
||||
self.layers.pop()
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the list of layers.
|
||||
#[inline]
|
||||
pub fn layers(&self) -> &[MachineLayer] {
|
||||
pub fn layers(&self) -> &[MachineLayer<T>] {
|
||||
&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<T>] {
|
||||
&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<S: AsRef<str>>(&self, name: S) -> Option<(usize, &MachineLayer)> {
|
||||
pub fn find_layer_by_name_ref<S: AsRef<str>>(
|
||||
&self,
|
||||
name: S,
|
||||
) -> Option<(usize, &MachineLayer<T>)> {
|
||||
find_by_name_ref(self.layers.iter().enumerate(), name)
|
||||
}
|
||||
|
||||
@@ -274,13 +277,13 @@ impl Machine {
|
||||
pub fn find_by_name_mut<S: AsRef<str>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
) -> Option<(usize, &mut MachineLayer)> {
|
||||
) -> Option<(usize, &mut MachineLayer<T>)> {
|
||||
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<T> {
|
||||
&self.final_pose
|
||||
}
|
||||
|
||||
@@ -288,9 +291,9 @@ impl Machine {
|
||||
#[inline]
|
||||
pub fn evaluate_pose(
|
||||
&mut self,
|
||||
animations: &mut AnimationContainer,
|
||||
animations: &mut AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) -> &AnimationPose {
|
||||
) -> &AnimationPose<T> {
|
||||
self.final_pose.reset();
|
||||
|
||||
for layer in self.layers.iter_mut() {
|
||||
|
||||
@@ -10,9 +10,10 @@ use crate::{
|
||||
node::AnimationEventCollectionStrategy, node::BasePoseNode, AnimationPoseSource, Parameter,
|
||||
ParameterContainer, PoseNode, PoseWeight,
|
||||
},
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose,
|
||||
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},
|
||||
@@ -22,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<T: EntityId> {
|
||||
/// Weight of the pose.
|
||||
pub weight: PoseWeight,
|
||||
|
||||
/// A source of animation pose.
|
||||
#[reflect(hidden)]
|
||||
pub pose_source: Handle<PoseNode>,
|
||||
pub pose_source: Handle<PoseNode<T>>,
|
||||
}
|
||||
|
||||
uuid_provider!(BlendPose = "b01d7639-7b39-4eaf-87e6-29fd5221951b");
|
||||
impl<T: EntityId> TypeUuidProvider for BlendPose<T> {
|
||||
fn type_uuid() -> Uuid {
|
||||
uuid!("b01d7639-7b39-4eaf-87e6-29fd5221951b")
|
||||
}
|
||||
}
|
||||
|
||||
impl BlendPose {
|
||||
impl<T: EntityId> BlendPose<T> {
|
||||
/// Creates new instance of blend pose with given weight and animation pose.
|
||||
pub fn new(weight: PoseWeight, pose_source: Handle<PoseNode>) -> Self {
|
||||
pub fn new(weight: PoseWeight, pose_source: Handle<PoseNode<T>>) -> Self {
|
||||
Self {
|
||||
weight,
|
||||
pose_source,
|
||||
@@ -44,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<PoseNode>) -> Self {
|
||||
pub fn with_constant_weight(weight: f32, pose_source: Handle<PoseNode<T>>) -> Self {
|
||||
Self {
|
||||
weight: PoseWeight::Constant(weight),
|
||||
pose_source,
|
||||
@@ -53,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<PoseNode>) -> Self {
|
||||
pub fn with_param_weight(param_id: &str, pose_source: Handle<PoseNode<T>>) -> Self {
|
||||
Self {
|
||||
weight: PoseWeight::Parameter(param_id.to_owned()),
|
||||
pose_source,
|
||||
@@ -69,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<T: EntityId> {
|
||||
/// Base node.
|
||||
pub base: BasePoseNode,
|
||||
pub base: BasePoseNode<T>,
|
||||
|
||||
/// A list of pose sources. See [`BlendPose`] docs for more info.
|
||||
pub pose_sources: Vec<BlendPose>,
|
||||
pub pose_sources: Vec<BlendPose<T>>,
|
||||
|
||||
/// Output pose of the node, contains final result of blending all input poses.
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
pub output_pose: RefCell<AnimationPose>,
|
||||
pub output_pose: RefCell<AnimationPose<T>>,
|
||||
}
|
||||
|
||||
impl Deref for BlendAnimations {
|
||||
type Target = BasePoseNode;
|
||||
impl<T: EntityId> Deref for BlendAnimations<T> {
|
||||
type Target = BasePoseNode<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for BlendAnimations {
|
||||
impl<T: EntityId> DerefMut for BlendAnimations<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl BlendAnimations {
|
||||
impl<T: EntityId> BlendAnimations<T> {
|
||||
/// Creates new animation blend node with given poses.
|
||||
pub fn new(poses: Vec<BlendPose>) -> Self {
|
||||
pub fn new(poses: Vec<BlendPose<T>>) -> Self {
|
||||
Self {
|
||||
base: Default::default(),
|
||||
pose_sources: poses,
|
||||
@@ -107,19 +112,19 @@ impl BlendAnimations {
|
||||
}
|
||||
|
||||
/// Returns a set of handles to children pose nodes.
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode>> {
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode<T>>> {
|
||||
self.pose_sources.iter().map(|s| s.pose_source).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimationPoseSource for BlendAnimations {
|
||||
impl<T: EntityId> AnimationPoseSource<T> for BlendAnimations<T> {
|
||||
fn eval_pose(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) -> Ref<AnimationPose> {
|
||||
) -> Ref<AnimationPose<T>> {
|
||||
self.output_pose.borrow_mut().reset();
|
||||
for blend_pose in self.pose_sources.iter() {
|
||||
let weight = match blend_pose.weight {
|
||||
@@ -145,17 +150,17 @@ impl AnimationPoseSource for BlendAnimations {
|
||||
self.output_pose.borrow()
|
||||
}
|
||||
|
||||
fn pose(&self) -> Ref<AnimationPose> {
|
||||
fn pose(&self) -> Ref<AnimationPose<T>> {
|
||||
self.output_pose.borrow()
|
||||
}
|
||||
|
||||
fn collect_animation_events(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
strategy: AnimationEventCollectionStrategy,
|
||||
) -> Vec<(Handle<Animation>, AnimationEvent)> {
|
||||
) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
|
||||
match strategy {
|
||||
AnimationEventCollectionStrategy::All => {
|
||||
let mut events = Vec::new();
|
||||
@@ -205,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<T: EntityId> {
|
||||
/// 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<PoseNode>,
|
||||
pub pose_source: Handle<PoseNode<T>>,
|
||||
}
|
||||
|
||||
uuid_provider!(IndexedBlendInput = "92fcc992-9a68-4152-8449-657546faa286");
|
||||
impl<T: EntityId> TypeUuidProvider for IndexedBlendInput<T> {
|
||||
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
|
||||
@@ -225,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<T: EntityId> {
|
||||
/// Base node.
|
||||
pub base: BasePoseNode,
|
||||
pub base: BasePoseNode<T>,
|
||||
|
||||
/// 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<IndexedBlendInput>,
|
||||
pub inputs: Vec<IndexedBlendInput<T>>,
|
||||
|
||||
/// Index of a previously active input pose.
|
||||
#[reflect(hidden)]
|
||||
@@ -246,26 +255,26 @@ pub struct BlendAnimationsByIndex {
|
||||
/// Output pose of the node.
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
pub output_pose: RefCell<AnimationPose>,
|
||||
pub output_pose: RefCell<AnimationPose<T>>,
|
||||
}
|
||||
|
||||
impl Deref for BlendAnimationsByIndex {
|
||||
type Target = BasePoseNode;
|
||||
impl<T: EntityId> Deref for BlendAnimationsByIndex<T> {
|
||||
type Target = BasePoseNode<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for BlendAnimationsByIndex {
|
||||
impl<T: EntityId> DerefMut for BlendAnimationsByIndex<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl BlendAnimationsByIndex {
|
||||
impl<T: EntityId> BlendAnimationsByIndex<T> {
|
||||
/// Creates new [`BlendAnimationsByIndex`] node using given index parameter name and a set of inputs.
|
||||
pub fn new(index_parameter: String, inputs: Vec<IndexedBlendInput>) -> Self {
|
||||
pub fn new(index_parameter: String, inputs: Vec<IndexedBlendInput<T>>) -> Self {
|
||||
Self {
|
||||
base: Default::default(),
|
||||
index_parameter,
|
||||
@@ -277,19 +286,19 @@ impl BlendAnimationsByIndex {
|
||||
}
|
||||
|
||||
/// Return a set of handle of children nodes.
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode>> {
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode<T>>> {
|
||||
self.inputs.iter().map(|s| s.pose_source).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimationPoseSource for BlendAnimationsByIndex {
|
||||
impl<T: EntityId> AnimationPoseSource<T> for BlendAnimationsByIndex<T> {
|
||||
fn eval_pose(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) -> Ref<AnimationPose> {
|
||||
) -> Ref<AnimationPose<T>> {
|
||||
self.output_pose.borrow_mut().reset();
|
||||
|
||||
if let Some(&Parameter::Index(current_index)) = params.get(&self.index_parameter) {
|
||||
@@ -343,17 +352,17 @@ impl AnimationPoseSource for BlendAnimationsByIndex {
|
||||
self.output_pose.borrow()
|
||||
}
|
||||
|
||||
fn pose(&self) -> Ref<AnimationPose> {
|
||||
fn pose(&self) -> Ref<AnimationPose<T>> {
|
||||
self.output_pose.borrow()
|
||||
}
|
||||
|
||||
fn collect_animation_events(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
strategy: AnimationEventCollectionStrategy,
|
||||
) -> Vec<(Handle<Animation>, AnimationEvent)> {
|
||||
) -> Vec<(Handle<Animation<T>>, 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 {
|
||||
|
||||
@@ -12,9 +12,10 @@ use crate::{
|
||||
node::AnimationEventCollectionStrategy, node::BasePoseNode, AnimationPoseSource, Parameter,
|
||||
ParameterContainer, PoseNode,
|
||||
},
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose,
|
||||
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::{
|
||||
@@ -23,18 +24,23 @@ use std::{
|
||||
};
|
||||
|
||||
#[derive(Debug, Visit, Clone, Reflect, PartialEq, Default)]
|
||||
pub struct BlendSpacePoint {
|
||||
pub struct BlendSpacePoint<T: EntityId> {
|
||||
pub position: Vector2<f32>,
|
||||
pub pose_source: Handle<PoseNode>,
|
||||
pub pose_source: Handle<PoseNode<T>>,
|
||||
}
|
||||
|
||||
impl<T: EntityId> TypeUuidProvider for BlendSpacePoint<T> {
|
||||
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<T: EntityId> {
|
||||
base: BasePoseNode<T>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
points: Vec<BlendSpacePoint>,
|
||||
points: Vec<BlendSpacePoint<T>>,
|
||||
|
||||
#[reflect(hidden)]
|
||||
triangles: Vec<TriangleDefinition>,
|
||||
@@ -59,10 +65,10 @@ pub struct BlendSpace {
|
||||
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
pose: RefCell<AnimationPose>,
|
||||
pose: RefCell<AnimationPose<T>>,
|
||||
}
|
||||
|
||||
impl Default for BlendSpace {
|
||||
impl<T: EntityId> Default for BlendSpace<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
base: Default::default(),
|
||||
@@ -79,28 +85,28 @@ impl Default for BlendSpace {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for BlendSpace {
|
||||
type Target = BasePoseNode;
|
||||
impl<T: EntityId> Deref for BlendSpace<T> {
|
||||
type Target = BasePoseNode<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for BlendSpace {
|
||||
impl<T: EntityId> DerefMut for BlendSpace<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimationPoseSource for BlendSpace {
|
||||
impl<T: EntityId> AnimationPoseSource<T> for BlendSpace<T> {
|
||||
fn eval_pose(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) -> Ref<AnimationPose> {
|
||||
) -> Ref<AnimationPose<T>> {
|
||||
let mut pose = self.pose.borrow_mut();
|
||||
|
||||
pose.reset();
|
||||
@@ -129,17 +135,17 @@ impl AnimationPoseSource for BlendSpace {
|
||||
self.pose.borrow()
|
||||
}
|
||||
|
||||
fn pose(&self) -> Ref<AnimationPose> {
|
||||
fn pose(&self) -> Ref<AnimationPose<T>> {
|
||||
self.pose.borrow()
|
||||
}
|
||||
|
||||
fn collect_animation_events(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
strategy: AnimationEventCollectionStrategy,
|
||||
) -> Vec<(Handle<Animation>, AnimationEvent)> {
|
||||
) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
|
||||
if let Some(Parameter::SamplingPoint(sampling_point)) = params.get(&self.sampling_parameter)
|
||||
{
|
||||
if let Some(weights) = self.fetch_weights(*sampling_point) {
|
||||
@@ -197,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<T>,
|
||||
}
|
||||
|
||||
impl<'a> Deref for PointsMut<'a> {
|
||||
type Target = Vec<BlendSpacePoint>;
|
||||
impl<'a, T: EntityId> Deref for PointsMut<'a, T> {
|
||||
type Target = Vec<BlendSpacePoint<T>>;
|
||||
|
||||
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<T: EntityId> BlendSpace<T> {
|
||||
pub fn add_point(&mut self, point: BlendSpacePoint<T>) -> bool {
|
||||
self.points.push(point);
|
||||
self.triangulate()
|
||||
}
|
||||
|
||||
/// Sets new points to the blend space.
|
||||
pub fn set_points(&mut self, points: Vec<BlendSpacePoint>) -> bool {
|
||||
pub fn set_points(&mut self, points: Vec<BlendSpacePoint<T>>) -> bool {
|
||||
self.points = points;
|
||||
self.triangulate()
|
||||
}
|
||||
@@ -238,11 +244,11 @@ impl BlendSpace {
|
||||
self.triangles.clear();
|
||||
}
|
||||
|
||||
pub fn points(&self) -> &[BlendSpacePoint] {
|
||||
pub fn points(&self) -> &[BlendSpacePoint<T>] {
|
||||
&self.points
|
||||
}
|
||||
|
||||
pub fn points_mut(&mut self) -> PointsMut {
|
||||
pub fn points_mut(&mut self) -> PointsMut<T> {
|
||||
PointsMut { blend_space: self }
|
||||
}
|
||||
|
||||
@@ -250,7 +256,7 @@ impl BlendSpace {
|
||||
&self.triangles
|
||||
}
|
||||
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode>> {
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode<T>>> {
|
||||
self.points.iter().map(|p| p.pose_source).collect()
|
||||
}
|
||||
|
||||
@@ -429,10 +435,11 @@ mod test {
|
||||
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::<ErasedHandle>::default();
|
||||
|
||||
blend_space.set_points(vec![
|
||||
BlendSpacePoint {
|
||||
@@ -463,14 +470,14 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_empty_blend_space_sampling() {
|
||||
assert!(BlendSpace::default()
|
||||
assert!(BlendSpace::<ErasedHandle>::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::<ErasedHandle>::default();
|
||||
|
||||
blend_space.set_points(vec![BlendSpacePoint {
|
||||
position: Vector2::new(0.0, 0.0),
|
||||
@@ -485,7 +492,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_two_points_blend_space_sampling() {
|
||||
let mut blend_space = BlendSpace::default();
|
||||
let mut blend_space = BlendSpace::<ErasedHandle>::default();
|
||||
|
||||
blend_space.set_points(vec![
|
||||
BlendSpacePoint {
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation},
|
||||
BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State,
|
||||
},
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose,
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId,
|
||||
};
|
||||
use std::{
|
||||
cell::Ref,
|
||||
@@ -25,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<T: EntityId> {
|
||||
/// Position on the canvas, it is editor-specific data.
|
||||
pub position: Vector2<f32>,
|
||||
|
||||
/// A handle of parent state that "owns" the node.
|
||||
#[reflect(hidden)]
|
||||
pub parent_state: Handle<State>,
|
||||
pub parent_state: Handle<State<T>>,
|
||||
}
|
||||
|
||||
/// Specialized node that provides animation pose. See documentation for each variant.
|
||||
#[derive(Debug, Visit, Clone, Reflect, PartialEq)]
|
||||
pub enum PoseNode {
|
||||
pub enum PoseNode<T: EntityId> {
|
||||
/// See docs for [`PlayAnimation`].
|
||||
PlayAnimation(PlayAnimation),
|
||||
PlayAnimation(PlayAnimation<T>),
|
||||
|
||||
/// See docs for [`BlendAnimations`].
|
||||
BlendAnimations(BlendAnimations),
|
||||
BlendAnimations(BlendAnimations<T>),
|
||||
|
||||
/// See docs for [`BlendAnimationsByIndex`].
|
||||
BlendAnimationsByIndex(BlendAnimationsByIndex),
|
||||
BlendAnimationsByIndex(BlendAnimationsByIndex<T>),
|
||||
|
||||
/// See doc for [`BlendSpace`]
|
||||
BlendSpace(BlendSpace),
|
||||
BlendSpace(BlendSpace<T>),
|
||||
}
|
||||
|
||||
impl Default for PoseNode {
|
||||
impl<T: EntityId> Default for PoseNode<T> {
|
||||
fn default() -> Self {
|
||||
Self::PlayAnimation(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl PoseNode {
|
||||
impl<T: EntityId> PoseNode<T> {
|
||||
/// Creates new node that plays an animation.
|
||||
pub fn make_play_animation(animation: Handle<Animation>) -> Self {
|
||||
pub fn make_play_animation(animation: Handle<Animation<T>>) -> Self {
|
||||
Self::PlayAnimation(PlayAnimation::new(animation))
|
||||
}
|
||||
|
||||
/// Creates new node that blends multiple poses into one.
|
||||
pub fn make_blend_animations(poses: Vec<BlendPose>) -> Self {
|
||||
pub fn make_blend_animations(poses: Vec<BlendPose<T>>) -> Self {
|
||||
Self::BlendAnimations(BlendAnimations::new(poses))
|
||||
}
|
||||
|
||||
@@ -71,13 +71,13 @@ impl PoseNode {
|
||||
/// one animation to another while switching.
|
||||
pub fn make_blend_animations_by_index(
|
||||
index_parameter: String,
|
||||
inputs: Vec<IndexedBlendInput>,
|
||||
inputs: Vec<IndexedBlendInput<T>>,
|
||||
) -> Self {
|
||||
Self::BlendAnimationsByIndex(BlendAnimationsByIndex::new(index_parameter, inputs))
|
||||
}
|
||||
|
||||
/// Returns a set of handles to children pose nodes.
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode>> {
|
||||
pub fn children(&self) -> Vec<Handle<PoseNode<T>>> {
|
||||
match self {
|
||||
Self::PlayAnimation(_) => {
|
||||
// No children nodes.
|
||||
@@ -101,15 +101,15 @@ macro_rules! static_dispatch {
|
||||
};
|
||||
}
|
||||
|
||||
impl Deref for PoseNode {
|
||||
type Target = BasePoseNode;
|
||||
impl<T: EntityId> Deref for PoseNode<T> {
|
||||
type Target = BasePoseNode<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
static_dispatch!(self, deref,)
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PoseNode {
|
||||
impl<T: EntityId> DerefMut for PoseNode<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
static_dispatch!(self, deref_mut,)
|
||||
}
|
||||
@@ -127,51 +127,51 @@ pub enum AnimationEventCollectionStrategy {
|
||||
}
|
||||
|
||||
/// A trait that responsible for animation pose evaluation.
|
||||
pub trait AnimationPoseSource {
|
||||
pub trait AnimationPoseSource<T: EntityId> {
|
||||
/// Evaluates animation pose and returns a reference to it.
|
||||
fn eval_pose(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) -> Ref<AnimationPose>;
|
||||
) -> Ref<AnimationPose<T>>;
|
||||
|
||||
/// Returns a reference to inner pose of a node.
|
||||
fn pose(&self) -> Ref<AnimationPose>;
|
||||
fn pose(&self) -> Ref<AnimationPose<T>>;
|
||||
|
||||
/// Collects animation events from internals.
|
||||
fn collect_animation_events(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
strategy: AnimationEventCollectionStrategy,
|
||||
) -> Vec<(Handle<Animation>, AnimationEvent)>;
|
||||
) -> Vec<(Handle<Animation<T>>, AnimationEvent)>;
|
||||
}
|
||||
|
||||
impl AnimationPoseSource for PoseNode {
|
||||
impl<T: EntityId> AnimationPoseSource<T> for PoseNode<T> {
|
||||
fn eval_pose(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) -> Ref<AnimationPose> {
|
||||
) -> Ref<AnimationPose<T>> {
|
||||
static_dispatch!(self, eval_pose, nodes, params, animations, dt)
|
||||
}
|
||||
|
||||
fn pose(&self) -> Ref<AnimationPose> {
|
||||
fn pose(&self) -> Ref<AnimationPose<T>> {
|
||||
static_dispatch!(self, pose,)
|
||||
}
|
||||
|
||||
fn collect_animation_events(
|
||||
&self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
strategy: AnimationEventCollectionStrategy,
|
||||
) -> Vec<(Handle<Animation>, AnimationEvent)> {
|
||||
) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
|
||||
static_dispatch!(
|
||||
self,
|
||||
collect_animation_events,
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
node::{AnimationPoseSource, BasePoseNode},
|
||||
ParameterContainer, PoseNode,
|
||||
},
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose,
|
||||
Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId,
|
||||
};
|
||||
use std::{
|
||||
cell::{Ref, RefCell},
|
||||
@@ -22,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<T: EntityId> {
|
||||
/// Base node.
|
||||
pub base: BasePoseNode,
|
||||
pub base: BasePoseNode<T>,
|
||||
|
||||
/// A handle to animation.
|
||||
pub animation: Handle<Animation>,
|
||||
pub animation: Handle<Animation<T>>,
|
||||
|
||||
/// Output pose, it contains a filtered (see [`crate::animation::machine::LayerMask`] for more info) pose from
|
||||
/// the animation specified by the `animation` field.
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
pub output_pose: RefCell<AnimationPose>,
|
||||
pub output_pose: RefCell<AnimationPose<T>>,
|
||||
}
|
||||
|
||||
impl Deref for PlayAnimation {
|
||||
type Target = BasePoseNode;
|
||||
impl<T: EntityId> Deref for PlayAnimation<T> {
|
||||
type Target = BasePoseNode<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PlayAnimation {
|
||||
impl<T: EntityId> DerefMut for PlayAnimation<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayAnimation {
|
||||
impl<T: EntityId> PlayAnimation<T> {
|
||||
/// Creates new PlayAnimation node with given animation handle.
|
||||
pub fn new(animation: Handle<Animation>) -> Self {
|
||||
pub fn new(animation: Handle<Animation<T>>) -> Self {
|
||||
Self {
|
||||
base: Default::default(),
|
||||
animation,
|
||||
@@ -61,14 +61,14 @@ impl PlayAnimation {
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimationPoseSource for PlayAnimation {
|
||||
impl<T: EntityId> AnimationPoseSource<T> for PlayAnimation<T> {
|
||||
fn eval_pose(
|
||||
&self,
|
||||
_nodes: &Pool<PoseNode>,
|
||||
_nodes: &Pool<PoseNode<T>>,
|
||||
_params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
_dt: f32,
|
||||
) -> Ref<AnimationPose> {
|
||||
) -> Ref<AnimationPose<T>> {
|
||||
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);
|
||||
@@ -78,17 +78,17 @@ impl AnimationPoseSource for PlayAnimation {
|
||||
self.output_pose.borrow()
|
||||
}
|
||||
|
||||
fn pose(&self) -> Ref<AnimationPose> {
|
||||
fn pose(&self) -> Ref<AnimationPose<T>> {
|
||||
self.output_pose.borrow()
|
||||
}
|
||||
|
||||
fn collect_animation_events(
|
||||
&self,
|
||||
_nodes: &Pool<PoseNode>,
|
||||
_nodes: &Pool<PoseNode<T>>,
|
||||
_params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
_strategy: AnimationEventCollectionStrategy,
|
||||
) -> Vec<(Handle<Animation>, AnimationEvent)> {
|
||||
) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
|
||||
animations
|
||||
.try_get(self.animation)
|
||||
.map(|a| {
|
||||
|
||||
@@ -9,9 +9,10 @@ use crate::{
|
||||
visitor::prelude::*,
|
||||
},
|
||||
machine::{AnimationPoseSource, ParameterContainer, PoseNode},
|
||||
Animation, AnimationContainer, AnimationPose,
|
||||
Animation, AnimationContainer, AnimationPose, EntityId,
|
||||
};
|
||||
use fyrox_core::{uuid_provider, NameProvider};
|
||||
use fyrox_core::uuid::{uuid, Uuid};
|
||||
use fyrox_core::{NameProvider, TypeUuidProvider};
|
||||
use std::{
|
||||
cell::Ref,
|
||||
ops::{Deref, DerefMut},
|
||||
@@ -20,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<T: EntityId>(pub StateAction<T>);
|
||||
|
||||
uuid_provider!(StateActionWrapper = "d686fac8-5cc1-46b1-82a4-7f4438cc078d");
|
||||
impl<T: EntityId> TypeUuidProvider for StateActionWrapper<T> {
|
||||
fn type_uuid() -> Uuid {
|
||||
uuid!("d686fac8-5cc1-46b1-82a4-7f4438cc078d")
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for StateActionWrapper {
|
||||
type Target = StateAction;
|
||||
impl<T: EntityId> Deref for StateActionWrapper<T> {
|
||||
type Target = StateAction<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for StateActionWrapper {
|
||||
impl<T: EntityId> DerefMut for StateActionWrapper<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
@@ -47,28 +52,32 @@ impl DerefMut for StateActionWrapper {
|
||||
#[derive(
|
||||
Default, Debug, Visit, Reflect, Clone, PartialEq, EnumVariantNames, EnumString, AsRefStr,
|
||||
)]
|
||||
pub enum StateAction {
|
||||
pub enum StateAction<T: EntityId> {
|
||||
/// No action.
|
||||
#[default]
|
||||
None,
|
||||
/// Rewinds the animation.
|
||||
RewindAnimation(Handle<Animation>),
|
||||
RewindAnimation(Handle<Animation<T>>),
|
||||
/// Enables the animation.
|
||||
EnableAnimation(Handle<Animation>),
|
||||
EnableAnimation(Handle<Animation<T>>),
|
||||
/// Disables the animation.
|
||||
DisableAnimation(Handle<Animation>),
|
||||
DisableAnimation(Handle<Animation<T>>),
|
||||
/// 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<Handle<Animation>>),
|
||||
EnableRandomAnimation(Vec<Handle<Animation<T>>>),
|
||||
}
|
||||
|
||||
uuid_provider!(StateAction = "c50a15cc-0f63-4409-bbe0-74b9d3e94755");
|
||||
impl<T: EntityId> TypeUuidProvider for StateAction<T> {
|
||||
fn type_uuid() -> Uuid {
|
||||
uuid!("c50a15cc-0f63-4409-bbe0-74b9d3e94755")
|
||||
}
|
||||
}
|
||||
|
||||
impl StateAction {
|
||||
impl<T: EntityId> StateAction<T> {
|
||||
/// Applies the action to the given animation container.
|
||||
pub fn apply(&self, animations: &mut AnimationContainer) {
|
||||
pub fn apply(&self, animations: &mut AnimationContainer<T>) {
|
||||
match self {
|
||||
StateAction::None => {}
|
||||
StateAction::RewindAnimation(animation) => {
|
||||
@@ -100,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<T: EntityId> {
|
||||
/// Position of state on the canvas. It is editor-specific data.
|
||||
pub position: Vector2<f32>,
|
||||
|
||||
@@ -109,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<StateActionWrapper>,
|
||||
pub on_enter_actions: Vec<StateActionWrapper<T>>,
|
||||
|
||||
/// A set of actions that will be executed when leaving the state.
|
||||
#[visit(optional)]
|
||||
pub on_leave_actions: Vec<StateActionWrapper>,
|
||||
pub on_leave_actions: Vec<StateActionWrapper<T>>,
|
||||
|
||||
/// Root node of the state that provides the state with animation data.
|
||||
#[reflect(read_only)]
|
||||
pub root: Handle<PoseNode>,
|
||||
pub root: Handle<PoseNode<T>>,
|
||||
}
|
||||
|
||||
impl NameProvider for State {
|
||||
impl<T: EntityId> NameProvider for State<T> {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
impl<T: EntityId> State<T> {
|
||||
/// Creates new instance of state with a given pose.
|
||||
pub fn new(name: &str, root: Handle<PoseNode>) -> Self {
|
||||
pub fn new(name: &str, root: Handle<PoseNode<T>>) -> Self {
|
||||
Self {
|
||||
position: Default::default(),
|
||||
name: name.to_owned(),
|
||||
@@ -139,15 +148,15 @@ impl State {
|
||||
}
|
||||
|
||||
/// Returns a final pose of the state.
|
||||
pub fn pose<'a>(&self, nodes: &'a Pool<PoseNode>) -> Option<Ref<'a, AnimationPose>> {
|
||||
pub fn pose<'a>(&self, nodes: &'a Pool<PoseNode<T>>) -> Option<Ref<'a, AnimationPose<T>>> {
|
||||
nodes.try_borrow(self.root).map(|root| root.pose())
|
||||
}
|
||||
|
||||
pub(super) fn update(
|
||||
&mut self,
|
||||
nodes: &Pool<PoseNode>,
|
||||
nodes: &Pool<PoseNode<T>>,
|
||||
params: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
dt: f32,
|
||||
) {
|
||||
if let Some(root) = nodes.try_borrow(self.root) {
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
use crate::{
|
||||
core::{pool::Handle, reflect::prelude::*, visitor::prelude::*},
|
||||
machine::{Parameter, ParameterContainer, State},
|
||||
Animation, AnimationContainer,
|
||||
Animation, AnimationContainer, EntityId,
|
||||
};
|
||||
use fyrox_core::{uuid_provider, NameProvider};
|
||||
use fyrox_core::uuid::{uuid, Uuid};
|
||||
use fyrox_core::{NameProvider, TypeUuidProvider};
|
||||
use std::any::{type_name, Any, TypeId};
|
||||
use strum_macros::{AsRefStr, EnumString, EnumVariantNames};
|
||||
|
||||
@@ -13,14 +14,14 @@ macro_rules! define_two_args_node {
|
||||
($(#[$meta:meta])* $name:ident) => {
|
||||
$(#[$meta])*
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct $name {
|
||||
pub struct $name <T:EntityId> {
|
||||
/// Left argument.
|
||||
pub lhs: Box<LogicNode>,
|
||||
pub lhs: Box<LogicNode<T>>,
|
||||
/// Right argument.
|
||||
pub rhs: Box<LogicNode>,
|
||||
pub rhs: Box<LogicNode<T>>,
|
||||
}
|
||||
|
||||
impl Default for $name {
|
||||
impl<T:EntityId> Default for $name<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lhs: Box::new(LogicNode::Parameter(Default::default())),
|
||||
@@ -29,7 +30,7 @@ macro_rules! define_two_args_node {
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for $name {
|
||||
impl<T:EntityId> Visit for $name<T> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut guard = visitor.enter_region(name)?;
|
||||
|
||||
@@ -40,7 +41,7 @@ macro_rules! define_two_args_node {
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflect for $name {
|
||||
impl<T:EntityId> Reflect for $name<T> {
|
||||
fn type_name(&self) -> &'static str {
|
||||
type_name::<Self>()
|
||||
}
|
||||
@@ -159,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<T: EntityId> {
|
||||
/// Argument to be negated.
|
||||
pub lhs: Box<LogicNode>,
|
||||
pub lhs: Box<LogicNode<T>>,
|
||||
}
|
||||
|
||||
impl Default for NotNode {
|
||||
impl<T: EntityId> Default for NotNode<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lhs: Box::new(LogicNode::Parameter(Default::default())),
|
||||
@@ -172,7 +173,7 @@ impl Default for NotNode {
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for NotNode {
|
||||
impl<T: EntityId> Visit for NotNode<T> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut guard = visitor.enter_region(name)?;
|
||||
|
||||
@@ -182,7 +183,7 @@ impl Visit for NotNode {
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflect for NotNode {
|
||||
impl<T: EntityId> Reflect for NotNode<T> {
|
||||
fn type_name(&self) -> &'static str {
|
||||
type_name::<Self>()
|
||||
}
|
||||
@@ -284,35 +285,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<T: EntityId> {
|
||||
/// 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<T>),
|
||||
/// Calculates logical OR between two arguments. Output value will be `true` iff any of the arguments is `true`.
|
||||
Or(OrNode),
|
||||
Or(OrNode<T>),
|
||||
/// Calculates logical XOR (excluding OR) between two arguments. Output value will be `true` iff the arguments differ.
|
||||
Xor(XorNode),
|
||||
Xor(XorNode<T>),
|
||||
/// Calculates logical NOT of an argument. Output value will be `true` if the value of the argument is `false`.
|
||||
Not(NotNode),
|
||||
Not(NotNode<T>),
|
||||
/// Returns `true` if the animation has ended, `false` - otherwise.
|
||||
IsAnimationEnded(Handle<Animation>),
|
||||
IsAnimationEnded(Handle<Animation<T>>),
|
||||
}
|
||||
|
||||
uuid_provider!(LogicNode = "98a5b767-5560-4ed7-ad40-1625a8868e39");
|
||||
impl<T: EntityId> TypeUuidProvider for LogicNode<T> {
|
||||
fn type_uuid() -> Uuid {
|
||||
uuid!("98a5b767-5560-4ed7-ad40-1625a8868e39")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LogicNode {
|
||||
impl<T: EntityId> Default for LogicNode<T> {
|
||||
fn default() -> Self {
|
||||
Self::Parameter(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl LogicNode {
|
||||
impl<T: EntityId> LogicNode<T> {
|
||||
/// Calculates final value of the logic node.
|
||||
pub fn calculate_value(
|
||||
&self,
|
||||
parameters: &ParameterContainer,
|
||||
animations: &AnimationContainer,
|
||||
animations: &AnimationContainer<T>,
|
||||
) -> bool {
|
||||
match self {
|
||||
LogicNode::Parameter(rule_name) => parameters.get(rule_name).map_or(false, |p| {
|
||||
@@ -347,7 +352,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<T: EntityId> {
|
||||
/// 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,
|
||||
@@ -360,21 +365,21 @@ pub struct Transition {
|
||||
pub(crate) elapsed_time: f32,
|
||||
|
||||
#[reflect(read_only)]
|
||||
pub(crate) source: Handle<State>,
|
||||
pub(crate) source: Handle<State<T>>,
|
||||
|
||||
#[reflect(read_only)]
|
||||
pub(crate) dest: Handle<State>,
|
||||
pub(crate) dest: Handle<State<T>>,
|
||||
|
||||
#[reflect(
|
||||
description = "Computational graph that can use any amount of Rule parameters to calculate transition value."
|
||||
)]
|
||||
pub(crate) condition: LogicNode,
|
||||
pub(crate) condition: LogicNode<T>,
|
||||
|
||||
/// 0 - evaluates `src` pose, 1 - `dest`, 0..1 - blends `src` and `dest`
|
||||
pub(crate) blend_factor: f32,
|
||||
}
|
||||
|
||||
impl Visit for Transition {
|
||||
impl<T: EntityId> Visit for Transition<T> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut guard = visitor.enter_region(name)?;
|
||||
|
||||
@@ -409,22 +414,22 @@ impl Visit for Transition {
|
||||
}
|
||||
}
|
||||
|
||||
impl NameProvider for Transition {
|
||||
impl<T: EntityId> NameProvider for Transition<T> {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl Transition {
|
||||
impl<T: EntityId> Transition<T> {
|
||||
/// 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<State>,
|
||||
dest: Handle<State>,
|
||||
src: Handle<State<T>>,
|
||||
dest: Handle<State<T>>,
|
||||
time: f32,
|
||||
rule: &str,
|
||||
) -> Transition {
|
||||
) -> Transition<T> {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
transition_time: time,
|
||||
@@ -450,23 +455,23 @@ impl Transition {
|
||||
|
||||
/// Returns a handle to source state.
|
||||
#[inline]
|
||||
pub fn source(&self) -> Handle<State> {
|
||||
pub fn source(&self) -> Handle<State<T>> {
|
||||
self.source
|
||||
}
|
||||
|
||||
/// Returns a handle to destination state.
|
||||
#[inline]
|
||||
pub fn dest(&self) -> Handle<State> {
|
||||
pub fn dest(&self) -> Handle<State<T>> {
|
||||
self.dest
|
||||
}
|
||||
|
||||
/// Sets new condition for the transition.
|
||||
pub fn set_condition(&mut self, condition: LogicNode) {
|
||||
pub fn set_condition(&mut self, condition: LogicNode<T>) {
|
||||
self.condition = condition;
|
||||
}
|
||||
|
||||
/// Returns a reference to the current condition of the transition.
|
||||
pub fn condition(&self) -> &LogicNode {
|
||||
pub fn condition(&self) -> &LogicNode<T> {
|
||||
&self.condition
|
||||
}
|
||||
|
||||
|
||||
+14
-15
@@ -1,39 +1,38 @@
|
||||
//! Pose is a set of property values of a node ([`NodePose`]) or a set of nodes ([`AnimationPose`]).
|
||||
|
||||
use crate::{value::BoundValue, value::BoundValueCollection, RootMotion};
|
||||
use crate::{value::BoundValue, value::BoundValueCollection, EntityId, RootMotion};
|
||||
use fxhash::FxHashMap;
|
||||
use fyrox_core::pool::ErasedHandle;
|
||||
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, Default)]
|
||||
pub struct NodePose {
|
||||
pub struct NodePose<T: EntityId> {
|
||||
/// A handle of an animated node.
|
||||
pub node: ErasedHandle,
|
||||
pub node: T,
|
||||
|
||||
/// A set of property values.
|
||||
pub values: BoundValueCollection,
|
||||
}
|
||||
|
||||
impl NodePose {
|
||||
impl<T: EntityId> NodePose<T> {
|
||||
/// 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<T>, 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<ErasedHandle, NodePose>,
|
||||
pub struct AnimationPose<T: EntityId> {
|
||||
poses: FxHashMap<T, NodePose<T>>,
|
||||
root_motion: Option<RootMotion>,
|
||||
}
|
||||
|
||||
impl AnimationPose {
|
||||
impl<T: EntityId> AnimationPose<T> {
|
||||
/// 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<T>) {
|
||||
dest.reset();
|
||||
for (handle, local_pose) in self.poses.iter() {
|
||||
dest.poses.insert(*handle, local_pose.clone());
|
||||
@@ -54,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<T>, 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);
|
||||
@@ -68,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<T>) {
|
||||
self.poses.insert(local_pose.node, local_pose);
|
||||
}
|
||||
|
||||
pub(super) fn add_to_node_pose(&mut self, node: ErasedHandle, 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);
|
||||
@@ -94,12 +93,12 @@ impl AnimationPose {
|
||||
}
|
||||
|
||||
/// Returns a reference to inner node pose map.
|
||||
pub fn poses(&self) -> &FxHashMap<ErasedHandle, NodePose> {
|
||||
pub fn poses(&self) -> &FxHashMap<T, NodePose<T>> {
|
||||
&self.poses
|
||||
}
|
||||
|
||||
/// Returns a reference to inner node pose map.
|
||||
pub fn poses_mut(&mut self) -> &mut FxHashMap<ErasedHandle, NodePose> {
|
||||
pub fn poses_mut(&mut self) -> &mut FxHashMap<T, NodePose<T>> {
|
||||
&mut self.poses
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,23 +4,23 @@ use crate::{
|
||||
container::{TrackDataContainer, TrackValueKind},
|
||||
core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
|
||||
value::{BoundValue, ValueBinding},
|
||||
EntityId,
|
||||
};
|
||||
use fyrox_core::pool::ErasedHandle;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Track is responsible in animating a property of a single scene node. The track consists up to 4 parametric curves
|
||||
/// 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<T: EntityId> {
|
||||
binding: ValueBinding,
|
||||
frames: TrackDataContainer,
|
||||
enabled: bool,
|
||||
target: ErasedHandle,
|
||||
target: T,
|
||||
id: Uuid,
|
||||
}
|
||||
|
||||
impl Visit for Track {
|
||||
impl<T: EntityId> Visit for Track<T> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
@@ -35,7 +35,7 @@ impl Visit for Track {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Track {
|
||||
impl<T: EntityId> Default for Track<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
binding: ValueBinding::Position,
|
||||
@@ -47,7 +47,7 @@ impl Default for Track {
|
||||
}
|
||||
}
|
||||
|
||||
impl Track {
|
||||
impl<T: EntityId> Track<T> {
|
||||
/// 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 {
|
||||
@@ -86,7 +86,7 @@ impl Track {
|
||||
}
|
||||
|
||||
/// Sets target of the track.
|
||||
pub fn with_target(mut self, target: ErasedHandle) -> Self {
|
||||
pub fn with_target(mut self, target: T) -> Self {
|
||||
self.target = target;
|
||||
self
|
||||
}
|
||||
@@ -102,12 +102,12 @@ impl Track {
|
||||
}
|
||||
|
||||
/// Sets a handle of a node that will be animated.
|
||||
pub fn set_target<H: Into<ErasedHandle>>(&mut self, target: H) {
|
||||
self.target = target.into();
|
||||
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) -> ErasedHandle {
|
||||
pub fn target(&self) -> T {
|
||||
self.target
|
||||
}
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ async fn convert_model(
|
||||
model: &FbxModel,
|
||||
resource_manager: ResourceManager,
|
||||
graph: &mut Graph,
|
||||
animation: &mut Animation,
|
||||
animation: &mut Animation<Handle<Node>>,
|
||||
model_path: &Path,
|
||||
model_import_options: &ModelImportOptions,
|
||||
) -> Result<Handle<Node>, FbxError> {
|
||||
@@ -682,7 +682,7 @@ async fn convert_model(
|
||||
}
|
||||
|
||||
fn fill_track<F: Fn(f32) -> f32>(
|
||||
track: &mut Track,
|
||||
track: &mut Track<Handle<Node>>,
|
||||
fbx_scene: &FbxScene,
|
||||
fbx_track: &FbxAnimationCurveNode,
|
||||
default: Vector3<f32>,
|
||||
@@ -730,7 +730,7 @@ async fn convert_model(
|
||||
}
|
||||
}
|
||||
|
||||
fn add_vec3_key(track: &mut Track, value: Vector3<f32>) {
|
||||
fn add_vec3_key(track: &mut Track<Handle<Node>>, value: Vector3<f32>) {
|
||||
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));
|
||||
|
||||
+24
-10
@@ -42,7 +42,6 @@ use crate::{
|
||||
Scene, SceneLoader,
|
||||
},
|
||||
};
|
||||
use fyrox_core::pool::ErasedHandle;
|
||||
use fyrox_core::uuid_provider;
|
||||
use fyrox_resource::io::ResourceIo;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -124,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<Node>, graph: &Graph) -> Vec<Animation>;
|
||||
fn retarget_animations_directly(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
graph: &Graph,
|
||||
) -> Vec<Animation<Handle<Node>>>;
|
||||
|
||||
/// 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
|
||||
@@ -139,7 +142,7 @@ pub trait ModelResourceExtension: Sized {
|
||||
root: Handle<Node>,
|
||||
dest_animation_player: Handle<Node>,
|
||||
graph: &mut Graph,
|
||||
) -> Vec<Handle<Animation>>;
|
||||
) -> Vec<Handle<Animation<Handle<Node>>>>;
|
||||
|
||||
/// 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
|
||||
@@ -148,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<Node>, graph: &mut Graph) -> Vec<Handle<Animation>>;
|
||||
fn retarget_animations(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
graph: &mut Graph,
|
||||
) -> Vec<Handle<Animation<Handle<Node>>>>;
|
||||
}
|
||||
|
||||
impl ModelResourceExtension for ModelResource {
|
||||
@@ -209,7 +216,11 @@ impl ModelResourceExtension for ModelResource {
|
||||
root
|
||||
}
|
||||
|
||||
fn retarget_animations_directly(&self, root: Handle<Node>, graph: &Graph) -> Vec<Animation> {
|
||||
fn retarget_animations_directly(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
graph: &Graph,
|
||||
) -> Vec<Animation<Handle<Node>>> {
|
||||
let mut retargetted_animations = Vec::new();
|
||||
|
||||
let mut header = self.state();
|
||||
@@ -224,8 +235,7 @@ impl ModelResourceExtension for ModelResource {
|
||||
// because we've made a plain copy and it has tracks with node handles mapped
|
||||
// to nodes of internal scene.
|
||||
for (i, ref_track) in src_anim.tracks().iter().enumerate() {
|
||||
let ref_node =
|
||||
&model.scene.graph[Handle::<Node>::from(ref_track.target())];
|
||||
let ref_node = &model.scene.graph[ref_track.target()];
|
||||
let track = &mut anim_copy.tracks_mut()[i];
|
||||
// Find instantiated node that corresponds to node in resource
|
||||
match graph.find_by_name(root, ref_node.name()) {
|
||||
@@ -234,7 +244,7 @@ impl ModelResourceExtension for ModelResource {
|
||||
track.set_target(instance_node);
|
||||
}
|
||||
None => {
|
||||
track.set_target(ErasedHandle::default());
|
||||
track.set_target(Default::default());
|
||||
Log::writeln(
|
||||
MessageKind::Error,
|
||||
format!(
|
||||
@@ -261,7 +271,7 @@ impl ModelResourceExtension for ModelResource {
|
||||
root: Handle<Node>,
|
||||
dest_animation_player: Handle<Node>,
|
||||
graph: &mut Graph,
|
||||
) -> Vec<Handle<Animation>> {
|
||||
) -> Vec<Handle<Animation<Handle<Node>>>> {
|
||||
let mut animation_handles = Vec::new();
|
||||
|
||||
let animations = self.retarget_animations_directly(root, graph);
|
||||
@@ -277,7 +287,11 @@ impl ModelResourceExtension for ModelResource {
|
||||
animation_handles
|
||||
}
|
||||
|
||||
fn retarget_animations(&self, root: Handle<Node>, graph: &mut Graph) -> Vec<Handle<Animation>> {
|
||||
fn retarget_animations(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
graph: &mut Graph,
|
||||
) -> Vec<Handle<Animation<Handle<Node>>>> {
|
||||
if let Some((animation_player, _)) = graph.find(root, &mut |n| {
|
||||
n.query_component_ref::<AnimationPlayer>().is_some()
|
||||
}) {
|
||||
|
||||
@@ -106,23 +106,23 @@ use std::ops::{Deref, DerefMut};
|
||||
#[derive(Visit, Reflect, Clone, Debug, Default)]
|
||||
pub struct AnimationBlendingStateMachine {
|
||||
base: Base,
|
||||
machine: InheritableVariable<Machine>,
|
||||
machine: InheritableVariable<Machine<Handle<Node>>>,
|
||||
animation_player: InheritableVariable<Handle<Node>>,
|
||||
}
|
||||
|
||||
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<Handle<Node>>) {
|
||||
self.machine.set_value_and_mark_modified(machine);
|
||||
}
|
||||
|
||||
/// Returns a reference to the state machine used by the node.
|
||||
pub fn machine(&self) -> &InheritableVariable<Machine> {
|
||||
pub fn machine(&self) -> &InheritableVariable<Machine<Handle<Node>>> {
|
||||
&self.machine
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the state machine used by the node.
|
||||
pub fn machine_mut(&mut self) -> &mut InheritableVariable<Machine> {
|
||||
pub fn machine_mut(&mut self) -> &mut InheritableVariable<Machine<Handle<Node>>> {
|
||||
&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<Handle<Node>>,
|
||||
animation_player: Handle<Node>,
|
||||
}
|
||||
|
||||
@@ -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<Handle<Node>>) -> Self {
|
||||
self.machine = machine;
|
||||
self
|
||||
}
|
||||
|
||||
+17
-22
@@ -35,7 +35,7 @@ pub trait AnimationContainerExt {
|
||||
fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32);
|
||||
}
|
||||
|
||||
impl AnimationContainerExt for AnimationContainer {
|
||||
impl AnimationContainerExt for AnimationContainer<Handle<Node>> {
|
||||
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);
|
||||
@@ -58,15 +58,15 @@ pub trait AnimationPoseExt {
|
||||
/// rules. This could be useful if you need to ignore transform some part of pose for a node.
|
||||
fn apply_with<C>(&self, graph: &mut Graph, callback: C)
|
||||
where
|
||||
C: FnMut(&mut Node, Handle<Node>, &NodePose);
|
||||
C: FnMut(&mut Node, Handle<Node>, &NodePose<Handle<Node>>);
|
||||
}
|
||||
|
||||
impl AnimationPoseExt for AnimationPose {
|
||||
impl AnimationPoseExt for AnimationPose<Handle<Node>> {
|
||||
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(Handle::from(*node)) {
|
||||
} else if let Some(node) = nodes.try_borrow_mut(*node) {
|
||||
local_pose.values.apply(node);
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ impl AnimationPoseExt for AnimationPose {
|
||||
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(Handle::from(*node)) {
|
||||
} else if let Some(node) = graph.try_get_mut(*node) {
|
||||
local_pose.values.apply(node);
|
||||
}
|
||||
}
|
||||
@@ -84,13 +84,13 @@ impl AnimationPoseExt for AnimationPose {
|
||||
|
||||
fn apply_with<C>(&self, graph: &mut Graph, mut callback: C)
|
||||
where
|
||||
C: FnMut(&mut Node, Handle<Node>, &NodePose),
|
||||
C: FnMut(&mut Node, Handle<Node>, &NodePose<Handle<Node>>),
|
||||
{
|
||||
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(Handle::from(*node)) {
|
||||
callback(node_ref, Handle::from(*node), local_pose);
|
||||
} else if let Some(node_ref) = graph.try_get_mut(*node) {
|
||||
callback(node_ref, *node, local_pose);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,14 +174,9 @@ pub trait LayerMaskExt {
|
||||
fn from_hierarchy(graph: &Graph, root: ErasedHandle) -> Self;
|
||||
}
|
||||
|
||||
impl LayerMaskExt for LayerMask {
|
||||
impl LayerMaskExt for LayerMask<Handle<Node>> {
|
||||
fn from_hierarchy(graph: &Graph, root: ErasedHandle) -> Self {
|
||||
Self::from(
|
||||
graph
|
||||
.traverse_handle_iter(root.into())
|
||||
.map(ErasedHandle::from)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
Self::from(graph.traverse_handle_iter(root.into()).collect::<Vec<_>>())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +205,7 @@ impl LayerMaskExt for LayerMask {
|
||||
/// scene::{animation::AnimationPlayerBuilder, base::BaseBuilder, graph::Graph, node::Node},
|
||||
/// };
|
||||
///
|
||||
/// fn create_bounce_animation(animated_node: Handle<Node>) -> Animation {
|
||||
/// fn create_bounce_animation(animated_node: Handle<Node>) -> Animation<Handle<Node>> {
|
||||
/// let mut frames_container = TrackDataContainer::new(TrackValueKind::Vector3);
|
||||
///
|
||||
/// // We'll animate only Y coordinate (at index 1).
|
||||
@@ -257,7 +252,7 @@ impl LayerMaskExt for LayerMask {
|
||||
#[derive(Visit, Reflect, Clone, Debug)]
|
||||
pub struct AnimationPlayer {
|
||||
base: Base,
|
||||
animations: InheritableVariable<AnimationContainer>,
|
||||
animations: InheritableVariable<AnimationContainer<Handle<Node>>>,
|
||||
auto_apply: bool,
|
||||
}
|
||||
|
||||
@@ -287,18 +282,18 @@ impl AnimationPlayer {
|
||||
}
|
||||
|
||||
/// Returns a reference to internal animations container.
|
||||
pub fn animations(&self) -> &InheritableVariable<AnimationContainer> {
|
||||
pub fn animations(&self) -> &InheritableVariable<AnimationContainer<Handle<Node>>> {
|
||||
&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<AnimationContainer> {
|
||||
pub fn animations_mut(&mut self) -> &mut InheritableVariable<AnimationContainer<Handle<Node>>> {
|
||||
&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<Handle<Node>>) {
|
||||
self.animations.set_value_and_mark_modified(animations);
|
||||
}
|
||||
}
|
||||
@@ -350,7 +345,7 @@ impl NodeTrait for AnimationPlayer {
|
||||
/// A builder for [`AnimationPlayer`] node.
|
||||
pub struct AnimationPlayerBuilder {
|
||||
base_builder: BaseBuilder,
|
||||
animations: AnimationContainer,
|
||||
animations: AnimationContainer<Handle<Node>>,
|
||||
auto_apply: bool,
|
||||
}
|
||||
|
||||
@@ -365,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<Handle<Node>>) -> Self {
|
||||
self.animations = animations;
|
||||
self
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user