diff --git a/.idea/rg3d-core.iml b/.idea/rg3d-core.iml
index a9ad7420a..19864a77b 100644
--- a/.idea/rg3d-core.iml
+++ b/.idea/rg3d-core.iml
@@ -31,6 +31,7 @@
+
diff --git a/Cargo.toml b/Cargo.toml
index c689867bb..f71adce6a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,6 +23,7 @@ members = [
"fyrox-ui",
"fyrox-resource",
"fyrox-scripts",
+ "fyrox-animation",
"editor",
"editor-standalone",
"template"
@@ -41,6 +42,7 @@ fyrox-core = { path = "fyrox-core", version = "0.26.0", features = ["serde"] }
fyrox-sound = { path = "fyrox-sound", version = "0.33.0" }
fyrox-ui = { path = "fyrox-ui", version = "0.23.0" }
fyrox-resource = { path = "fyrox-resource", version = "0.10.0" }
+fyrox-animation = { path = "fyrox-animation", version = "0.1.0" }
rapier2d = { version = "0.17", features = ["debug-render"] }
rapier3d = { version = "0.17", features = ["debug-render"] }
image = { version = "0.24.3", default-features = false, features = ["gif", "jpeg", "png", "tga", "tiff", "bmp"] }
@@ -58,7 +60,6 @@ fxhash = "0.2.1"
strum = "0.25.0"
strum_macros = "0.25.0"
clap = { version = "4", features = ["derive"] }
-spade = "2.1.0"
winit = { version = "0.29.2", features = ["serde"] }
half = "2.2.1"
fast_image_resize = "2.7.0"
diff --git a/editor/src/absm/mod.rs b/editor/src/absm/mod.rs
index 9ffed0d86..782a6510f 100644
--- a/editor/src/absm/mod.rs
+++ b/editor/src/absm/mod.rs
@@ -484,7 +484,7 @@ impl AbsmEditor {
let mut animation_targets = FxHashSet::default();
for animation in animation_player.animations_mut().iter_mut() {
for track in animation.tracks() {
- animation_targets.insert(track.target());
+ animation_targets.insert(Handle::::from(track.target()));
}
}
diff --git a/editor/src/absm/toolbar.rs b/editor/src/absm/toolbar.rs
index 287eca6eb..db11c8f63 100644
--- a/editor/src/absm/toolbar.rs
+++ b/editor/src/absm/toolbar.rs
@@ -1,4 +1,3 @@
-use crate::message::MessageSender;
use crate::{
absm::{
command::{AddLayerCommand, RemoveLayerCommand, SetLayerMaskCommand, SetLayerNameCommand},
@@ -7,6 +6,7 @@ use crate::{
},
gui::make_dropdown_list_option,
load_image,
+ message::MessageSender,
scene::{
commands::{ChangeSelectionCommand, CommandGroup, GameSceneCommand},
selector::{HierarchyNode, NodeSelectorMessage, NodeSelectorWindowBuilder},
@@ -14,8 +14,6 @@ use crate::{
},
send_sync_message,
};
-use fyrox::core::pool::ErasedHandle;
-use fyrox::scene::node::Node;
use fyrox::{
animation::machine::{LayerMask, MachineLayer},
core::pool::Handle,
@@ -252,14 +250,14 @@ impl Toolbar {
.cloned()
.filter(|n| {
graph
- .try_get(*n)
- .map_or(false, |n| !unique_nodes.contains(&n.parent()))
+ .try_get((*n).into())
+ .map_or(false, |n| !unique_nodes.contains(&(n.parent().into())))
})
.collect::>();
for local_root in local_roots {
root.children.push(HierarchyNode::from_scene_node(
- local_root,
+ local_root.into(),
game_scene.editor_objects_root,
graph,
));
@@ -283,12 +281,8 @@ 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()
- .map(|h| ErasedHandle::from(*h))
- .collect::>();
+ let selection =
+ layer.mask().inner().iter().cloned().collect::>();
ui.send_message(NodeSelectorMessage::selection(
self.node_selector,
@@ -332,12 +326,7 @@ impl Toolbar {
&& message.direction() == MessageDirection::FromWidget
{
if let Some(layer_index) = selection.layer {
- let new_mask = LayerMask::from(
- mask_selection
- .iter()
- .map(|h| Handle::::from(*h))
- .collect::>(),
- );
+ let new_mask = LayerMask::from(mask_selection.clone());
sender.do_scene_command(SetLayerMaskCommand {
absm_node_handle: selection.absm_node_handle,
layer_index,
diff --git a/editor/src/animation/command/mod.rs b/editor/src/animation/command/mod.rs
index 5020682b0..3f44d5ec0 100644
--- a/editor/src/animation/command/mod.rs
+++ b/editor/src/animation/command/mod.rs
@@ -603,7 +603,7 @@ impl SetTrackTargetCommand {
.find(|t| t.id() == self.track)
.unwrap();
- let old = track.target();
+ let old = track.target().into();
track.set_target(self.target);
self.target = old;
}
diff --git a/editor/src/animation/mod.rs b/editor/src/animation/mod.rs
index 9e97a686e..f866e5324 100644
--- a/editor/src/animation/mod.rs
+++ b/editor/src/animation/mod.rs
@@ -353,7 +353,7 @@ impl AnimationEditor {
let animation_targets = animation
.tracks()
.iter()
- .map(|t| t.target())
+ .map(|t| Handle::::from(t.target()))
.collect::>();
self.enter_preview_mode(
diff --git a/editor/src/animation/toolbar.rs b/editor/src/animation/toolbar.rs
index b6181afee..0dad4bd7b 100644
--- a/editor/src/animation/toolbar.rs
+++ b/editor/src/animation/toolbar.rs
@@ -263,7 +263,7 @@ impl RootMotionDropdownArea {
self.node_selector,
MessageDirection::ToWidget,
if settings.node.is_some() {
- vec![settings.node.into()]
+ vec![settings.node]
} else {
vec![]
},
@@ -285,7 +285,7 @@ impl RootMotionDropdownArea {
node_handle: selection.animation_player,
animation_handle: selection.animation,
value: Some(RootMotionSettings {
- node: node_selection.first().cloned().unwrap_or_default().into(),
+ node: node_selection.first().cloned().unwrap_or_default(),
..*settings
}),
});
@@ -346,7 +346,7 @@ impl RootMotionDropdownArea {
MessageDirection::ToWidget,
scene
.graph
- .try_get(settings.node)
+ .try_get(settings.node.into())
.map(|n| n.name().to_owned())
.unwrap_or_else(|| String::from("")),
),
diff --git a/editor/src/animation/track.rs b/editor/src/animation/track.rs
index db6bea6d6..97369d82f 100644
--- a/editor/src/animation/track.rs
+++ b/editor/src/animation/track.rs
@@ -852,21 +852,21 @@ impl TrackList {
sender.do_scene_command(AddTrackCommand::new(
animation_player,
animation,
- Track::new_position().with_target(self.selected_node),
+ Track::new_position().with_target(self.selected_node.into()),
));
}
PropertyBindingMode::Rotation => {
sender.do_scene_command(AddTrackCommand::new(
animation_player,
animation,
- Track::new_rotation().with_target(self.selected_node),
+ Track::new_rotation().with_target(self.selected_node.into()),
));
}
PropertyBindingMode::Scale => {
sender.do_scene_command(AddTrackCommand::new(
animation_player,
animation,
- Track::new_scale().with_target(self.selected_node),
+ Track::new_scale().with_target(self.selected_node.into()),
));
}
}
@@ -1185,7 +1185,7 @@ impl TrackList {
.find(|t| t.id() == first_selected_track)
{
self.context_menu.property_rebinding_selector =
- Self::open_property_selector(graph, track.target(), ui);
+ Self::open_property_selector(graph, track.target().into(), ui);
}
}
@@ -1223,7 +1223,7 @@ impl TrackList {
return;
};
- let Some(node) = graph.try_get(track.target()) else {
+ let Some(node) = graph.try_get(track.target().into()) else {
Log::err("Invalid node handle!");
return;
};
@@ -1348,7 +1348,8 @@ impl TrackList {
.map(|v| ui.node(*v))
.all(|v| v.query_component::().unwrap().id != model_track.id())
{
- let parent_group = match self.group_views.entry(model_track.target()) {
+ let parent_group = match self.group_views.entry(model_track.target().into())
+ {
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
let ctx = &mut ui.build_ctx();
@@ -1361,7 +1362,7 @@ impl TrackList {
.with_text(format!(
"{} ({}:{})",
graph
- .try_get(model_track.target())
+ .try_get(model_track.target().into())
.map(|n| n.name())
.unwrap_or_default(),
model_track.target().index(),
@@ -1420,7 +1421,7 @@ impl TrackList {
)
.with_track_enabled(model_track.is_enabled())
.with_id(model_track.id())
- .with_target(model_track.target())
+ .with_target(model_track.target().into())
.with_name(format!("{}", model_track.binding()))
.build(ctx);
@@ -1495,8 +1496,8 @@ impl TrackList {
}
let mut validation_result = Ok(());
- if let Some(target) = graph.try_get(track_model.target()) {
- if let Some(parent_group) = self.group_views.get(&track_model.target()) {
+ if let Some(target) = graph.try_get(track_model.target().into()) {
+ if let Some(parent_group) = self.group_views.get(&track_model.target().into()) {
send_sync_message(
ui,
TextMessage::text(
diff --git a/fyrox-animation/Cargo.toml b/fyrox-animation/Cargo.toml
new file mode 100644
index 000000000..afb2173e9
--- /dev/null
+++ b/fyrox-animation/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "fyrox-animation"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+fyrox-core = { version = "0.26.0", path = "../fyrox-core" }
+fyrox-resource = { version = "0.10.0", path = "../fyrox-resource" }
+strum = "0.25.0"
+strum_macros = "0.25.0"
+fxhash = "0.2.1"
+spade = "2.1.0"
\ No newline at end of file
diff --git a/src/animation/container.rs b/fyrox-animation/src/container.rs
similarity index 99%
rename from src/animation/container.rs
rename to fyrox-animation/src/container.rs
index 6a5238ffb..7cc0ef5db 100644
--- a/src/animation/container.rs
+++ b/fyrox-animation/src/container.rs
@@ -2,7 +2,6 @@
//! of parametric curves. See [`TrackDataContainer`] docs for more info.
use crate::{
- animation::value::TrackValue,
core::{
algebra::{Vector2, Vector3, Vector4},
curve::Curve,
@@ -10,6 +9,7 @@ use crate::{
reflect::prelude::*,
visitor::prelude::*,
},
+ value::TrackValue,
};
/// The kind of track output value, the animation system works only with numeric properties and the number
diff --git a/src/animation/mod.rs b/fyrox-animation/src/lib.rs
similarity index 91%
rename from src/animation/mod.rs
rename to fyrox-animation/src/lib.rs
index bed93c8dd..ae4fcb14b 100644
--- a/src/animation/mod.rs
+++ b/fyrox-animation/src/lib.rs
@@ -4,7 +4,6 @@
#![warn(missing_docs)]
use crate::{
- animation::track::Track,
core::{
algebra::{UnitQuaternion, Vector3},
math::wrapf,
@@ -13,22 +12,21 @@ use crate::{
uuid::Uuid,
visitor::{Visit, VisitResult, Visitor},
},
- scene::{
- graph::{Graph, NodePool},
- node::Node,
- },
- utils::{self, NameProvider},
+ track::Track,
};
-use fyrox_core::uuid_provider;
+use fyrox_core::{uuid_provider, NameProvider};
use std::{
collections::VecDeque,
fmt::Debug,
ops::{Index, IndexMut, Range},
};
-use crate::animation::value::{TrackValue, ValueBinding};
+pub use fyrox_core as core;
+use fyrox_core::pool::ErasedHandle;
+
pub use pose::{AnimationPose, NodePose};
pub use signal::{AnimationEvent, AnimationSignal};
+use value::{TrackValue, ValueBinding};
pub mod container;
pub mod machine;
@@ -117,26 +115,19 @@ pub mod value;
/// Use the following example code as a guide **only** if you need to create procedural animations:
///
/// ```rust
-/// use fyrox::{
-/// animation::{
-/// container::{TrackDataContainer, TrackValueKind},
-/// track::Track,
-/// value::ValueBinding,
-/// Animation,
-/// },
+/// use fyrox_animation::{
+/// container::{TrackDataContainer, TrackValueKind},
+/// track::Track,
+/// value::ValueBinding,
+/// Animation,
/// core::{
/// curve::{Curve, CurveKey, CurveKeyKind},
/// pool::Handle,
/// },
-/// scene::{
-/// node::Node,
-/// base::BaseBuilder,
-/// graph::Graph,
-/// pivot::PivotBuilder
-/// }
/// };
+/// use fyrox_core::pool::ErasedHandle;
///
-/// fn create_animation(node: Handle) -> Animation {
+/// fn create_animation(target: ErasedHandle) -> Animation {
/// let mut frames_container = TrackDataContainer::new(TrackValueKind::Vector3);
///
/// // We'll animate only X coordinate (at index 0).
@@ -148,7 +139,7 @@ pub mod value;
///
/// // Create a track that will animated the node using the curve above.
/// let mut track = Track::new(frames_container, ValueBinding::Position);
-/// track.set_target(node);
+/// track.set_target(target);
///
/// // Finally create an animation and set its time slice and turn it on.
/// let mut animation = Animation::default();
@@ -159,17 +150,12 @@ pub mod value;
/// animation
/// }
///
-/// // Create a graph with a node.
-/// let mut graph = Graph::new();
-/// let some_node = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
-///
/// // Create the animation.
-/// let mut animation = create_animation(some_node);
+/// let mut animation = create_animation(Default::default());
///
/// // Emulate some ticks (like it was updated from the main loop of your game).
/// for _ in 0..10 {
/// animation.tick(1.0 / 60.0);
-/// animation.pose().apply(&mut graph);
/// }
/// ```
///
@@ -215,7 +201,7 @@ uuid_provider!(Animation = "aade8e9d-e2cf-401d-a4d1-59c6943645f3");
pub struct RootMotionSettings {
/// A handle to a node which movement will be extracted and put in root motion field of an animation
/// to which these settings were set to.
- pub node: Handle,
+ pub node: ErasedHandle,
/// 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.
@@ -683,39 +669,8 @@ impl Animation {
self.tracks.retain(filter)
}
- /// Enables or disables animation tracks for nodes in hierarchy starting from given root. Could be useful to enable
- /// or disable animation for skeleton parts, i.e. you don't want legs to be animated and you know that legs starts
- /// from torso bone, then you could do this.
- ///
- /// ```
- /// use fyrox::scene::node::Node;
- /// use fyrox::animation::Animation;
- /// use fyrox::core::pool::Handle;
- /// use fyrox::scene::graph::Graph;
- ///
- /// fn disable_legs(torso_bone: Handle, aim_animation: &mut Animation, graph: &Graph) {
- /// aim_animation.set_tracks_enabled_from(torso_bone, false, graph)
- /// }
- /// ```
- ///
- /// After this legs won't be animated and animation could be blended together with run animation so it will produce
- /// new animation - run and aim.
- pub fn set_tracks_enabled_from(&mut self, handle: Handle, enabled: bool, graph: &Graph) {
- let mut stack = vec![handle];
- while let Some(node) = stack.pop() {
- for track in self.tracks.iter_mut() {
- if track.target() == node {
- track.set_enabled(enabled);
- }
- }
- for child in graph[node].children() {
- stack.push(*child);
- }
- }
- }
-
/// Tries to find all tracks that refer to a given node and enables or disables them.
- pub fn set_node_track_enabled(&mut self, handle: Handle, enabled: bool) {
+ pub fn set_node_track_enabled(&mut self, handle: ErasedHandle, enabled: bool) {
for track in self.tracks.iter_mut() {
if track.target() == handle {
track.set_enabled(enabled);
@@ -724,14 +679,14 @@ impl Animation {
}
/// Returns an iterator that yields a number of references to tracks that refer to a given node.
- pub fn tracks_of(&self, handle: Handle) -> impl Iterator- {
+ pub fn tracks_of(&self, handle: ErasedHandle) -> impl Iterator
- {
self.tracks
.iter()
.filter(move |track| track.target() == handle)
}
/// Returns an iterator that yields a number of references to tracks that refer to a given node.
- pub fn tracks_of_mut(&mut self, handle: Handle) -> impl Iterator
- {
+ pub fn tracks_of_mut(&mut self, handle: ErasedHandle) -> impl Iterator
- {
self.tracks
.iter_mut()
.filter(move |track| track.target() == handle)
@@ -743,7 +698,7 @@ impl Animation {
&self,
name: S,
) -> Option<(usize, &AnimationSignal)> {
- utils::find_by_name_ref(self.signals.iter().enumerate(), name)
+ core::find_by_name_ref(self.signals.iter().enumerate(), name)
}
/// Tries to find a signal by its name. Returns index of the signal and its reference.
@@ -752,7 +707,7 @@ impl Animation {
&mut self,
name: S,
) -> Option<(usize, &mut AnimationSignal)> {
- utils::find_by_name_mut(self.signals.iter_mut().enumerate(), name)
+ core::find_by_name_mut(self.signals.iter_mut().enumerate(), name)
}
/// Returns `true` if there's a signal with given name and id.
@@ -920,7 +875,7 @@ impl AnimationContainer {
&self,
name: S,
) -> Option<(Handle, &Animation)> {
- utils::find_by_name_ref(self.pool.pair_iter(), name)
+ core::find_by_name_ref(self.pool.pair_iter(), name)
}
/// Tries to find an animation by its name in the container.
@@ -929,7 +884,7 @@ impl AnimationContainer {
&mut self,
name: S,
) -> Option<(Handle, &mut Animation)> {
- utils::find_by_name_mut(self.pool.pair_iter_mut(), name)
+ core::find_by_name_mut(self.pool.pair_iter_mut(), name)
}
/// Removes every animation from the container that does not satisfy a particular condition represented by the given
@@ -942,17 +897,6 @@ impl AnimationContainer {
self.pool.retain(pred)
}
- /// Updates all animations in the container and applies their poses to respective nodes. This method is intended to
- /// be used only by the internals of the engine!
- pub fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32) {
- for animation in self.pool.iter_mut().filter(|anim| anim.enabled) {
- animation.tick(dt);
- if apply {
- animation.pose.apply_internal(nodes);
- }
- }
- }
-
/// Removes queued animation events from every animation in the container.
///
/// # Potential use cases
diff --git a/src/animation/machine/event.rs b/fyrox-animation/src/machine/event.rs
similarity index 97%
rename from src/animation/machine/event.rs
rename to fyrox-animation/src/machine/event.rs
index 7849c8610..fdbf7acec 100644
--- a/src/animation/machine/event.rs
+++ b/fyrox-animation/src/machine/event.rs
@@ -2,8 +2,8 @@
//! needed to works with such events.
use crate::{
- animation::machine::{State, Transition},
core::pool::Handle,
+ machine::{State, Transition},
};
use std::collections::VecDeque;
diff --git a/src/animation/machine/layer.rs b/fyrox-animation/src/machine/layer.rs
similarity index 96%
rename from src/animation/machine/layer.rs
rename to fyrox-animation/src/machine/layer.rs
index 96b712632..3ff954e82 100644
--- a/src/animation/machine/layer.rs
+++ b/fyrox-animation/src/machine/layer.rs
@@ -1,25 +1,20 @@
//! Layer is a separate state graph that usually animates only a part of nodes from animations. See docs of [`MachineLayer`]
//! for more info.
-use crate::animation::machine::node::AnimationEventCollectionStrategy;
-use crate::animation::machine::AnimationPoseSource;
-use crate::animation::AnimationEvent;
use crate::{
- animation::{
- machine::{
- event::FixedEventQueue, Event, LayerMask, ParameterContainer, PoseNode, State,
- Transition,
- },
- Animation, AnimationContainer, AnimationPose,
- },
core::{
log::{Log, MessageKind},
pool::{Handle, Pool},
reflect::prelude::*,
visitor::prelude::*,
},
- utils::{self, NameProvider},
+ machine::{
+ event::FixedEventQueue, node::AnimationEventCollectionStrategy, AnimationPoseSource, Event,
+ LayerMask, ParameterContainer, PoseNode, State, Transition,
+ },
+ Animation, AnimationContainer, AnimationEvent, AnimationPose,
};
+use fyrox_core::{find_by_name_mut, find_by_name_ref, NameProvider};
/// Layer is a separate state graph. Layers mainly used to animate different parts of humanoid (but not only) characters. For
/// example there could a layer for upper body and a layer for lower body. Upper body layer could contain animations for aiming,
@@ -30,8 +25,8 @@ use crate::{
/// # Example
///
/// ```rust
-/// use fyrox::{
-/// animation::machine::{
+/// use fyrox_animation::{
+/// machine::{
/// State, Transition, PoseNode, MachineLayer,
/// Parameter, PlayAnimation, PoseWeight, BlendAnimations, BlendPose
/// },
@@ -241,7 +236,7 @@ impl MachineLayer {
/// # Example
///
/// ```rust
- /// use fyrox::animation::machine::{Event, MachineLayer};
+ /// use fyrox_animation::machine::{Event, MachineLayer};
///
/// let mut layer = MachineLayer::new();
///
@@ -451,7 +446,7 @@ impl MachineLayer {
&self,
name: S,
) -> Option<(Handle, &Transition)> {
- utils::find_by_name_ref(self.transitions.pair_iter(), name)
+ find_by_name_ref(self.transitions.pair_iter(), name)
}
/// Tries to find a transition by its name.
@@ -460,7 +455,7 @@ impl MachineLayer {
&mut self,
name: S,
) -> Option<(Handle, &mut Transition)> {
- utils::find_by_name_mut(self.transitions.pair_iter_mut(), name)
+ find_by_name_mut(self.transitions.pair_iter_mut(), name)
}
/// Tries to borrow a state using its handle, panics if the handle is invalid.
@@ -481,7 +476,7 @@ impl MachineLayer {
&self,
name: S,
) -> Option<(Handle, &State)> {
- utils::find_by_name_ref(self.states.pair_iter(), name)
+ find_by_name_ref(self.states.pair_iter(), name)
}
/// Tries to find a state by its name.
@@ -490,7 +485,7 @@ impl MachineLayer {
&mut self,
name: S,
) -> Option<(Handle, &mut State)> {
- utils::find_by_name_mut(self.states.pair_iter_mut(), name)
+ find_by_name_mut(self.states.pair_iter_mut(), name)
}
/// Returns a reference to inner states container.
diff --git a/src/animation/machine/mask.rs b/fyrox-animation/src/machine/mask.rs
similarity index 76%
rename from src/animation/machine/mask.rs
rename to fyrox-animation/src/machine/mask.rs
index 995d95034..0e5f20871 100644
--- a/src/animation/machine/mask.rs
+++ b/fyrox-animation/src/machine/mask.rs
@@ -1,34 +1,24 @@
//! Layer mask is a sort of blacklist that prevents layer from animating certain nodes. See [`LayerMask`] docs
//! for more info.
-use crate::{
- core::{pool::Handle, reflect::prelude::*, visitor::prelude::*},
- scene::{graph::Graph, node::Node},
-};
+use crate::core::{pool::ErasedHandle, reflect::prelude::*, visitor::prelude::*};
/// 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>,
+ excluded_bones: Vec,
}
-impl From>> for LayerMask {
- fn from(mut excluded_bones: Vec>) -> Self {
+impl From> for LayerMask {
+ fn from(mut excluded_bones: Vec) -> Self {
excluded_bones.sort_by_key(|h| h.index());
Self { excluded_bones }
}
}
impl LayerMask {
- /// Creates a layer mask for every descendant node starting from specified `root` (included). It could
- /// be useful if you have an entire node hierarchy (for example, lower part of a body) that needs to
- /// be filtered out.
- pub fn from_hierarchy(graph: &Graph, root: Handle) -> Self {
- Self::from(graph.traverse_handle_iter(root).collect::>())
- }
-
/// Merges a given layer mask in the current mask, handles will be automatically de-duplicated.
pub fn merge(&mut self, other: LayerMask) {
for handle in other.into_inner() {
@@ -46,7 +36,7 @@ impl LayerMask {
///
/// The method has O(log(n)) complexity, which means it is very fast for most use cases.
#[inline]
- pub fn add(&mut self, node: Handle) {
+ pub fn add(&mut self, node: ErasedHandle) {
let index = self
.excluded_bones
.partition_point(|h| h.index() < node.index());
@@ -59,13 +49,13 @@ impl LayerMask {
/// # Performance
///
/// The method has O(log(n)) complexity, which means it is very fast for most use cases.
- pub fn remove(&mut self, node: Handle) {
+ pub fn remove(&mut self, node: ErasedHandle) {
if let Some(index) = self.index_of(node) {
self.excluded_bones.remove(index);
}
}
- fn index_of(&self, node: Handle) -> Option {
+ fn index_of(&self, node: ErasedHandle) -> Option {
if let Ok(mut index) = self
.excluded_bones
.binary_search_by(|h| h.index().cmp(&node.index()))
@@ -98,7 +88,7 @@ impl LayerMask {
///
/// The method has O(log(n)) complexity, which means it is very fast for most use cases.
#[inline]
- pub fn contains(&self, node: Handle) -> bool {
+ pub fn contains(&self, node: ErasedHandle) -> bool {
self.index_of(node).is_some()
}
@@ -108,20 +98,20 @@ impl LayerMask {
///
/// The method has O(log(n)) complexity, which means it is very fast for most use cases.
#[inline]
- pub fn should_animate(&self, node: Handle) -> bool {
+ pub fn should_animate(&self, node: ErasedHandle) -> bool {
!self.contains(node)
}
/// Return a reference to inner container. There's only non-mutable version because inner container must always
/// be sorted.
#[inline]
- pub fn inner(&self) -> &Vec> {
+ pub fn inner(&self) -> &Vec {
&self.excluded_bones
}
/// Converts the mask into inner container.
#[inline]
- pub fn into_inner(self) -> Vec> {
+ pub fn into_inner(self) -> Vec {
self.excluded_bones
}
}
diff --git a/src/animation/machine/mod.rs b/fyrox-animation/src/machine/mod.rs
similarity index 97%
rename from src/animation/machine/mod.rs
rename to fyrox-animation/src/machine/mod.rs
index ac782ab04..45b6f7e1d 100644
--- a/src/animation/machine/mod.rs
+++ b/fyrox-animation/src/machine/mod.rs
@@ -6,15 +6,15 @@
#![warn(missing_docs)]
use crate::{
- animation::{AnimationContainer, AnimationPose},
core::{
reflect::prelude::*,
visitor::{Visit, VisitResult, Visitor},
},
- utils,
+ AnimationContainer, AnimationPose,
};
pub use event::Event;
+use fyrox_core::{find_by_name_mut, find_by_name_ref};
pub use layer::MachineLayer;
pub use mask::LayerMask;
pub use node::{
@@ -122,8 +122,8 @@ pub mod transition;
/// using code like so:
///
/// ```no_run
-/// use fyrox::{
-/// animation::machine::{
+/// use fyrox_animation::{
+/// machine::{
/// Machine, State, Transition, PoseNode,
/// Parameter, PlayAnimation, PoseWeight, BlendAnimations, BlendPose
/// },
@@ -193,7 +193,7 @@ impl Machine {
/// The method returns a reference to the machine, so the calls could be chained:
///
/// ```rust
- /// use fyrox::animation::machine::{Machine, Parameter};
+ /// use fyrox_animation::machine::{Machine, Parameter};
///
/// let mut machine = Machine::new();
///
@@ -266,7 +266,7 @@ impl Machine {
/// Tries to find a layer by its name. Returns index of the layer and its reference.
#[inline]
pub fn find_layer_by_name_ref>(&self, name: S) -> Option<(usize, &MachineLayer)> {
- utils::find_by_name_ref(self.layers.iter().enumerate(), name)
+ find_by_name_ref(self.layers.iter().enumerate(), name)
}
/// Tries to find a layer by its name. Returns index of the layer and its reference.
@@ -275,7 +275,7 @@ impl Machine {
&mut self,
name: S,
) -> Option<(usize, &mut MachineLayer)> {
- utils::find_by_name_mut(self.layers.iter_mut().enumerate(), name)
+ find_by_name_mut(self.layers.iter_mut().enumerate(), name)
}
/// Returns final pose of the machine.
diff --git a/src/animation/machine/node/blend.rs b/fyrox-animation/src/machine/node/blend.rs
similarity index 97%
rename from src/animation/machine/node/blend.rs
rename to fyrox-animation/src/machine/node/blend.rs
index 954bfa760..9b38334aa 100644
--- a/src/animation/machine/node/blend.rs
+++ b/fyrox-animation/src/machine/node/blend.rs
@@ -1,20 +1,16 @@
//! Various animation blending nodes.
-use crate::animation::machine::node::AnimationEventCollectionStrategy;
-use crate::animation::{Animation, AnimationEvent};
use crate::{
- animation::{
- machine::{
- node::BasePoseNode, AnimationPoseSource, Parameter, ParameterContainer, PoseNode,
- PoseWeight,
- },
- AnimationContainer, AnimationPose,
- },
core::{
pool::{Handle, Pool},
reflect::prelude::*,
visitor::{Visit, VisitResult, Visitor},
},
+ machine::{
+ node::AnimationEventCollectionStrategy, node::BasePoseNode, AnimationPoseSource, Parameter,
+ ParameterContainer, PoseNode, PoseWeight,
+ },
+ Animation, AnimationContainer, AnimationEvent, AnimationPose,
};
use fyrox_core::uuid_provider;
use std::cmp::Ordering;
diff --git a/src/animation/machine/node/blendspace.rs b/fyrox-animation/src/machine/node/blendspace.rs
similarity index 97%
rename from src/animation/machine/node/blendspace.rs
rename to fyrox-animation/src/machine/node/blendspace.rs
index bf92552eb..47ed17ece 100644
--- a/src/animation/machine/node/blendspace.rs
+++ b/fyrox-animation/src/machine/node/blendspace.rs
@@ -1,14 +1,6 @@
#![allow(missing_docs)] // TODO
-use crate::animation::machine::node::AnimationEventCollectionStrategy;
-use crate::animation::{Animation, AnimationEvent};
use crate::{
- animation::{
- machine::{
- node::BasePoseNode, AnimationPoseSource, Parameter, ParameterContainer, PoseNode,
- },
- AnimationContainer, AnimationPose,
- },
core::{
algebra::Vector2,
math::{self, TriangleDefinition},
@@ -16,6 +8,11 @@ use crate::{
reflect::prelude::*,
visitor::prelude::*,
},
+ machine::{
+ node::AnimationEventCollectionStrategy, node::BasePoseNode, AnimationPoseSource, Parameter,
+ ParameterContainer, PoseNode,
+ },
+ Animation, AnimationContainer, AnimationEvent, AnimationPose,
};
use fyrox_core::uuid_provider;
use spade::{DelaunayTriangulation, Point2, Triangulation};
@@ -429,8 +426,8 @@ impl BlendSpace {
#[cfg(test)]
mod test {
use crate::{
- animation::machine::node::blendspace::{BlendSpace, BlendSpacePoint},
core::{algebra::Vector2, math::TriangleDefinition},
+ machine::node::blendspace::{BlendSpace, BlendSpacePoint},
};
#[test]
diff --git a/src/animation/machine/node/mod.rs b/fyrox-animation/src/machine/node/mod.rs
similarity index 94%
rename from src/animation/machine/node/mod.rs
rename to fyrox-animation/src/machine/node/mod.rs
index 7c9adbaee..4e6dad56d 100644
--- a/src/animation/machine/node/mod.rs
+++ b/fyrox-animation/src/machine/node/mod.rs
@@ -1,21 +1,18 @@
//! Node is a part of animation blending tree, that backs a state with animation data. See [`PoseNode`] docs for
//! more info.
-use crate::animation::AnimationEvent;
use crate::{
- animation::{
- machine::{
- node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation},
- BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State,
- },
- Animation, AnimationContainer, AnimationPose,
- },
core::{
algebra::Vector2,
pool::{Handle, Pool},
reflect::prelude::*,
visitor::prelude::*,
},
+ machine::{
+ node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation},
+ BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State,
+ },
+ Animation, AnimationContainer, AnimationEvent, AnimationPose,
};
use std::{
cell::Ref,
diff --git a/src/animation/machine/node/play.rs b/fyrox-animation/src/machine/node/play.rs
similarity index 90%
rename from src/animation/machine/node/play.rs
rename to fyrox-animation/src/machine/node/play.rs
index e130eafe9..1f76312d6 100644
--- a/src/animation/machine/node/play.rs
+++ b/fyrox-animation/src/machine/node/play.rs
@@ -1,20 +1,17 @@
//! A simplest pose node that extracts pose from a specific animation and prepares it for further use.
-use crate::animation::machine::node::AnimationEventCollectionStrategy;
-use crate::animation::AnimationEvent;
use crate::{
- animation::{
- machine::{
- node::{AnimationPoseSource, BasePoseNode},
- ParameterContainer, PoseNode,
- },
- Animation, AnimationContainer, AnimationPose,
- },
core::{
pool::{Handle, Pool},
reflect::prelude::*,
visitor::prelude::*,
},
+ machine::{
+ node::AnimationEventCollectionStrategy,
+ node::{AnimationPoseSource, BasePoseNode},
+ ParameterContainer, PoseNode,
+ },
+ Animation, AnimationContainer, AnimationEvent, AnimationPose,
};
use std::{
cell::{Ref, RefCell},
diff --git a/src/animation/machine/parameter.rs b/fyrox-animation/src/machine/parameter.rs
similarity index 100%
rename from src/animation/machine/parameter.rs
rename to fyrox-animation/src/machine/parameter.rs
diff --git a/src/animation/machine/state.rs b/fyrox-animation/src/machine/state.rs
similarity index 95%
rename from src/animation/machine/state.rs
rename to fyrox-animation/src/machine/state.rs
index 8c440297f..a452be969 100644
--- a/src/animation/machine/state.rs
+++ b/fyrox-animation/src/machine/state.rs
@@ -1,20 +1,17 @@
//! State is a final "container" for animation pose. See [`State`] docs for more info.
use crate::{
- animation::{
- machine::{AnimationPoseSource, ParameterContainer, PoseNode},
- Animation, AnimationContainer, AnimationPose,
- },
core::{
algebra::Vector2,
pool::{Handle, Pool},
+ rand::{self, seq::IteratorRandom},
reflect::prelude::*,
visitor::prelude::*,
},
- rand::{self, seq::IteratorRandom},
- utils::NameProvider,
+ machine::{AnimationPoseSource, ParameterContainer, PoseNode},
+ Animation, AnimationContainer, AnimationPose,
};
-use fyrox_core::uuid_provider;
+use fyrox_core::{uuid_provider, NameProvider};
use std::{
cell::Ref,
ops::{Deref, DerefMut},
diff --git a/src/animation/machine/transition.rs b/fyrox-animation/src/machine/transition.rs
similarity index 98%
rename from src/animation/machine/transition.rs
rename to fyrox-animation/src/machine/transition.rs
index f0ea05b72..051d5eafe 100644
--- a/src/animation/machine/transition.rs
+++ b/fyrox-animation/src/machine/transition.rs
@@ -1,14 +1,11 @@
//! Transition is a connection between two states with a rule that defines possibility of actual transition with blending.
use crate::{
- animation::{
- machine::{Parameter, ParameterContainer, State},
- Animation, AnimationContainer,
- },
core::{pool::Handle, reflect::prelude::*, visitor::prelude::*},
- utils::NameProvider,
+ machine::{Parameter, ParameterContainer, State},
+ Animation, AnimationContainer,
};
-use fyrox_core::uuid_provider;
+use fyrox_core::{uuid_provider, NameProvider};
use std::any::{type_name, Any, TypeId};
use strum_macros::{AsRefStr, EnumString, EnumVariantNames};
@@ -266,8 +263,8 @@ impl Reflect for NotNode {
/// # Examples
///
/// ```rust
-/// use fyrox::animation::AnimationContainer;
-/// use fyrox::animation::machine::{
+/// use fyrox_animation::AnimationContainer;
+/// use fyrox_animation::machine::{
/// transition::{AndNode, LogicNode, NotNode},
/// Parameter, ParameterContainer,
/// };
diff --git a/src/animation/pose.rs b/fyrox-animation/src/pose.rs
similarity index 58%
rename from src/animation/pose.rs
rename to fyrox-animation/src/pose.rs
index 266162a18..2c0c3286f 100644
--- a/src/animation/pose.rs
+++ b/fyrox-animation/src/pose.rs
@@ -1,36 +1,21 @@
//! Pose is a set of property values of a node ([`NodePose`]) or a set of nodes ([`AnimationPose`]).
-use crate::{
- animation::{value::BoundValue, value::BoundValueCollection, RootMotion},
- core::{
- log::{Log, MessageKind},
- pool::Handle,
- },
- scene::{graph::Graph, graph::NodePool, node::Node},
-};
+use crate::{value::BoundValue, value::BoundValueCollection, 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)]
+#[derive(Clone, Debug, PartialEq, Default)]
pub struct NodePose {
/// A handle of an animated node.
- pub node: Handle,
+ pub node: ErasedHandle,
/// A set of property values.
pub values: BoundValueCollection,
}
-impl Default for NodePose {
- fn default() -> Self {
- Self {
- node: Handle::NONE,
- values: Default::default(),
- }
- }
-}
-
impl NodePose {
/// Performs a blending of the current with some other pose. See [`super::value::TrackValue::blend_with`] docs for more
/// info.
@@ -42,7 +27,7 @@ impl NodePose {
/// Animations pose is a set of node poses. See [`NodePose`] docs for more info.
#[derive(Default, Debug, Clone, PartialEq)]
pub struct AnimationPose {
- poses: FxHashMap, NodePose>,
+ poses: FxHashMap,
root_motion: Option,
}
@@ -87,7 +72,7 @@ impl AnimationPose {
self.poses.insert(local_pose.node, local_pose);
}
- pub(super) fn add_to_node_pose(&mut self, node: Handle, bound_value: BoundValue) {
+ pub(super) fn add_to_node_pose(&mut self, node: ErasedHandle, bound_value: BoundValue) {
match self.poses.entry(node) {
Entry::Occupied(entry) => {
entry.into_mut().values.values.push(bound_value);
@@ -109,48 +94,12 @@ impl AnimationPose {
}
/// Returns a reference to inner node pose map.
- pub fn poses(&self) -> &FxHashMap, NodePose> {
+ pub fn poses(&self) -> &FxHashMap {
&self.poses
}
/// Returns a reference to inner node pose map.
- pub fn poses_mut(&mut self) -> &mut FxHashMap, NodePose> {
+ pub fn poses_mut(&mut self) -> &mut FxHashMap {
&mut self.poses
}
-
- pub(crate) fn apply_internal(&self, nodes: &mut NodePool) {
- for (node, local_pose) in self.poses.iter() {
- if node.is_none() {
- Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!");
- } else if let Some(node) = nodes.try_borrow_mut(*node) {
- local_pose.values.apply(node);
- }
- }
- }
-
- /// Tries to set each value to the each property from the animation pose to respective scene nodes.
- pub fn apply(&self, graph: &mut Graph) {
- for (node, local_pose) in self.poses.iter() {
- if node.is_none() {
- Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!");
- } else if let Some(node) = graph.try_get_mut(*node) {
- local_pose.values.apply(node);
- }
- }
- }
-
- /// Calls given callback function for each node and allows you to apply pose with your own
- /// rules. This could be useful if you need to ignore transform some part of pose for a node.
- pub fn apply_with(&self, graph: &mut Graph, mut callback: C)
- where
- C: FnMut(&mut Node, Handle, &NodePose),
- {
- for (node, local_pose) in self.poses.iter() {
- if node.is_none() {
- Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!");
- } else if let Some(node_ref) = graph.try_get_mut(*node) {
- callback(node_ref, *node, local_pose);
- }
- }
- }
}
diff --git a/src/animation/signal.rs b/fyrox-animation/src/signal.rs
similarity index 95%
rename from src/animation/signal.rs
rename to fyrox-animation/src/signal.rs
index 41a669f98..0b0923c42 100644
--- a/src/animation/signal.rs
+++ b/fyrox-animation/src/signal.rs
@@ -1,9 +1,7 @@
//! Signal is a named marker on specific time position on the animation timeline. See [`AnimationSignal`] docs for more info.
-use crate::{
- core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
- utils::NameProvider,
-};
+use crate::core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*};
+use fyrox_core::NameProvider;
/// An event happened in an animation.
#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/src/animation/spritesheet/mod.rs b/fyrox-animation/src/spritesheet/mod.rs
similarity index 97%
rename from src/animation/spritesheet/mod.rs
rename to fyrox-animation/src/spritesheet/mod.rs
index dd8360ad0..9677d4e99 100644
--- a/src/animation/spritesheet/mod.rs
+++ b/fyrox-animation/src/spritesheet/mod.rs
@@ -4,11 +4,11 @@
#![warn(missing_docs)]
use crate::{
- animation::spritesheet::signal::Signal,
core::{algebra::Vector2, math::Rect, reflect::prelude::*, visitor::prelude::*},
- resource::texture::TextureResource,
+ spritesheet::signal::Signal,
};
use fyrox_core::uuid_provider;
+use fyrox_resource::untyped::UntypedResource;
use std::collections::vec_deque::VecDeque;
use strum_macros::{AsRefStr, EnumString, EnumVariantNames};
@@ -58,7 +58,7 @@ pub struct SpriteSheetFramesContainer {
size: Vector2,
frames: Vec>,
#[visit(optional)]
- texture: Option,
+ texture: Option,
}
impl SpriteSheetFramesContainer {
@@ -115,7 +115,7 @@ impl SpriteSheetFramesContainer {
}
/// Returns current texture of the container. To set a texture use sprite sheet animation methods.
- pub fn texture(&self) -> Option {
+ pub fn texture(&self) -> Option {
self.texture.clone()
}
}
@@ -143,7 +143,7 @@ pub struct SpriteSheetAnimation {
signals: Vec,
#[visit(optional)]
#[reflect(setter = "set_texture")]
- texture: Option,
+ texture: Option,
#[reflect(hidden)]
#[visit(skip)]
events: VecDeque,
@@ -221,8 +221,8 @@ impl SpriteSheetAnimation {
/// like this:
///
/// ```rust
- /// # use fyrox::{
- /// # animation::spritesheet::{ImageParameters, SpriteSheetAnimation},
+ /// # use fyrox_animation::{
+ /// # spritesheet::{ImageParameters, SpriteSheetAnimation},
/// # core::math::Rect,
/// # };
/// fn extract_animations() {
@@ -310,13 +310,13 @@ impl SpriteSheetAnimation {
}
/// Sets new texture for the animation.
- pub fn set_texture(&mut self, texture: Option) -> Option {
+ pub fn set_texture(&mut self, texture: Option) -> Option {
self.frames_container.texture = texture.clone();
std::mem::replace(&mut self.texture, texture)
}
/// Returns current texture of the animation.
- pub fn texture(&self) -> Option {
+ pub fn texture(&self) -> Option {
self.texture.clone()
}
@@ -510,7 +510,7 @@ impl SpriteSheetAnimation {
#[cfg(test)]
mod test {
- use crate::animation::spritesheet::{
+ use crate::spritesheet::{
signal::Signal, Event, ImageParameters, SpriteSheetAnimation, Status,
};
use fyrox_core::algebra::Vector2;
diff --git a/src/animation/spritesheet/signal.rs b/fyrox-animation/src/spritesheet/signal.rs
similarity index 100%
rename from src/animation/spritesheet/signal.rs
rename to fyrox-animation/src/spritesheet/signal.rs
diff --git a/src/animation/track.rs b/fyrox-animation/src/track.rs
similarity index 91%
rename from src/animation/track.rs
rename to fyrox-animation/src/track.rs
index 62648401c..13c504e8d 100644
--- a/src/animation/track.rs
+++ b/fyrox-animation/src/track.rs
@@ -1,13 +1,11 @@
//! Track is responsible in animating a property of a single scene node. See [`Track`] docs for more info.
use crate::{
- animation::{
- container::{TrackDataContainer, TrackValueKind},
- value::{BoundValue, ValueBinding},
- },
- core::{pool::Handle, reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
- scene::node::Node,
+ container::{TrackDataContainer, TrackValueKind},
+ core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
+ value::{BoundValue, ValueBinding},
};
+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
@@ -18,7 +16,7 @@ pub struct Track {
binding: ValueBinding,
frames: TrackDataContainer,
enabled: bool,
- target: Handle,
+ target: ErasedHandle,
id: Uuid,
}
@@ -88,7 +86,7 @@ impl Track {
}
/// Sets target of the track.
- pub fn with_target(mut self, target: Handle) -> Self {
+ pub fn with_target(mut self, target: ErasedHandle) -> Self {
self.target = target;
self
}
@@ -104,12 +102,12 @@ impl Track {
}
/// Sets a handle of a node that will be animated.
- pub fn set_target(&mut self, target: Handle) {
- self.target = target;
+ pub fn set_target>(&mut self, target: H) {
+ self.target = target.into();
}
/// Returns a handle of a node that will be animated.
- pub fn target(&self) -> Handle {
+ pub fn target(&self) -> ErasedHandle {
self.target
}
diff --git a/src/animation/value.rs b/fyrox-animation/src/value.rs
similarity index 77%
rename from src/animation/value.rs
rename to fyrox-animation/src/value.rs
index 6ced615ae..d0c4de915 100644
--- a/src/animation/value.rs
+++ b/fyrox-animation/src/value.rs
@@ -1,16 +1,12 @@
//! A module that contains everything related to numeric values of animation tracks. See [`TrackValue`] docs
//! for more info.
-use crate::{
- core::{
- algebra::{UnitQuaternion, Vector2, Vector3, Vector4},
- log::Log,
- math::lerpf,
- num_traits::AsPrimitive,
- reflect::{prelude::*, SetFieldByPathError},
- visitor::prelude::*,
- },
- scene::node::Node,
+use crate::core::{
+ algebra::{UnitQuaternion, Vector2, Vector3, Vector4},
+ math::lerpf,
+ num_traits::AsPrimitive,
+ reflect::prelude::*,
+ visitor::prelude::*,
};
use std::fmt::{Debug, Display, Formatter};
@@ -327,67 +323,4 @@ impl BoundValueCollection {
}
}
}
-
- /// Tries to set each value from the collection to the respective property (by binding) of the given scene node.
- pub fn apply(&self, node_ref: &mut Node) {
- for bound_value in self.values.iter() {
- match bound_value.binding {
- ValueBinding::Position => {
- if let TrackValue::Vector3(v) = bound_value.value {
- node_ref.local_transform_mut().set_position(v);
- } else {
- Log::err(
- "Unable to apply position, because underlying type is not Vector3!",
- )
- }
- }
- ValueBinding::Scale => {
- if let TrackValue::Vector3(v) = bound_value.value {
- node_ref.local_transform_mut().set_scale(v);
- } else {
- Log::err("Unable to apply scaling, because underlying type is not Vector3!")
- }
- }
- ValueBinding::Rotation => {
- if let TrackValue::UnitQuaternion(v) = bound_value.value {
- node_ref.local_transform_mut().set_rotation(v);
- } else {
- Log::err("Unable to apply rotation, because underlying type is not UnitQuaternion!")
- }
- }
- ValueBinding::Property {
- name: ref property_name,
- value_type,
- } => {
- if let Some(casted) = bound_value.value.numeric_type_cast(value_type) {
- let mut casted = Some(casted);
- node_ref.as_reflect_mut(&mut |node_ref| {
- node_ref.set_field_by_path(
- property_name,
- casted.take().unwrap(),
- &mut |result| {
- if let Err(err) = result {
- match err {
- SetFieldByPathError::InvalidPath { reason, .. } => {
- Log::err(format!(
- "Failed to set property {}! Invalid path: {}",
- property_name, reason
- ));
- }
- SetFieldByPathError::InvalidValue(_) => {
- Log::err(format!(
- "Failed to set property {}! Types mismatch!",
- property_name
- ));
- }
- }
- }
- },
- )
- })
- }
- }
- }
- }
- }
}
diff --git a/fyrox-core/src/lib.rs b/fyrox-core/src/lib.rs
index 561dc134c..15724590d 100644
--- a/fyrox-core/src/lib.rs
+++ b/fyrox-core/src/lib.rs
@@ -455,6 +455,32 @@ impl Default for PhantomDataSendSync {
}
}
+/// A trait for entities that have name.
+pub trait NameProvider {
+ /// Returns a reference to the name of the entity.
+ fn name(&self) -> &str;
+}
+
+/// Tries to find an entity by its name in a series of entities produced by an iterator.
+pub fn find_by_name_ref<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a T)>
+where
+ T: NameProvider,
+ I: Iterator
- ,
+ S: AsRef,
+{
+ iter.find(|(_, value)| value.name() == name.as_ref())
+}
+
+/// Tries to find an entity by its name in a series of entities produced by an iterator.
+pub fn find_by_name_mut<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a mut T)>
+where
+ T: NameProvider,
+ I: Iterator
- ,
+ S: AsRef,
+{
+ iter.find(|(_, value)| value.name() == name.as_ref())
+}
+
#[cfg(test)]
mod test {
use std::path::Path;
diff --git a/src/lib.rs b/src/lib.rs
index 8ba3f2a60..38c021295 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,7 +9,7 @@
#![allow(clippy::from_over_into)]
#![allow(clippy::approx_constant)]
-pub mod animation;
+pub use fyrox_animation as animation;
pub mod engine;
pub mod material;
pub mod plugin;
diff --git a/src/resource/model/mod.rs b/src/resource/model/mod.rs
index 899058098..e2826f1cf 100644
--- a/src/resource/model/mod.rs
+++ b/src/resource/model/mod.rs
@@ -42,6 +42,7 @@ use crate::{
Scene, SceneLoader,
},
};
+use fyrox_core::pool::ErasedHandle;
use fyrox_core::uuid_provider;
use fyrox_resource::io::ResourceIo;
use serde::{Deserialize, Serialize};
@@ -223,7 +224,8 @@ 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[ref_track.target()];
+ let ref_node =
+ &model.scene.graph[Handle::::from(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()) {
@@ -232,7 +234,7 @@ impl ModelResourceExtension for ModelResource {
track.set_target(instance_node);
}
None => {
- track.set_target(Handle::NONE);
+ track.set_target(ErasedHandle::default());
Log::writeln(
MessageKind::Error,
format!(
diff --git a/src/scene/animation/absm.rs b/src/scene/animation/absm.rs
index d7675105f..4b2f9cfa8 100644
--- a/src/scene/animation/absm.rs
+++ b/src/scene/animation/absm.rs
@@ -13,7 +13,7 @@ use crate::{
TypeUuidProvider,
},
scene::{
- animation::AnimationPlayer,
+ animation::{AnimationPlayer, AnimationPoseExt},
base::{Base, BaseBuilder},
graph::Graph,
node::{Node, NodeTrait, UpdateContext},
diff --git a/src/scene/animation/mod.rs b/src/scene/animation/mod.rs
index 5f77e0199..0f1602299 100644
--- a/src/scene/animation/mod.rs
+++ b/src/scene/animation/mod.rs
@@ -2,8 +2,12 @@
//! See [`AnimationPlayer`] docs for more info.
use crate::{
- animation::AnimationContainer,
+ animation::{
+ value::{BoundValueCollection, TrackValue, ValueBinding},
+ AnimationContainer, AnimationPose, NodePose,
+ },
core::{
+ log::{Log, MessageKind},
math::aabb::AxisAlignedBoundingBox,
pool::Handle,
reflect::prelude::*,
@@ -14,14 +18,173 @@ use crate::{
},
scene::{
base::{Base, BaseBuilder},
- graph::Graph,
+ graph::{Graph, NodePool},
node::{Node, NodeTrait, UpdateContext},
},
};
+use fyrox_animation::machine::LayerMask;
+use fyrox_core::pool::ErasedHandle;
use std::ops::{Deref, DerefMut};
pub mod absm;
+/// Extension trait for [`AnimationContainer`].
+pub trait AnimationContainerExt {
+ /// Updates all animations in the container and applies their poses to respective nodes. This method is intended to
+ /// be used only by the internals of the engine!
+ fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32);
+}
+
+impl AnimationContainerExt for AnimationContainer {
+ fn update_animations(&mut self, nodes: &mut NodePool, apply: bool, dt: f32) {
+ for animation in self.iter_mut().filter(|anim| anim.is_enabled()) {
+ animation.tick(dt);
+ if apply {
+ animation.pose().apply_internal(nodes);
+ }
+ }
+ }
+}
+
+/// Extension trait for [`AnimationPose`].
+pub trait AnimationPoseExt {
+ /// Tries to set each value to the each property from the animation pose to respective scene nodes.
+ fn apply_internal(&self, nodes: &mut NodePool);
+
+ /// Tries to set each value to the each property from the animation pose to respective scene nodes.
+ fn apply(&self, graph: &mut Graph);
+
+ /// Calls given callback function for each node and allows you to apply pose with your own
+ /// rules. This could be useful if you need to ignore transform some part of pose for a node.
+ fn apply_with(&self, graph: &mut Graph, callback: C)
+ where
+ C: FnMut(&mut Node, Handle, &NodePose);
+}
+
+impl AnimationPoseExt for AnimationPose {
+ fn apply_internal(&self, nodes: &mut NodePool) {
+ for (node, local_pose) in self.poses() {
+ if node.is_none() {
+ Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!");
+ } else if let Some(node) = nodes.try_borrow_mut(Handle::from(*node)) {
+ local_pose.values.apply(node);
+ }
+ }
+ }
+
+ fn apply(&self, graph: &mut Graph) {
+ for (node, local_pose) in self.poses() {
+ if node.is_none() {
+ Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!");
+ } else if let Some(node) = graph.try_get_mut(Handle::from(*node)) {
+ local_pose.values.apply(node);
+ }
+ }
+ }
+
+ fn apply_with(&self, graph: &mut Graph, mut callback: C)
+ where
+ C: FnMut(&mut Node, Handle, &NodePose),
+ {
+ for (node, local_pose) in self.poses() {
+ if node.is_none() {
+ Log::writeln(MessageKind::Error, "Invalid node handle found for animation pose, most likely it means that animation retargeting failed!");
+ } else if let Some(node_ref) = graph.try_get_mut(Handle::from(*node)) {
+ callback(node_ref, Handle::from(*node), local_pose);
+ }
+ }
+ }
+}
+
+/// Extension trait for [`BoundValueCollection`].
+pub trait BoundValueCollectionExt {
+ /// Tries to set each value from the collection to the respective property (by binding) of the given scene node.
+ fn apply(&self, node_ref: &mut Node);
+}
+
+impl BoundValueCollectionExt for BoundValueCollection {
+ fn apply(&self, node_ref: &mut Node) {
+ for bound_value in self.values.iter() {
+ match bound_value.binding {
+ ValueBinding::Position => {
+ if let TrackValue::Vector3(v) = bound_value.value {
+ node_ref.local_transform_mut().set_position(v);
+ } else {
+ Log::err(
+ "Unable to apply position, because underlying type is not Vector3!",
+ )
+ }
+ }
+ ValueBinding::Scale => {
+ if let TrackValue::Vector3(v) = bound_value.value {
+ node_ref.local_transform_mut().set_scale(v);
+ } else {
+ Log::err("Unable to apply scaling, because underlying type is not Vector3!")
+ }
+ }
+ ValueBinding::Rotation => {
+ if let TrackValue::UnitQuaternion(v) = bound_value.value {
+ node_ref.local_transform_mut().set_rotation(v);
+ } else {
+ Log::err("Unable to apply rotation, because underlying type is not UnitQuaternion!")
+ }
+ }
+ ValueBinding::Property {
+ name: ref property_name,
+ value_type,
+ } => {
+ if let Some(casted) = bound_value.value.numeric_type_cast(value_type) {
+ let mut casted = Some(casted);
+ node_ref.as_reflect_mut(&mut |node_ref| {
+ node_ref.set_field_by_path(
+ property_name,
+ casted.take().unwrap(),
+ &mut |result| {
+ if let Err(err) = result {
+ match err {
+ SetFieldByPathError::InvalidPath { reason, .. } => {
+ Log::err(format!(
+ "Failed to set property {}! Invalid path: {}",
+ property_name, reason
+ ));
+ }
+ SetFieldByPathError::InvalidValue(_) => {
+ Log::err(format!(
+ "Failed to set property {}! Types mismatch!",
+ property_name
+ ));
+ }
+ }
+ }
+ },
+ )
+ })
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Extension trait for [`LayerMask`].
+pub trait LayerMaskExt {
+ /// Creates a layer mask for every descendant node starting from specified `root` (included). It could
+ /// be useful if you have an entire node hierarchy (for example, lower part of a body) that needs to
+ /// be filtered out.
+ fn from_hierarchy(graph: &Graph, root: ErasedHandle) -> Self;
+}
+
+impl LayerMaskExt for LayerMask {
+ fn from_hierarchy(graph: &Graph, root: ErasedHandle) -> Self {
+ Self::from(
+ graph
+ .traverse_handle_iter(root.into())
+ .map(ErasedHandle::from)
+ .collect::>(),
+ )
+ }
+}
+
/// Animation player is a node that contains multiple animations. It updates and plays all the animations.
/// The node could be a source of animations for animation blending state machines. To learn more about
/// animations, see [`crate::animation::Animation`] docs.
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 629fa3fa1..5d3f1f160 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -782,32 +782,6 @@ pub fn into_any_arc(
}
}
-/// A trait for entities that have name.
-pub trait NameProvider {
- /// Returns a reference to the name of the entity.
- fn name(&self) -> &str;
-}
-
-/// Tries to find an entity by its name in a series of entities produced by an iterator.
-pub fn find_by_name_ref<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a T)>
-where
- T: NameProvider,
- I: Iterator
- ,
- S: AsRef,
-{
- iter.find(|(_, value)| value.name() == name.as_ref())
-}
-
-/// Tries to find an entity by its name in a series of entities produced by an iterator.
-pub fn find_by_name_mut<'a, T, I, S, K>(mut iter: I, name: S) -> Option<(K, &'a mut T)>
-where
- T: NameProvider,
- I: Iterator
- ,
- S: AsRef,
-{
- iter.find(|(_, value)| value.name() == name.as_ref())
-}
-
/// Converts `Vector3` -> `Vector3`.
pub fn vec3_f16_from_f32(v: Vector3) -> Vector3 {
v.map(f16::from_f32)
diff --git a/src/utils/navmesh.rs b/src/utils/navmesh.rs
index a472e4030..bacc089e2 100644
--- a/src/utils/navmesh.rs
+++ b/src/utils/navmesh.rs
@@ -965,7 +965,7 @@ mod test {
#[test]
fn test_navmesh() {
- let mut navmesh = Navmesh::new(
+ let navmesh = Navmesh::new(
vec![
TriangleDefinition([0, 1, 3]),
TriangleDefinition([1, 2, 3]),
@@ -989,7 +989,7 @@ mod test {
let mut agent = NavmeshAgent::new();
agent.set_target(Vector3::new(3.0, 0.0, 1.0));
- agent.update(1.0 / 60.0, &mut navmesh).unwrap();
+ agent.update(1.0 / 60.0, &navmesh).unwrap();
let graph = &navmesh.graph;