use abstract EntityId instead of ErasedHandle in animation entities

This commit is contained in:
Dmitry Stepanov
2023-12-26 20:10:46 +03:00
parent de4835e6f0
commit b145f0bd4b
40 changed files with 755 additions and 615 deletions
+3 -2
View File
@@ -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() {
+9 -9
View File
@@ -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 {
+36 -24
View File
@@ -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 {
+1 -1
View File
@@ -15,7 +15,7 @@ define_universal_commands! {
GameSceneCommandTrait,
GameSceneCommand,
GameSceneContext,
Handle<PoseNode>,
Handle<PoseNode<Handle<Node>>>,
ctx,
handle,
self,
+1 -1
View File
@@ -15,7 +15,7 @@ define_universal_commands!(
GameSceneCommandTrait,
GameSceneCommand,
GameSceneContext,
Handle<State>,
Handle<State<Handle<Node>>>,
ctx,
handle,
self,
+1 -1
View File
@@ -15,7 +15,7 @@ define_universal_commands!(
GameSceneCommandTrait,
GameSceneCommand,
GameSceneContext,
Handle<Transition>,
Handle<Transition<Handle<Node>>>,
ctx,
handle,
self,
+5 -5
View File
@@ -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()
+3 -3
View File
@@ -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)]
+4 -3
View File
@@ -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
}
+2 -2
View File
@@ -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,
+22 -15
View File
@@ -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
+5 -5
View File
@@ -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
+29 -18
View File
@@ -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
+17 -5
View File
@@ -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 -2
View File
@@ -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
+37 -29
View File
@@ -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,
}
+1 -1
View File
@@ -27,5 +27,5 @@ define_universal_commands!(
.unwrap()
},
node_handle: Handle<Node>,
animation_handle: Handle<Animation>
animation_handle: Handle<Animation<Handle<Node>>>
);
+1 -1
View File
@@ -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>,
}
+9 -5
View File
@@ -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 {
+4 -4
View File
@@ -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,
+10 -5
View File
@@ -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(
+56 -24
View File
@@ -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());
+2 -1
View File
@@ -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
View File
@@ -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]
}
}
+13 -12
View File
@@ -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()
}
}
+58 -58
View File
@@ -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() {
+18 -42
View File
@@ -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
}
}
+19 -16
View File
@@ -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() {
+57 -48
View File
@@ -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 {
+44 -37
View File
@@ -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 {
+33 -33
View File
@@ -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,
+18 -18
View File
@@ -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| {
+34 -25
View File
@@ -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) {
+42 -37
View File
@@ -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(&parameters, &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
View File
@@ -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
}
}
+10 -10
View File
@@ -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
}
+3 -3
View File
@@ -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
View File
@@ -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()
}) {
+6 -6
View File
@@ -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
View File
@@ -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
}