error handling for graph + fixes for the engine

- editor fixes on their way
This commit is contained in:
Dmitry Stepanov
2025-12-23 20:11:46 +03:00
parent 4b4c3e060f
commit 1e79298d60
62 changed files with 556 additions and 407 deletions
+7 -3
View File
@@ -41,6 +41,7 @@ use crate::{
};
use fxhash::FxHashMap;
pub use fyrox_core as core;
use fyrox_core::pool::PoolError;
use fyrox_resource::untyped::ResourceKind;
use fyrox_resource::{Resource, ResourceData};
pub use pose::{AnimationPose, NodePose};
@@ -1008,7 +1009,7 @@ impl<T: EntityId> AnimationContainer<T> {
/// Tries to remove an animation from the container by its handle.
#[inline]
pub fn remove(&mut self, handle: Handle<Animation<T>>) -> Option<Animation<T>> {
pub fn remove(&mut self, handle: Handle<Animation<T>>) -> Result<Animation<T>, PoolError> {
self.pool.try_free(handle)
}
@@ -1055,13 +1056,16 @@ impl<T: EntityId> AnimationContainer<T> {
/// Tries to borrow a reference to an animation in the container.
#[inline]
pub fn try_get(&self, handle: Handle<Animation<T>>) -> Option<&Animation<T>> {
pub fn try_get(&self, handle: Handle<Animation<T>>) -> Result<&Animation<T>, PoolError> {
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<T>>) -> Option<&mut Animation<T>> {
pub fn try_get_mut(
&mut self,
handle: Handle<Animation<T>>,
) -> Result<&mut Animation<T>, PoolError> {
self.pool.try_borrow_mut(handle)
}
+12 -12
View File
@@ -310,7 +310,7 @@ impl<T: EntityId> MachineLayer<T> {
animations: &AnimationContainer<T>,
strategy: AnimationEventCollectionStrategy,
) -> LayerAnimationEventsCollection<T> {
if let Some(state) = self.states.try_borrow(self.active_state) {
if let Ok(state) = self.states.try_borrow(self.active_state) {
return LayerAnimationEventsCollection {
source: AnimationEventsSource::State {
handle: self.active_state,
@@ -324,8 +324,8 @@ impl<T: EntityId> MachineLayer<T> {
})
.unwrap_or_default(),
};
} else if let Some(transition) = self.transitions.try_borrow(self.active_transition) {
if let (Some(source_state), Some(dest_state)) = (
} else if let Ok(transition) = self.transitions.try_borrow(self.active_transition) {
if let (Ok(source_state), Ok(dest_state)) = (
self.states.try_borrow(transition.source()),
self.states.try_borrow(transition.dest()),
) {
@@ -333,7 +333,7 @@ impl<T: EntityId> MachineLayer<T> {
match strategy {
AnimationEventCollectionStrategy::All => {
for state in [source_state, dest_state] {
if let Some(root) = self.nodes.try_borrow(state.root) {
if let Ok(root) = self.nodes.try_borrow(state.root) {
events.extend(root.collect_animation_events(
&self.nodes,
params,
@@ -350,7 +350,7 @@ impl<T: EntityId> MachineLayer<T> {
dest_state
};
if let Some(pose_source) = self.nodes.try_borrow(input.root) {
if let Ok(pose_source) = self.nodes.try_borrow(input.root) {
events = pose_source.collect_animation_events(
&self.nodes,
params,
@@ -366,7 +366,7 @@ impl<T: EntityId> MachineLayer<T> {
source_state
};
if let Some(pose_source) = self.nodes.try_borrow(input.root) {
if let Ok(pose_source) = self.nodes.try_borrow(input.root) {
events = pose_source.collect_animation_events(
&self.nodes,
params,
@@ -581,7 +581,7 @@ impl<T: EntityId> MachineLayer<T> {
animations: &AnimationContainer<T>,
) -> bool {
self.animations_of_state(state)
.filter_map(|a| animations.try_get(a))
.filter_map(|a| animations.try_get(a).ok())
.all(|a| a.has_ended())
}
@@ -610,7 +610,7 @@ impl<T: EntityId> MachineLayer<T> {
}
if transition.condition.calculate_value(parameters, animations) {
if let Some(active_state) = self.states.try_borrow(self.active_state) {
if let Ok(active_state) = self.states.try_borrow(self.active_state) {
for action in active_state.on_leave_actions.iter() {
action.apply(animations);
}
@@ -624,7 +624,7 @@ impl<T: EntityId> MachineLayer<T> {
);
}
if let Some(source) = self.states.try_borrow(transition.dest()) {
if let Ok(source) = self.states.try_borrow(transition.dest()) {
for action in source.on_enter_actions.iter() {
action.apply(animations);
}
@@ -654,11 +654,11 @@ impl<T: EntityId> MachineLayer<T> {
let transition = &mut self.transitions[self.active_transition];
// Blend between source and dest states.
if let Some(source_pose) = self.states[transition.source()].pose(&self.nodes) {
if let Ok(source_pose) = self.states[transition.source()].pose(&self.nodes) {
self.final_pose
.blend_with(&source_pose, 1.0 - transition.blend_factor());
}
if let Some(dest_pose) = self.states[transition.dest()].pose(&self.nodes) {
if let Ok(dest_pose) = self.states[transition.dest()].pose(&self.nodes) {
self.final_pose
.blend_with(&dest_pose, transition.blend_factor());
}
@@ -691,7 +691,7 @@ impl<T: EntityId> MachineLayer<T> {
} else {
// We must have active state all the time when we do not have any active transition.
// Just get pose from active state.
if let Some(active_state_pose) = self.states[self.active_state].pose(&self.nodes) {
if let Ok(active_state_pose) = self.states[self.active_state].pose(&self.nodes) {
active_state_pose.clone_into(&mut self.final_pose);
}
}
+3 -4
View File
@@ -332,21 +332,20 @@ impl<T: EntityId> Machine<T> {
self.animations_cache.clear();
for layer in self.layers.iter_mut() {
let mut states_to_check = [Some(layer.active_state()), None, None];
if let Some(active_transition) =
layer.transitions().try_borrow(layer.active_transition())
if let Ok(active_transition) = layer.transitions().try_borrow(layer.active_transition())
{
states_to_check[1] = Some(active_transition.source);
states_to_check[2] = Some(active_transition.dest);
}
for state_to_check in states_to_check.iter().flatten() {
if let Some(state) = layer.states().try_borrow(*state_to_check) {
if let Ok(state) = layer.states().try_borrow(*state_to_check) {
state.collect_animations(layer.nodes(), &mut self.animations_cache);
}
}
}
for animation_handle in self.animations_cache.iter() {
if let Some(animation) = animations.try_get_mut(*animation_handle) {
if let Ok(animation) = animations.try_get_mut(*animation_handle) {
if animation.is_enabled() {
animation.tick(dt);
}
+8 -8
View File
@@ -158,7 +158,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimations<T> {
}
};
if let Some(pose_source) = nodes
if let Ok(pose_source) = nodes
.try_borrow(blend_pose.pose_source)
.map(|pose_source| pose_source.eval_pose(nodes, params, animations, dt))
{
@@ -185,7 +185,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimations<T> {
AnimationEventCollectionStrategy::All => {
let mut events = Vec::new();
for pose in self.pose_sources.iter() {
if let Some(source) = nodes.try_borrow(pose.pose_source) {
if let Ok(source) = nodes.try_borrow(pose.pose_source) {
events.extend(
source.collect_animation_events(nodes, params, animations, strategy),
);
@@ -200,7 +200,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimations<T> {
.filter_map(|s| s.weight.value(params).map(|w| (s, w)))
.max_by(|(_, w1), (_, w2)| w1.partial_cmp(w2).unwrap_or(Ordering::Equal))
{
if let Some(pose_source) = nodes.try_borrow(pose.pose_source) {
if let Ok(pose_source) = nodes.try_borrow(pose.pose_source) {
return pose_source
.collect_animation_events(nodes, params, animations, strategy);
}
@@ -215,7 +215,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimations<T> {
.filter_map(|s| s.weight.value(params).map(|w| (s, w)))
.min_by(|(_, w1), (_, w2)| w1.partial_cmp(w2).unwrap_or(Ordering::Equal))
{
if let Some(pose_source) = nodes.try_borrow(pose.pose_source) {
if let Ok(pose_source) = nodes.try_borrow(pose.pose_source) {
return pose_source
.collect_animation_events(nodes, params, animations, strategy);
}
@@ -396,7 +396,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimationsByIndex<T> {
AnimationEventCollectionStrategy::All => {
let mut events = Vec::new();
for input in [prev_input, current_input] {
if let Some(source) = nodes.try_borrow(input.pose_source) {
if let Ok(source) = nodes.try_borrow(input.pose_source) {
events.extend(source.collect_animation_events(
nodes, params, animations, strategy,
));
@@ -411,7 +411,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimationsByIndex<T> {
current_input
};
if let Some(pose_source) = nodes.try_borrow(input.pose_source) {
if let Ok(pose_source) = nodes.try_borrow(input.pose_source) {
return pose_source.collect_animation_events(
nodes, params, animations, strategy,
);
@@ -424,7 +424,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimationsByIndex<T> {
prev_input
};
if let Some(pose_source) = nodes.try_borrow(input.pose_source) {
if let Ok(pose_source) = nodes.try_borrow(input.pose_source) {
return pose_source.collect_animation_events(
nodes, params, animations, strategy,
);
@@ -436,7 +436,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendAnimationsByIndex<T> {
// In case where the transition is done, all the strategies does the same - just collects events
// from active pose node.
if let Some(current_input) = self.inputs.get(current_index as usize) {
if let Some(pose_source) = nodes.try_borrow(current_input.pose_source) {
if let Ok(pose_source) = nodes.try_borrow(current_input.pose_source) {
return pose_source
.collect_animation_events(nodes, params, animations, strategy);
}
@@ -138,7 +138,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendSpace<T> {
let (ib, wb) = weights[1];
let (ic, wc) = weights[2];
if let (Some(pose_a), Some(pose_b), Some(pose_c)) = (
if let (Ok(pose_a), Ok(pose_b), Ok(pose_c)) = (
nodes.try_borrow(self.points[ia].pose_source),
nodes.try_borrow(self.points[ib].pose_source),
nodes.try_borrow(self.points[ic].pose_source),
@@ -173,7 +173,7 @@ impl<T: EntityId> AnimationPoseSource<T> for BlendSpace<T> {
let (ib, wb) = weights[1];
let (ic, wc) = weights[2];
if let (Some(pose_a), Some(pose_b), Some(pose_c)) = (
if let (Ok(pose_a), Ok(pose_b), Ok(pose_c)) = (
nodes.try_borrow(self.points[ia].pose_source),
nodes.try_borrow(self.points[ib].pose_source),
nodes.try_borrow(self.points[ic].pose_source),
+3 -3
View File
@@ -122,21 +122,21 @@ impl<T: EntityId> PoseNode<T> {
}
PoseNode::BlendAnimations(blend_animations) => {
for input in blend_animations.pose_sources.iter() {
if let Some(source) = nodes.try_borrow(input.pose_source) {
if let Ok(source) = nodes.try_borrow(input.pose_source) {
source.collect_animations(nodes, animations)
}
}
}
PoseNode::BlendAnimationsByIndex(blend_animations_by_index) => {
for input in blend_animations_by_index.inputs.iter() {
if let Some(source) = nodes.try_borrow(input.pose_source) {
if let Ok(source) = nodes.try_borrow(input.pose_source) {
source.collect_animations(nodes, animations)
}
}
}
PoseNode::BlendSpace(blend_space) => {
for point in blend_space.points() {
if let Some(source) = nodes.try_borrow(point.pose_source) {
if let Ok(source) = nodes.try_borrow(point.pose_source) {
source.collect_animations(nodes, animations)
}
}
+1 -1
View File
@@ -89,7 +89,7 @@ impl<T: EntityId> AnimationPoseSource<T> for PlayAnimation<T> {
animations: &AnimationContainer<T>,
_dt: f32,
) -> Ref<AnimationPose<T>> {
if let Some(animation) = animations.try_get(self.animation) {
if let Ok(animation) = animations.try_get(self.animation) {
let mut output_pose = self.output_pose.borrow_mut();
animation.pose().clone_into(&mut output_pose);
// Pass the root motion (if any) so it will be blended correctly.
+11 -7
View File
@@ -32,6 +32,7 @@ use crate::{
Animation, AnimationContainer, AnimationPose, EntityId,
};
use fxhash::FxHashSet;
use fyrox_core::pool::PoolError;
use fyrox_core::uuid::{uuid, Uuid};
use fyrox_core::{NameProvider, TypeUuidProvider};
use std::{
@@ -100,23 +101,23 @@ impl<T: EntityId> StateAction<T> {
match self {
StateAction::None => {}
StateAction::RewindAnimation(animation) => {
if let Some(animation) = animations.try_get_mut(*animation) {
if let Ok(animation) = animations.try_get_mut(*animation) {
animation.rewind();
}
}
StateAction::EnableAnimation(animation) => {
if let Some(animation) = animations.try_get_mut(*animation) {
if let Ok(animation) = animations.try_get_mut(*animation) {
animation.set_enabled(true);
}
}
StateAction::DisableAnimation(animation) => {
if let Some(animation) = animations.try_get_mut(*animation) {
if let Ok(animation) = animations.try_get_mut(*animation) {
animation.set_enabled(false);
}
}
StateAction::EnableRandomAnimation(animation_handles) => {
if let Some(animation) = animation_handles.iter().choose(&mut rand::thread_rng()) {
if let Some(animation) = animations.try_get_mut(*animation) {
if let Ok(animation) = animations.try_get_mut(*animation) {
animation.set_enabled(true);
}
}
@@ -167,7 +168,10 @@ impl<T: EntityId> State<T> {
}
/// Returns a final pose of the state.
pub fn pose<'a>(&self, nodes: &'a Pool<PoseNode<T>>) -> Option<Ref<'a, AnimationPose<T>>> {
pub fn pose<'a>(
&self,
nodes: &'a Pool<PoseNode<T>>,
) -> Result<Ref<'a, AnimationPose<T>>, PoolError> {
nodes.try_borrow(self.root).map(|root| root.pose())
}
@@ -177,7 +181,7 @@ impl<T: EntityId> State<T> {
nodes: &Pool<PoseNode<T>>,
animations: &mut FxHashSet<Handle<Animation<T>>>,
) {
if let Some(root) = nodes.try_borrow(self.root) {
if let Ok(root) = nodes.try_borrow(self.root) {
root.collect_animations(nodes, animations);
}
}
@@ -189,7 +193,7 @@ impl<T: EntityId> State<T> {
animations: &AnimationContainer<T>,
dt: f32,
) {
if let Some(root) = nodes.try_borrow(self.root) {
if let Ok(root) = nodes.try_borrow(self.root) {
root.eval_pose(nodes, params, animations, dt);
}
}
+4 -3
View File
@@ -436,9 +436,10 @@ impl<T: EntityId> LogicNode<T> {
lhs_value ^ rhs_value
}
LogicNode::Not(node) => !node.lhs.calculate_value(parameters, animations),
LogicNode::IsAnimationEnded(animation) => {
animations.try_get(*animation).is_none_or(|a| a.has_ended())
}
LogicNode::IsAnimationEnded(animation) => animations
.try_get(*animation)
.ok()
.is_none_or(|a| a.has_ended()),
}
}
}
+47 -60
View File
@@ -427,21 +427,21 @@ where
}
}
#[derive(PartialEq)]
pub enum PoolError<T> {
#[derive(PartialEq, Copy, Clone)]
pub enum PoolError {
InvalidIndex(u32),
InvalidGeneration(u32),
InvalidType(Handle<T>),
Empty(Handle<T>),
NoSuchComponent(Handle<T>),
MutablyBorrowed(Handle<T>),
ImmutablyBorrowed(Handle<T>),
UnknownDependentObject(Handle<T>),
InvalidType(ErasedHandle),
Empty(ErasedHandle),
NoSuchComponent(ErasedHandle),
MutablyBorrowed(ErasedHandle),
ImmutablyBorrowed(ErasedHandle),
UnknownDependentObject(ErasedHandle),
}
impl<T> std::error::Error for PoolError<T> {}
impl std::error::Error for PoolError {}
impl<T> Display for PoolError<T> {
impl Display for PoolError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidIndex(index) => {
@@ -495,7 +495,7 @@ impl<T> Display for PoolError<T> {
}
}
impl<T> Debug for PoolError<T> {
impl Debug for PoolError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
}
@@ -526,33 +526,33 @@ where
u32::try_from(self.records.len()).expect("Number of records overflowed u32")
}
fn records_get(&self, index: u32) -> Result<&PoolRecord<T, P>, PoolError<T>> {
fn records_get(&self, index: u32) -> Result<&PoolRecord<T, P>, PoolError> {
self.records
.get(usize::try_from(index).expect("Index overflowed usize"))
.ok_or(PoolError::InvalidIndex(index))
}
fn records_get_mut(&mut self, index: u32) -> Result<&mut PoolRecord<T, P>, PoolError<T>> {
fn records_get_mut(&mut self, index: u32) -> Result<&mut PoolRecord<T, P>, PoolError> {
self.records
.get_mut(usize::try_from(index).expect("Index overflowed usize"))
.ok_or(PoolError::InvalidIndex(index))
}
#[inline]
pub fn try_get<U: ObjectOrVariant<T>>(&self, handle: Handle<U>) -> Result<&U, PoolError<T>> {
pub fn try_get<U: ObjectOrVariant<T>>(&self, handle: Handle<U>) -> Result<&U, PoolError> {
let handle = handle.transmute();
let pool_object = self.try_borrow(handle)?;
U::convert_to_dest_type(pool_object).ok_or(PoolError::InvalidType(handle))
U::convert_to_dest_type(pool_object).ok_or(PoolError::InvalidType(handle.into()))
}
#[inline]
pub fn try_get_mut<U: ObjectOrVariant<T>>(
&mut self,
handle: Handle<U>,
) -> Result<&mut U, PoolError<T>> {
) -> Result<&mut U, PoolError> {
let handle = handle.transmute();
let pool_object = self.try_borrow_mut(handle)?;
U::convert_to_dest_type_mut(pool_object).ok_or(PoolError::InvalidType(handle))
U::convert_to_dest_type_mut(pool_object).ok_or(PoolError::InvalidType(handle.into()))
}
#[inline]
@@ -830,10 +830,10 @@ where
/// generation of pool record at handle index (in other words it means that object
/// at handle's index is different than the object was there before).
#[inline]
pub fn try_borrow(&self, handle: Handle<T>) -> Result<&T, PoolError<T>> {
pub fn try_borrow(&self, handle: Handle<T>) -> Result<&T, PoolError> {
self.records_get(handle.index).and_then(|r| {
if r.generation == handle.generation {
r.payload.as_ref().ok_or(PoolError::Empty(handle))
r.payload.as_ref().ok_or(PoolError::Empty(handle.into()))
} else {
Err(PoolError::InvalidGeneration(handle.generation))
}
@@ -846,10 +846,10 @@ where
/// generation of pool record at handle index (in other words it means that object
/// at handle's index is different than the object was there before).
#[inline]
pub fn try_borrow_mut(&mut self, handle: Handle<T>) -> Result<&mut T, PoolError<T>> {
pub fn try_borrow_mut(&mut self, handle: Handle<T>) -> Result<&mut T, PoolError> {
self.records_get_mut(handle.index).and_then(|r| {
if r.generation == handle.generation {
r.payload.as_mut().ok_or(PoolError::Empty(handle))
r.payload.as_mut().ok_or(PoolError::Empty(handle.into()))
} else {
Err(PoolError::InvalidGeneration(handle.generation))
}
@@ -981,7 +981,7 @@ where
&mut self,
handle: Handle<T>,
func: F,
) -> (Result<&mut T, PoolError<T>>, Result<&mut T, PoolError<T>>)
) -> (Result<&mut T, PoolError>, Result<&mut T, PoolError>)
where
F: FnOnce(&T) -> Handle<T>,
{
@@ -992,11 +992,11 @@ where
if second_handle != handle {
return (first, this.try_borrow_mut(second_handle));
} else {
return (first, Err(PoolError::MutablyBorrowed(second_handle)));
return (first, Err(PoolError::MutablyBorrowed(second_handle.into())));
}
}
(first, Err(PoolError::UnknownDependentObject(handle)))
(first, Err(PoolError::UnknownDependentObject(handle.into())))
}
/// Moves object out of the pool using the given handle. All handles to the object will become invalid.
@@ -1006,33 +1006,14 @@ where
/// Panics if the given handle is invalid.
#[inline]
pub fn free(&mut self, handle: Handle<T>) -> T {
let index = usize::try_from(handle.index).expect("index overflowed usize");
if let Some(record) = self.records.get_mut(index) {
if record.generation == handle.generation {
// Remember this index as free
self.free_stack.push(handle.index);
// Return current payload.
if let Some(payload) = record.payload.take() {
payload
} else {
panic!("Attempt to double free object at handle {handle:?}!");
}
} else {
panic!(
"Attempt to free object using dangling handle {:?}! Record generation is {}",
handle, record.generation
);
}
} else {
panic!("Attempt to free destroyed object using out-of-bounds handle {:?}! Record count is {}", handle, self.records.len());
}
self.try_free(handle).unwrap()
}
/// Tries to move object out of the pool using the given handle. Returns None if given handle
/// is invalid. After object is moved out if the pool, all handles to the object will become
/// invalid.
#[inline]
pub fn try_free(&mut self, handle: Handle<T>) -> Result<T, PoolError<T>> {
pub fn try_free(&mut self, handle: Handle<T>) -> Result<T, PoolError> {
let index = usize::try_from(handle.index).expect("index overflowed usize");
self.records
.get_mut(index)
@@ -1043,7 +1024,7 @@ where
self.free_stack.push(handle.index);
Ok(payload)
} else {
Err(PoolError::Empty(handle))
Err(PoolError::Empty(handle.into()))
}
} else {
Err(PoolError::InvalidGeneration(handle.generation))
@@ -1080,7 +1061,7 @@ where
///
/// [`take_reserve`]: Pool::take_reserve
#[inline]
pub fn try_take_reserve(&mut self, handle: Handle<T>) -> Result<(Ticket<T>, T), PoolError<T>> {
pub fn try_take_reserve(&mut self, handle: Handle<T>) -> Result<(Ticket<T>, T), PoolError> {
let record = self.records_get_mut(handle.index)?;
if record.generation == handle.generation {
if let Some(payload) = record.payload.take() {
@@ -1090,7 +1071,7 @@ where
};
Ok((ticket, payload))
} else {
Err(PoolError::Empty(handle))
Err(PoolError::Empty(handle.into()))
}
} else {
Err(PoolError::InvalidGeneration(handle.generation))
@@ -1143,21 +1124,21 @@ where
}
#[inline]
pub fn at_mut(&mut self, n: u32) -> Result<&mut T, PoolError<T>> {
pub fn at_mut(&mut self, n: u32) -> Result<&mut T, PoolError> {
self.records_get_mut(n).and_then(|rec| {
rec.payload
.as_mut()
.ok_or(PoolError::Empty(Handle::new(n, 0)))
.ok_or(PoolError::Empty(ErasedHandle::new(n, 0)))
})
}
#[inline]
pub fn at(&self, n: u32) -> Result<&T, PoolError<T>> {
pub fn at(&self, n: u32) -> Result<&T, PoolError> {
self.records_get(n).and_then(|rec| {
rec.payload
.get()
.as_ref()
.ok_or(PoolError::Empty(Handle::new(n, 0)))
.ok_or(PoolError::Empty(ErasedHandle::new(n, 0)))
})
}
@@ -1409,16 +1390,19 @@ where
{
/// Tries to mutably borrow an object and fetch its component of specified type.
#[inline]
pub fn try_get_component_of_type<C>(&self, handle: Handle<T>) -> Result<&C, PoolError<T>>
pub fn try_get_component_of_type<C>(&self, handle: Handle<T>) -> Result<&C, PoolError>
where
C: 'static,
{
self.try_borrow(handle)
.and_then(|n| {
n.query_component_ref(TypeId::of::<C>())
.ok_or(PoolError::NoSuchComponent(handle))
.ok_or(PoolError::NoSuchComponent(handle.into()))
})
.and_then(|c| {
c.downcast_ref()
.ok_or(PoolError::InvalidType(handle.into()))
})
.and_then(|c| c.downcast_ref().ok_or(PoolError::InvalidType(handle)))
}
/// Tries to mutably borrow an object and fetch its component of specified type.
@@ -1426,16 +1410,19 @@ where
pub fn try_get_component_of_type_mut<C>(
&mut self,
handle: Handle<T>,
) -> Result<&mut C, PoolError<T>>
) -> Result<&mut C, PoolError>
where
C: 'static,
{
self.try_borrow_mut(handle)
.and_then(|n| {
n.query_component_mut(TypeId::of::<C>())
.ok_or(PoolError::NoSuchComponent(handle))
.ok_or(PoolError::NoSuchComponent(handle.into()))
})
.and_then(|c| {
c.downcast_mut()
.ok_or(PoolError::InvalidType(handle.into()))
})
.and_then(|c| c.downcast_mut().ok_or(PoolError::InvalidType(handle)))
}
}
@@ -1752,7 +1739,7 @@ mod test {
let handle = pool.spawn(Payload);
assert_eq!(pool.try_free(handle), Ok(Payload));
assert_eq!(pool.free_stack.len(), 1);
assert_eq!(pool.try_free(handle), Err(PoolError::Empty(handle)));
assert_eq!(pool.try_free(handle), Err(PoolError::Empty(handle.into())));
assert_eq!(pool.free_stack.len(), 1);
}
@@ -1849,7 +1836,7 @@ mod test {
assert_eq!(
pool.try_borrow_dependant_mut(a, |_| a),
(Ok(&mut 42), Err(PoolError::MutablyBorrowed(a)))
(Ok(&mut 42), Err(PoolError::MutablyBorrowed(a.into())))
);
}
+27 -24
View File
@@ -163,10 +163,10 @@ where
&'b self,
handle: Handle<T>,
func: F,
) -> Result<Ref<'a, 'b, C>, PoolError<T>>
) -> Result<Ref<'a, 'b, C>, PoolError>
where
C: ?Sized,
F: FnOnce(&T) -> Result<&C, PoolError<T>>,
F: FnOnce(&T) -> Result<&C, PoolError>,
{
let record = self.pool.records_get(handle.index)?;
@@ -176,14 +176,14 @@ where
let current_ref_count = unsafe { record.ref_counter.get() };
if current_ref_count < 0 {
return Err(PoolError::MutablyBorrowed(handle));
return Err(PoolError::MutablyBorrowed(handle.into()));
}
// SAFETY: We've enforced borrowing rules by the previous check.
let payload_container = unsafe { &*record.payload.0.get() };
let Some(payload) = payload_container.as_ref() else {
return Err(PoolError::Empty(handle));
return Err(PoolError::Empty(handle.into()));
};
unsafe {
@@ -206,7 +206,7 @@ where
/// in the internal handles storage) - in this case you must increase `N`.
/// 3) A given handle is invalid.
#[inline]
pub fn try_get<'b: 'a>(&'b self, handle: Handle<T>) -> Result<Ref<'a, 'b, T>, PoolError<T>> {
pub fn try_get<'b: 'a>(&'b self, handle: Handle<T>) -> Result<Ref<'a, 'b, T>, PoolError> {
self.try_get_internal(handle, |obj| Ok(obj))
}
@@ -220,10 +220,10 @@ where
&'b self,
handle: Handle<T>,
func: F,
) -> Result<RefMut<'a, 'b, C>, PoolError<T>>
) -> Result<RefMut<'a, 'b, C>, PoolError>
where
C: ?Sized,
F: FnOnce(&mut T) -> Result<&mut C, PoolError<T>>,
F: FnOnce(&mut T) -> Result<&mut C, PoolError>,
{
let record = self.pool.records_get(handle.index)?;
@@ -236,10 +236,10 @@ where
let current_ref_count = unsafe { record.ref_counter.get() };
match current_ref_count.cmp(&0) {
Ordering::Less => {
return Err(PoolError::MutablyBorrowed(handle));
return Err(PoolError::MutablyBorrowed(handle.into()));
}
Ordering::Greater => {
return Err(PoolError::ImmutablyBorrowed(handle));
return Err(PoolError::ImmutablyBorrowed(handle.into()));
}
_ => (),
}
@@ -248,7 +248,7 @@ where
let payload_container = unsafe { &mut *record.payload.0.get() };
let Some(payload) = payload_container.as_mut() else {
return Err(PoolError::Empty(handle));
return Err(PoolError::Empty(handle.into()));
};
// SAFETY: It is safe to access the counter because of borrow checker guarantees that
@@ -268,7 +268,7 @@ where
pub fn try_get_mut<'b: 'a>(
&'b self,
handle: Handle<T>,
) -> Result<RefMut<'a, 'b, T>, PoolError<T>> {
) -> Result<RefMut<'a, 'b, T>, PoolError> {
self.try_get_mut_internal(handle, |obj| Ok(obj))
}
@@ -278,7 +278,7 @@ where
}
#[inline]
pub fn free(&self, handle: Handle<T>) -> Result<T, PoolError<T>> {
pub fn free(&self, handle: Handle<T>) -> Result<T, PoolError> {
let record = self.pool.records_get(handle.index)?;
if handle.generation != record.generation {
@@ -291,10 +291,10 @@ where
let current_ref_count = unsafe { record.ref_counter.get() };
match current_ref_count.cmp(&0) {
Ordering::Less => {
return Err(PoolError::MutablyBorrowed(handle));
return Err(PoolError::MutablyBorrowed(handle.into()));
}
Ordering::Greater => {
return Err(PoolError::ImmutablyBorrowed(handle));
return Err(PoolError::ImmutablyBorrowed(handle.into()));
}
_ => (),
}
@@ -303,7 +303,7 @@ where
let payload_container = unsafe { &mut *record.payload.0.get() };
let Some(payload) = payload_container.take() else {
return Err(PoolError::Empty(handle));
return Err(PoolError::Empty(handle.into()));
};
self.free_indices.borrow_mut().push(handle.index);
@@ -322,14 +322,14 @@ where
pub fn try_get_component_of_type<'b: 'a, C>(
&'b self,
handle: Handle<T>,
) -> Result<Ref<'a, 'b, C>, PoolError<T>>
) -> Result<Ref<'a, 'b, C>, PoolError>
where
C: 'static,
{
self.try_get_internal(handle, move |obj| {
obj.query_component_ref(TypeId::of::<C>())
.and_then(|c| c.downcast_ref())
.ok_or(PoolError::NoSuchComponent(handle))
.ok_or(PoolError::NoSuchComponent(handle.into()))
})
}
@@ -338,14 +338,14 @@ where
pub fn try_get_component_of_type_mut<'b: 'a, C>(
&'b self,
handle: Handle<T>,
) -> Result<RefMut<'a, 'b, C>, PoolError<T>>
) -> Result<RefMut<'a, 'b, C>, PoolError>
where
C: 'static,
{
self.try_get_mut_internal(handle, move |obj| {
obj.query_component_mut(TypeId::of::<C>())
.and_then(|c| c.downcast_mut())
.ok_or(PoolError::NoSuchComponent(handle))
.ok_or(PoolError::NoSuchComponent(handle.into()))
})
}
}
@@ -378,10 +378,13 @@ mod test {
// Test empty.
{
assert_eq!(ctx.try_get(d).as_deref(), Err(PoolError::Empty(d)).as_ref());
assert_eq!(
ctx.try_get(d).as_deref(),
Err(PoolError::Empty(d.into())).as_ref()
);
assert_eq!(
ctx.try_get_mut(d).as_deref_mut(),
Err(PoolError::Empty(d)).as_mut()
Err(PoolError::Empty(d.into())).as_mut()
);
}
@@ -404,7 +407,7 @@ mod test {
assert_eq!(ref_a_2.as_deref(), Ok(&val_a));
assert_eq!(
ctx.try_get_mut(a).as_deref(),
Err(PoolError::ImmutablyBorrowed(a)).as_ref()
Err(PoolError::ImmutablyBorrowed(a.into())).as_ref()
);
drop(ref_a_1);
@@ -433,7 +436,7 @@ mod test {
assert_eq!(ref_b_1.as_deref_mut(), Ok(&mut val_b));
assert_eq!(
ref_b_2.as_deref_mut(),
Err(PoolError::MutablyBorrowed(b)).as_mut()
Err(PoolError::MutablyBorrowed(b.into())).as_mut()
);
let mut ref_c_1 = ctx.try_get_mut(c);
@@ -441,7 +444,7 @@ mod test {
assert_eq!(ref_c_1.as_deref_mut(), Ok(&mut val_c));
assert_eq!(
ref_c_2.as_deref_mut(),
Err(PoolError::MutablyBorrowed(c)).as_mut()
Err(PoolError::MutablyBorrowed(c.into())).as_mut()
);
}
}
+1 -1
View File
@@ -697,7 +697,7 @@ impl Visitor {
/// The name of the current region. This should never be None if the Visitor is operating normally,
/// because there should be no way to leave the initial `__ROOT__` region.
pub fn current_region(&self) -> Result<&str, PoolError<VisitorNode>> {
pub fn current_region(&self) -> Result<&str, PoolError> {
self.nodes
.try_borrow(self.current_node)
.map(|n| n.name.as_str())
+65 -34
View File
@@ -29,7 +29,7 @@ pub mod prelude {
}
use fxhash::FxHashMap;
use fyrox_core::pool::{ErasedHandle, ObjectOrVariant, PayloadContainer};
use fyrox_core::pool::{ErasedHandle, ObjectOrVariant, PayloadContainer, PoolError};
use fyrox_core::reflect::ReflectHandle;
use fyrox_core::{
log::{Log, MessageKind},
@@ -679,11 +679,14 @@ impl<N> Default for LinkScheme<N> {
}
pub trait AbstractSceneGraph: 'static {
fn try_get_node_untyped(&self, handle: ErasedHandle) -> Option<&dyn AbstractSceneNode>;
fn try_get_node_untyped(
&self,
handle: ErasedHandle,
) -> Result<&dyn AbstractSceneNode, PoolError>;
fn try_get_node_untyped_mut(
&mut self,
handle: ErasedHandle,
) -> Option<&mut dyn AbstractSceneNode>;
) -> Result<&mut dyn AbstractSceneNode, PoolError>;
}
/// BaseSceneGraph is a dyn-compatible trait for all scene graphs to implement.
@@ -698,13 +701,13 @@ pub trait BaseSceneGraph: AbstractSceneGraph {
fn summary(&self) -> String;
/// Returns actual type id of the node.
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Option<TypeId>;
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Result<TypeId, PoolError>;
/// Returns actual type name of the node.
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Option<&'static str>;
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Result<&'static str, PoolError>;
/// Returns a list of derived type ids of the node.
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Option<Vec<TypeId>>;
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Result<Vec<TypeId>, PoolError>;
/// Returns a handle of the root node of the graph.
fn root(&self) -> Handle<Self::Node>;
@@ -713,10 +716,13 @@ pub trait BaseSceneGraph: AbstractSceneGraph {
fn set_root(&mut self, root: Handle<Self::Node>);
/// Tries to borrow a node, returns Some(node) if the handle is valid, None - otherwise.
fn try_get_node(&self, handle: Handle<Self::Node>) -> Option<&Self::Node>;
fn try_get_node(&self, handle: Handle<Self::Node>) -> Result<&Self::Node, PoolError>;
/// Tries to borrow a node, returns Some(node) if the handle is valid, None - otherwise.
fn try_get_node_mut(&mut self, handle: Handle<Self::Node>) -> Option<&mut Self::Node>;
fn try_get_node_mut(
&mut self,
handle: Handle<Self::Node>,
) -> Result<&mut Self::Node, PoolError>;
/// Checks whether the given node handle is valid or not.
fn is_valid_handle(&self, handle: Handle<Self::Node>) -> bool;
@@ -854,33 +860,48 @@ pub trait SceneGraph: BaseSceneGraph {
/// of nodes. It does *not* perform any tree traversal!
fn linear_iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Node>;
fn try_get<U: ObjectOrVariant<Self::ObjectType>>(&self, handle: Handle<U>) -> Option<&U>;
fn try_get<U: ObjectOrVariant<Self::ObjectType>>(
&self,
handle: Handle<U>,
) -> Result<&U, PoolError>;
fn try_get_mut<U: ObjectOrVariant<Self::ObjectType>>(
&mut self,
handle: Handle<U>,
) -> Option<&mut U>;
) -> Result<&mut U, PoolError>;
/// Tries to borrow a node and fetch its component of specified type.
#[inline]
fn try_get_of_type<T>(&self, handle: Handle<Self::Node>) -> Option<&T>
fn try_get_of_type<T>(&self, handle: Handle<Self::Node>) -> Result<&T, PoolError>
where
T: 'static,
{
self.try_get_node(handle)
.and_then(|n| n.query_component_ref(TypeId::of::<T>()))
.and_then(|c| c.downcast_ref())
.and_then(|n| {
n.query_component_ref(TypeId::of::<T>())
.ok_or(PoolError::NoSuchComponent(handle.into()))
})
.and_then(|c| {
c.downcast_ref()
.ok_or(PoolError::InvalidType(handle.into()))
})
}
/// Tries to mutably borrow a node and fetch its component of specified type.
#[inline]
fn try_get_mut_of_type<T>(&mut self, handle: Handle<Self::Node>) -> Option<&mut T>
fn try_get_mut_of_type<T>(&mut self, handle: Handle<Self::Node>) -> Result<&mut T, PoolError>
where
T: 'static,
{
self.try_get_node_mut(handle)
.and_then(|n| n.query_component_mut(TypeId::of::<T>()))
.and_then(|c| c.downcast_mut())
.and_then(|n| {
n.query_component_mut(TypeId::of::<T>())
.ok_or(PoolError::NoSuchComponent(handle.into()))
})
.and_then(|c| {
c.downcast_mut()
.ok_or(PoolError::InvalidType(handle.into()))
})
}
/// Tries to borrow a node by the given handle and checks if it has a component of the specified
@@ -890,7 +911,7 @@ pub trait SceneGraph: BaseSceneGraph {
where
T: 'static,
{
self.try_get_of_type::<T>(handle).is_some()
self.try_get_of_type::<T>(handle).is_ok()
}
/// Searches for a node down the tree starting from the specified node using the specified closure. Returns a tuple
@@ -905,7 +926,7 @@ pub trait SceneGraph: BaseSceneGraph {
C: FnMut(&Self::Node) -> Option<&T>,
T: ?Sized,
{
self.try_get_node(root_node).and_then(|root| {
self.try_get_node(root_node).ok().and_then(|root| {
if let Some(x) = cmp(root) {
Some((root_node, x))
} else {
@@ -926,7 +947,7 @@ pub trait SceneGraph: BaseSceneGraph {
C: FnMut(&Self::Node) -> bool,
{
let mut handle = root_node;
while let Some(node) = self.try_get_node(handle) {
while let Ok(node) = self.try_get_node(handle) {
if cmp(node) {
return Some((handle, node));
}
@@ -985,7 +1006,7 @@ pub trait SceneGraph: BaseSceneGraph {
T: ?Sized,
{
let mut handle = root_node;
while let Some(node) = self.try_get_node(handle) {
while let Ok(node) = self.try_get_node(handle) {
if let Some(x) = cmp(node) {
return Some((handle, x));
}
@@ -1052,7 +1073,7 @@ pub trait SceneGraph: BaseSceneGraph {
where
C: FnMut(&Self::Node) -> bool,
{
self.try_get_node(root_node).and_then(|root| {
self.try_get_node(root_node).ok().and_then(|root| {
if cmp(root) {
Some((root_node, root))
} else {
@@ -1091,8 +1112,8 @@ pub trait SceneGraph: BaseSceneGraph {
child: Handle<Self::Node>,
offset: isize,
) -> Option<(Handle<Self::Node>, usize)> {
let parents_parent_handle = self.try_get_node(child)?.parent();
let parents_parent_ref = self.try_get_node(parents_parent_handle)?;
let parents_parent_handle = self.try_get_node(child).ok()?.parent();
let parents_parent_ref = self.try_get_node(parents_parent_handle).ok()?;
let position = parents_parent_ref.child_position(child)?;
Some((
parents_parent_handle,
@@ -1320,6 +1341,7 @@ pub trait SceneGraph: BaseSceneGraph {
.map(|resource_node| {
(resource_node, node.original_handle_in_resource())
})
.ok()
}
};
@@ -1464,7 +1486,7 @@ mod test {
AbstractSceneGraph, AbstractSceneNode, BaseSceneGraph, NodeHandleMap, NodeMapping,
PrefabData, SceneGraph, SceneGraphNode,
};
use fyrox_core::pool::{ObjectOrVariant, ObjectOrVariantHelper};
use fyrox_core::pool::{ObjectOrVariant, ObjectOrVariantHelper, PoolError};
use fyrox_core::{
define_as_any_trait,
pool::{ErasedHandle, Handle, PayloadContainer, Pool},
@@ -1795,7 +1817,10 @@ mod test {
}
impl AbstractSceneGraph for Graph {
fn try_get_node_untyped(&self, handle: ErasedHandle) -> Option<&dyn AbstractSceneNode> {
fn try_get_node_untyped(
&self,
handle: ErasedHandle,
) -> Result<&dyn AbstractSceneNode, PoolError> {
self.nodes
.try_borrow(handle.into())
.map(|n| n as &dyn AbstractSceneNode)
@@ -1804,7 +1829,7 @@ mod test {
fn try_get_node_untyped_mut(
&mut self,
handle: ErasedHandle,
) -> Option<&mut dyn AbstractSceneNode> {
) -> Result<&mut dyn AbstractSceneNode, PoolError> {
self.nodes
.try_borrow_mut(handle.into())
.map(|n| n as &mut dyn AbstractSceneNode)
@@ -1876,34 +1901,37 @@ mod test {
let parent_handle =
std::mem::replace(&mut self.nodes[node_handle].parent, Handle::NONE);
if let Some(parent) = self.nodes.try_borrow_mut(parent_handle) {
if let Ok(parent) = self.nodes.try_borrow_mut(parent_handle) {
if let Some(i) = parent.children().iter().position(|h| *h == node_handle) {
parent.children.remove(i);
}
}
}
fn try_get_node(&self, handle: Handle<Self::Node>) -> Option<&Self::Node> {
fn try_get_node(&self, handle: Handle<Self::Node>) -> Result<&Self::Node, PoolError> {
self.nodes.try_borrow(handle)
}
fn try_get_node_mut(&mut self, handle: Handle<Self::Node>) -> Option<&mut Self::Node> {
fn try_get_node_mut(
&mut self,
handle: Handle<Self::Node>,
) -> Result<&mut Self::Node, PoolError> {
self.nodes.try_borrow_mut(handle)
}
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Option<TypeId> {
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Result<TypeId, PoolError> {
self.nodes
.try_borrow(handle)
.map(|n| NodeAsAny::as_any(n.0.deref()).type_id())
}
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Option<Vec<TypeId>> {
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Result<Vec<TypeId>, PoolError> {
self.nodes
.try_borrow(handle)
.map(|n| n.0.deref().query_derived_types().to_vec())
}
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Option<&'static str> {
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Result<&'static str, PoolError> {
self.nodes
.try_borrow(handle)
.map(|n| n.0.deref().type_name())
@@ -1924,11 +1952,14 @@ mod test {
self.nodes.iter_mut()
}
fn try_get<U: ObjectOrVariant<Node>>(&self, handle: Handle<U>) -> Option<&U> {
fn try_get<U: ObjectOrVariant<Node>>(&self, handle: Handle<U>) -> Result<&U, PoolError> {
self.nodes.try_get(handle)
}
fn try_get_mut<U: ObjectOrVariant<Node>>(&mut self, handle: Handle<U>) -> Option<&mut U> {
fn try_get_mut<U: ObjectOrVariant<Node>>(
&mut self,
handle: Handle<U>,
) -> Result<&mut U, PoolError> {
self.nodes.try_get_mut(handle)
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ impl SceneState {
for index in 0..scene.graph.capacity() {
let handle = scene.graph.handle_from_index(index);
let Some(node) = scene.graph.try_get_node_mut(handle) else {
let Ok(node) = scene.graph.try_get_node_mut(handle) else {
continue;
};
+8 -7
View File
@@ -642,7 +642,7 @@ impl ScriptMessageDispatcher {
ScriptMessageKind::Hierarchical { root, routing } => match routing {
RoutingStrategy::Up => {
let mut node = root;
while let Some(node_ref) = scene.graph.try_get_node(node) {
while let Ok(node_ref) = scene.graph.try_get_node(node) {
let parent = node_ref.parent();
let mut context = ScriptMessageContext {
@@ -1188,7 +1188,7 @@ where
T: FnMut(&mut Script, &mut C),
C: UniversalScriptContext,
{
let Some(node) = context.node() else {
let Ok(node) = context.node() else {
// A node was destroyed.
return false;
};
@@ -1209,7 +1209,7 @@ where
func(&mut script, context);
match context.node() {
Some(node) => {
Ok(node) => {
let entry = node
.scripts
.get_mut(index)
@@ -1222,7 +1222,7 @@ where
entry.script = Some(script);
}
}
None => {
Err(_) => {
// If the node was deleted by the `func` call, we must send the script to destruction
// queue, not silently drop it.
context.destroy_script_deferred(script, index);
@@ -2032,8 +2032,8 @@ impl Engine {
.find(|e| e.handle == node_task_handler.scene_handle)
{
let payload = result.payload;
if let Some(scene) = self.scenes.try_get_mut(node_task_handler.scene_handle) {
if let Some(node) =
if let Ok(scene) = self.scenes.try_get_mut(node_task_handler.scene_handle) {
if let Ok(node) =
scene.graph.try_get_node_mut(node_task_handler.node_handle)
{
if let Some(mut script) = node
@@ -2062,7 +2062,7 @@ impl Engine {
},
);
if let Some(node) =
if let Ok(node) =
scene.graph.try_get_node_mut(node_task_handler.node_handle)
{
if let Some(entry) =
@@ -2129,6 +2129,7 @@ impl Engine {
while let Some(message) = self
.user_interfaces
.try_get_mut(ui)
.ok()
.and_then(|ui| ui.poll_message())
{
let mut context = PluginContext {
+1 -1
View File
@@ -897,7 +897,7 @@ impl RenderDataBundleStorage {
if let Some(lod_group) = node.lod_group() {
for level in lod_group.levels.iter() {
for &object in level.objects.iter() {
if let Some(object_ref) = graph.try_get_node(object) {
if let Ok(object_ref) = graph.try_get_node(object) {
let distance = observer_position
.translation
.metric_distance(&object_ref.global_position());
+2 -1
View File
@@ -115,6 +115,7 @@ impl TileBuffer {
fn inflated_world_aabb(graph: &Graph, object: Handle<Node>) -> Option<AxisAlignedBoundingBox> {
let mut aabb = graph
.try_get_node(object)
.ok()
.map(|node_ref| node_ref.world_bounding_box())?;
aabb.inflate(Vector3::repeat(0.01));
Some(aabb)
@@ -228,7 +229,7 @@ impl OcclusionTester {
let mut lines = Vec::new();
for (object_index, object) in self.objects_to_test.iter().enumerate() {
let object_index = object_index as u32;
let Some(node_ref) = graph.try_get_node(*object) else {
let Ok(node_ref) = graph.try_get_node(*object) else {
continue;
};
+1 -1
View File
@@ -282,7 +282,7 @@ impl VisibilityCache {
/// Updates the cache by removing unused data.
pub fn update(&mut self, graph: &Graph) {
self.observers.retain(|observer, data| {
let Some(observer_ref) = graph.try_get_node(*observer) else {
let Ok(observer_ref) = graph.try_get_node(*observer) else {
return false;
};
@@ -66,6 +66,7 @@ impl FbxTexture {
if self.filename == PathBuf::default() {
components
.try_borrow(self.ancestor)
.ok()
.and_then(|parent| parent.as_texture().ok())
.map(|texture| texture.get_root_file_path(components))
.unwrap_or_default()
+1 -1
View File
@@ -111,7 +111,7 @@ impl ImportedTarget {
self.binding.value_binding()
}
fn value_in_graph(&self, graph: &Graph) -> Option<Box<[f32]>> {
let node: &Node = graph.try_get_node(self.handle)?;
let node: &Node = graph.try_get_node(self.handle).ok()?;
match self.binding {
ImportedBinding::Position => {
Some(node.local_transform().position().data.as_slice().into())
+3 -3
View File
@@ -170,13 +170,13 @@ fn get_ancestor_names<'a>(
fn get_ancestor_name(mut handle: Handle<Node>, depth: usize, graph: &Graph) -> Option<&str> {
for _ in 0..depth {
if let Some(n) = graph.try_get_node(handle) {
if let Ok(n) = graph.try_get_node(handle) {
handle = n.parent();
} else {
return None;
}
}
graph.try_get_node(handle).map(Node::name)
graph.try_get_node(handle).ok().map(Node::name)
}
fn contains_duplicate_name(names: &[&str]) -> bool {
@@ -192,7 +192,7 @@ fn contains_duplicate_name(names: &[&str]) -> bool {
fn count_ancestor_depth(mut handle: Handle<Node>, list: &[Handle<Node>], graph: &Graph) -> usize {
let mut count: usize = 0;
while let Some(node) = graph.try_get_node(handle) {
while let Ok(node) = graph.try_get_node(handle) {
handle = node.parent();
if list.contains(&handle) {
count += 1;
+5 -7
View File
@@ -41,7 +41,7 @@ use crate::{
},
};
use fyrox_graph::constructor::ConstructorProvider;
use fyrox_graph::{BaseSceneGraph, SceneGraph, SceneGraphNode};
use fyrox_graph::{BaseSceneGraph, SceneGraph};
use std::ops::{Deref, DerefMut};
/// Scene specific root motion settings.
@@ -312,10 +312,9 @@ impl NodeTrait for AnimationBlendingStateMachine {
}
fn update(&mut self, context: &mut UpdateContext) {
if let Some(animation_player) = context
if let Ok(animation_player) = context
.nodes
.try_borrow_mut(*self.animation_player)
.and_then(|n| n.component_mut::<AnimationPlayer>())
.try_get_component_of_type_mut::<AnimationPlayer>(*self.animation_player)
{
// Prevent animation player to apply animation to scene nodes. The animation will
// do than instead.
@@ -333,9 +332,8 @@ impl NodeTrait for AnimationBlendingStateMachine {
fn validate(&self, scene: &Scene) -> Result<(), String> {
if scene
.graph
.try_get_node(*self.animation_player)
.and_then(|n| n.component_ref::<AnimationPlayer>())
.is_none()
.try_get_of_type::<AnimationPlayer>(*self.animation_player)
.is_err()
{
Err(
"Animation player is not set or invalid! Animation blending state \
+3 -3
View File
@@ -109,7 +109,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) = nodes.try_borrow_mut(*node) {
} else if let Ok(node) = nodes.try_borrow_mut(*node) {
local_pose.values.apply(node);
}
}
@@ -119,7 +119,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_node_mut(*node) {
} else if let Ok(node) = graph.try_get_node_mut(*node) {
local_pose.values.apply(node);
}
}
@@ -132,7 +132,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_ref) = graph.try_get_node_mut(*node) {
} else if let Ok(node_ref) = graph.try_get_node_mut(*node) {
callback(node_ref, *node, local_pose);
}
}
+1 -1
View File
@@ -1181,7 +1181,7 @@ impl Base {
if let Some(resource) = self.resource.as_ref() {
let mut state = resource.state();
if let Some(model) = state.data() {
if let Some(ancestor_node) = model
if let Ok(ancestor_node) = model
.get_scene()
.graph
.try_get_node(self.original_handle_in_resource)
+3 -4
View File
@@ -50,7 +50,7 @@ use fyrox_core::algebra::{Isometry3, Translation3};
use fyrox_core::uuid_provider;
use fyrox_graph::constructor::ConstructorProvider;
use fyrox_graph::{BaseSceneGraph, SceneGraphNode};
use fyrox_graph::{BaseSceneGraph, SceneGraph};
use rapier3d::geometry::{self, ColliderHandle};
use std::fmt::Write;
use std::{
@@ -1044,9 +1044,8 @@ impl NodeTrait for Collider {
if scene
.graph
.try_get_node(self.parent())
.and_then(|p| p.component_ref::<RigidBody>())
.is_none()
.try_get_of_type::<RigidBody>(self.parent())
.is_err()
{
message += "3D Collider must be a direct child of a 3D Rigid Body node, \
otherwise it will not have any effect!";
+4 -4
View File
@@ -36,7 +36,7 @@ use crate::{
visitor::prelude::*,
ImmutableString, TypeUuidProvider,
},
graph::{BaseSceneGraph, SceneGraphNode},
graph::BaseSceneGraph,
scene::{
base::{Base, BaseBuilder},
collider::InteractionGroups,
@@ -51,6 +51,7 @@ use crate::{
};
use fyrox_graph::constructor::ConstructorProvider;
use fyrox_graph::SceneGraph;
use rapier2d::geometry::ColliderHandle;
use std::{
cell::Cell,
@@ -703,9 +704,8 @@ impl NodeTrait for Collider {
if scene
.graph
.try_get_node(self.parent())
.and_then(|p| p.component_ref::<RigidBody>())
.is_none()
.try_get_of_type::<RigidBody>(self.parent())
.is_err()
{
message += "2D Collider must be a direct child of a 3D Rigid Body node, \
otherwise it will not have any effect!";
+2 -2
View File
@@ -588,13 +588,13 @@ impl NodeTrait for Joint {
}
fn validate(&self, scene: &Scene) -> Result<(), String> {
if scene.graph.try_get(self.body1()).is_none() {
if scene.graph.try_get(self.body1()).is_err() {
return Err("2D Joint has invalid or unassigned handle to a \
first body, the joint will not operate!"
.to_string());
}
if scene.graph.try_get(self.body2()).is_none() {
if scene.graph.try_get(self.body2()).is_err() {
return Err("2D Joint has invalid or unassigned handle to a \
second body, the joint will not operate!"
.to_string());
+13 -12
View File
@@ -58,6 +58,7 @@ use crate::{
tilemap::TileMap,
},
};
use fyrox_graph::SceneGraph;
pub use rapier2d::geometry::shape::*;
use rapier2d::parry::query::DefaultQueryDispatcher;
use rapier2d::{
@@ -361,7 +362,10 @@ fn tile_map_to_collider_shape(
nodes: &NodePool,
collider_name: &ImmutableString,
) -> Option<SharedShape> {
let tile_map = nodes.try_borrow(tile_map.0)?.component_ref::<TileMap>()?;
let tile_map = nodes
.try_borrow(tile_map.0)
.ok()?
.component_ref::<TileMap>()?;
let tile_set_resource = tile_map.tile_set()?.data_ref();
let tile_set = tile_set_resource.as_loaded_ref()?;
@@ -847,13 +851,11 @@ impl PhysicsWorld {
}),
exclude_collider: filter
.exclude_collider
.and_then(|h| graph.try_get_node(h))
.and_then(|n| n.component_ref::<dim2::collider::Collider>())
.and_then(|h| graph.try_get_of_type::<dim2::collider::Collider>(h).ok())
.map(|c| c.native.get()),
exclude_rigid_body: filter
.exclude_collider
.and_then(|h| graph.try_get_node(h))
.and_then(|n| n.component_ref::<dim2::rigidbody::RigidBody>())
.and_then(|h| graph.try_get_of_type::<dim2::rigidbody::RigidBody>(h).ok())
.map(|c| c.native.get()),
predicate: Some(&predicate),
};
@@ -1163,9 +1165,8 @@ impl PhysicsWorld {
}
}
}
} else if let Some(parent_body) = nodes
.try_borrow(collider_node.parent())
.and_then(|n| n.cast::<dim2::rigidbody::RigidBody>())
} else if let Ok(parent_body) =
nodes.try_get_component_of_type::<dim2::rigidbody::RigidBody>(collider_node.parent())
{
if parent_body.native.get() != RigidBodyHandle::invalid() {
let rigid_body_native = parent_body.native.get();
@@ -1235,12 +1236,12 @@ impl PhysicsWorld {
if let Some(native) = self.joints.set.get_mut(joint.native.get(), false) {
joint.body1.try_sync_model(|v| {
if let Some(rigid_body_node) = nodes.try_get(v) {
if let Ok(rigid_body_node) = nodes.try_get(v) {
native.body1 = rigid_body_node.native.get();
}
});
joint.body2.try_sync_model(|v| {
if let Some(rigid_body_node) = nodes.try_get(v) {
if let Ok(rigid_body_node) = nodes.try_get(v) {
native.body2 = rigid_body_node.native.get();
}
});
@@ -1288,7 +1289,7 @@ impl PhysicsWorld {
});
let mut local_frames = joint.local_frames.borrow_mut();
if local_frames.is_none() {
if let (Some(body1), Some(body2)) =
if let (Ok(body1), Ok(body2)) =
(nodes.try_get(joint.body1()), nodes.try_get(joint.body2()))
{
let (local_frame1, local_frame2) = calculate_local_frames(joint, body1, body2);
@@ -1303,7 +1304,7 @@ impl PhysicsWorld {
let params = joint.params().clone();
// A native joint can be created iff both rigid bodies are correctly assigned.
if let (Some(body1), Some(body2)) =
if let (Ok(body1), Ok(body2)) =
(nodes.try_get(body1_handle), nodes.try_get(body2_handle))
{
let native_body1 = body1.native.get();
+2 -1
View File
@@ -511,6 +511,7 @@ impl NodeTrait for RigidBody {
context
.nodes
.try_borrow(self.parent)
.ok()
.map(|p| p.global_transform())
.unwrap_or_else(Matrix4::identity),
);
@@ -518,7 +519,7 @@ impl NodeTrait for RigidBody {
fn validate(&self, scene: &Scene) -> Result<(), String> {
for &child in self.children() {
if scene.graph.try_get_of_type::<Collider>(child).is_some() {
if scene.graph.try_get_of_type::<Collider>(child).is_ok() {
return Ok(());
}
}
+156 -62
View File
@@ -76,9 +76,9 @@ use crate::{
};
use bitflags::bitflags;
use fxhash::{FxHashMap, FxHashSet};
use fyrox_core::pool::ObjectOrVariant;
use fyrox_core::pool::{ObjectOrVariant, PoolError};
use fyrox_graph::SceneGraphNode;
use std::fmt::Write;
use std::fmt::{Display, Formatter, Write};
use std::ops::Deref;
use std::{
any::{Any, TypeId},
@@ -319,6 +319,63 @@ impl Default for GraphUpdateSwitches {
}
}
#[derive(PartialEq)]
pub enum GraphError {
PoolError(PoolError),
NoScript {
handle: Handle<Node>,
script_type_name: &'static str,
},
NoScriptComponent {
handle: Handle<Node>,
component_type_name: &'static str,
},
UnknownId(SceneNodeId),
}
impl Display for GraphError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GraphError::PoolError(err) => std::fmt::Display::fmt(&err, f),
GraphError::NoScript {
handle,
script_type_name,
} => {
write!(
f,
"There's no script {script_type_name} on the scene node {handle}"
)
}
GraphError::NoScriptComponent {
handle,
component_type_name,
} => {
write!(
f,
"There's no script component {component_type_name} on the scene node {handle}"
)
}
GraphError::UnknownId(id) => {
write!(f, "There's no scene node with {id:?} id!")
}
}
}
}
impl Debug for GraphError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
}
}
impl std::error::Error for GraphError {}
impl From<PoolError> for GraphError {
fn from(value: PoolError) -> Self {
Self::PoolError(value)
}
}
impl Graph {
/// Creates new graph instance with single root node.
#[inline]
@@ -412,7 +469,7 @@ impl Graph {
for _ in 0..indent {
result.push_str(" ");
}
let Some(node) = self.try_get(current) else {
let Ok(node) = self.try_get(current) else {
use std::fmt::Write;
writeln!(result, "{}: Failed to get", current).unwrap();
return;
@@ -481,8 +538,8 @@ impl Graph {
let (node, parent) = self
.pool
.try_borrow_dependant_mut(node_handle, |node| node.parent());
if let Some(node) = node {
if let Some(parent) = parent {
if let Ok(node) = node {
if let Ok(parent) = parent {
let relative_position = parent
.global_transform()
.try_inverse()
@@ -514,8 +571,8 @@ impl Graph {
let (node, parent) = self
.pool
.try_borrow_dependant_mut(node, |node| node.parent());
if let Some(node) = node {
if let Some(parent) = parent {
if let Ok(node) = node {
if let Ok(parent) = parent {
let basis = parent
.global_transform()
.try_inverse()
@@ -989,7 +1046,7 @@ impl Graph {
where
F: FnMut(Handle<Node>, &Node) -> bool,
{
graph.try_get_node(node).and_then(|n| {
graph.try_get_node(node).ok().and_then(|n| {
if filter(node, n) {
let mut aabb = n.local_bounding_box();
if aabb.is_invalid_or_degenerate() {
@@ -1014,12 +1071,13 @@ impl Graph {
}
pub(crate) fn update_enabled_flag_recursively(nodes: &NodePool, node_handle: Handle<Node>) {
let Some(node) = nodes.try_borrow(node_handle) else {
let Ok(node) = nodes.try_borrow(node_handle) else {
return;
};
let parent_enabled = nodes
.try_borrow(node.parent())
.ok()
.is_none_or(|p| p.is_globally_enabled());
node.global_enabled.set(parent_enabled && node.is_enabled());
@@ -1029,12 +1087,13 @@ impl Graph {
}
pub(crate) fn update_visibility_recursively(nodes: &NodePool, node_handle: Handle<Node>) {
let Some(node) = nodes.try_borrow(node_handle) else {
let Ok(node) = nodes.try_borrow(node_handle) else {
return;
};
let parent_visibility = nodes
.try_borrow(node.parent())
.ok()
.is_none_or(|p| p.global_visibility());
node.global_visibility
.set(parent_visibility && node.visibility());
@@ -1051,11 +1110,11 @@ impl Graph {
physics2d: &mut dim2::physics::PhysicsWorld,
node_handle: Handle<Node>,
) {
let Some(node) = nodes.try_borrow(node_handle) else {
let Ok(node) = nodes.try_borrow(node_handle) else {
return;
};
let parent_global_transform = if let Some(parent) = nodes.try_borrow(node.parent()) {
let parent_global_transform = if let Ok(parent) = nodes.try_borrow(node.parent()) {
parent.global_transform()
} else {
Matrix4::identity()
@@ -1161,7 +1220,7 @@ impl Graph {
while let Ok(message) = self.message_receiver.try_recv() {
if let NodeMessageKind::TransformChanged = message.kind {
if let Some(node) = self.pool.try_borrow(message.node) {
if let Ok(node) = self.pool.try_borrow(message.node) {
node.on_local_transform_changed(&mut SyncContext {
nodes: &self.pool,
physics: &mut self.physics,
@@ -1199,7 +1258,7 @@ impl Graph {
func: &mut impl FnMut(Handle<Node>),
) {
func(from);
if let Some(node) = graph.try_get_node(from) {
if let Ok(node) = graph.try_get_node(from) {
for &child in node.children() {
traverse_recursive(graph, child, func)
}
@@ -1264,7 +1323,7 @@ impl Graph {
dt: f32,
delete_dead_nodes: bool,
) {
if let Some((ticket, mut node)) = self.pool.try_take_reserve(handle) {
if let Ok((ticket, mut node)) = self.pool.try_take_reserve(handle) {
let mut is_alive = node.is_alive();
if node.is_globally_enabled() {
@@ -1650,7 +1709,7 @@ impl Graph {
#[inline]
pub fn global_scale(&self, mut node: Handle<Node>) -> Vector3<f32> {
let mut global_scale = Vector3::repeat(1.0);
while let Some(node_ref) = self.try_get_node(node) {
while let Ok(node_ref) = self.try_get_node(node) {
global_scale = global_scale.component_mul(node_ref.local_transform().scale());
node = node_ref.parent;
}
@@ -1660,12 +1719,16 @@ impl Graph {
/// Tries to borrow a node using the given handle and searches the script buffer for a script
/// of type T and cast the first script, that could be found to the specified type.
#[inline]
pub fn try_get_script_of<T>(&self, node: Handle<Node>) -> Option<&T>
pub fn try_get_script_of<T>(&self, handle: Handle<Node>) -> Result<&T, GraphError>
where
T: ScriptTrait,
{
self.try_get_node(node)
.and_then(|node| node.try_get_script::<T>())
let node = self.try_get_node(handle)?;
node.try_get_script::<T>()
.ok_or_else(|| GraphError::NoScript {
handle,
script_type_name: std::any::type_name::<T>(),
})
}
/// Tries to borrow a node and query all scripts of the given type `T`. This method returns
@@ -1674,55 +1737,75 @@ impl Graph {
#[inline]
pub fn try_get_scripts_of<T: ScriptTrait>(
&self,
node: Handle<Node>,
) -> Option<impl Iterator<Item = &T>> {
self.try_get_node(node).map(|n| n.try_get_scripts())
handle: Handle<Node>,
) -> Result<impl Iterator<Item = &T>, GraphError> {
let node = self.try_get_node(handle)?;
Ok(node.try_get_scripts())
}
/// Tries to borrow a node using the given handle and searches the script buffer for a script
/// of type T and cast the first script, that could be found to the specified type.
#[inline]
pub fn try_get_script_of_mut<T>(&mut self, node: Handle<Node>) -> Option<&mut T>
pub fn try_get_script_of_mut<T>(&mut self, handle: Handle<Node>) -> Result<&mut T, GraphError>
where
T: ScriptTrait,
{
self.try_get_node_mut(node)
.and_then(|node| node.try_get_script_mut::<T>())
let node = self.try_get_node_mut(handle)?;
node.try_get_script_mut::<T>()
.ok_or_else(|| GraphError::NoScript {
handle,
script_type_name: std::any::type_name::<T>(),
})
}
/// Tries to borrow a node and query all scripts of the given type `T`. This method returns
/// [`None`] if the given node handle is invalid, otherwise it returns an iterator over the
/// scripts of the type `T`.
#[inline]
pub fn try_get_scripts_of_mut<T: ScriptTrait>(
pub fn try_get_scripts_of_mut<T>(
&mut self,
node: Handle<Node>,
) -> Option<impl Iterator<Item = &mut T>> {
self.try_get_node_mut(node).map(|n| n.try_get_scripts_mut())
handle: Handle<Node>,
) -> Result<impl Iterator<Item = &mut T>, GraphError>
where
T: ScriptTrait,
{
let node = self.try_get_node_mut(handle)?;
Ok(node.try_get_scripts_mut())
}
/// Tries to borrow a node and find a component of the given type `C` across **all** available
/// scripts of the node. If you want to search a component `C` in a particular script, then use
/// [`Self::try_get_script_of`] and then search for component in it.
#[inline]
pub fn try_get_script_component_of<C>(&self, node: Handle<Node>) -> Option<&C>
pub fn try_get_script_component_of<C>(&self, handle: Handle<Node>) -> Result<&C, GraphError>
where
C: Any,
{
self.try_get_node(node)
.and_then(|node| node.try_get_script_component())
let node = self.try_get_node(handle)?;
node.try_get_script_component()
.ok_or_else(|| GraphError::NoScriptComponent {
handle,
component_type_name: std::any::type_name::<C>(),
})
}
/// Tries to borrow a node and find a component of the given type `C` across **all** available
/// scripts of the node. If you want to search a component `C` in a particular script, then use
/// [`Self::try_get_script_of_mut`] and then search for component in it.
#[inline]
pub fn try_get_script_component_of_mut<C>(&mut self, node: Handle<Node>) -> Option<&mut C>
pub fn try_get_script_component_of_mut<C>(
&mut self,
handle: Handle<Node>,
) -> Result<&mut C, GraphError>
where
C: Any,
{
self.try_get_node_mut(node)
.and_then(|node| node.try_get_script_component_mut())
let node = self.try_get_node_mut(handle)?;
node.try_get_script_component_mut()
.ok_or_else(|| GraphError::NoScriptComponent {
handle,
component_type_name: std::any::type_name::<C>(),
})
}
/// Returns a handle of the node that has the given id.
@@ -1731,17 +1814,22 @@ impl Graph {
}
/// Tries to borrow a node by its id.
pub fn node_by_id(&self, id: SceneNodeId) -> Option<(Handle<Node>, &Node)> {
pub fn node_by_id(&self, id: SceneNodeId) -> Result<(Handle<Node>, &Node), GraphError> {
self.instance_id_map
.get(&id)
.and_then(|h| self.pool.try_borrow(*h).map(|n| (*h, n)))
.ok_or_else(|| GraphError::UnknownId(id))
.and_then(|h| Ok(self.pool.try_borrow(*h).map(|n| (*h, n))?))
}
/// Tries to borrow a node by its id.
pub fn node_by_id_mut(&mut self, id: SceneNodeId) -> Option<(Handle<Node>, &mut Node)> {
pub fn node_by_id_mut(
&mut self,
id: SceneNodeId,
) -> Result<(Handle<Node>, &mut Node), GraphError> {
self.instance_id_map
.get(&id)
.and_then(|h| self.pool.try_borrow_mut(*h).map(|n| (*h, n)))
.ok_or_else(|| GraphError::UnknownId(id))
.and_then(|h| Ok(self.pool.try_borrow_mut(*h).map(|n| (*h, n))?))
}
}
@@ -1784,7 +1872,10 @@ impl Visit for Graph {
}
impl AbstractSceneGraph for Graph {
fn try_get_node_untyped(&self, handle: ErasedHandle) -> Option<&dyn AbstractSceneNode> {
fn try_get_node_untyped(
&self,
handle: ErasedHandle,
) -> Result<&dyn AbstractSceneNode, PoolError> {
self.pool
.try_borrow(handle.into())
.map(|n| n as &dyn AbstractSceneNode)
@@ -1793,7 +1884,7 @@ impl AbstractSceneGraph for Graph {
fn try_get_node_untyped_mut(
&mut self,
handle: ErasedHandle,
) -> Option<&mut dyn AbstractSceneNode> {
) -> Result<&mut dyn AbstractSceneNode, PoolError> {
self.pool
.try_borrow_mut(handle.into())
.map(|n| n as &mut dyn AbstractSceneNode)
@@ -1813,7 +1904,7 @@ impl BaseSceneGraph for Graph {
}
#[inline]
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Option<TypeId> {
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Result<TypeId, PoolError> {
self.pool
.try_borrow(handle)
.map(|n| NodeAsAny::as_any(n.0.deref()).type_id())
@@ -1919,7 +2010,7 @@ impl BaseSceneGraph for Graph {
let parent_handle = std::mem::replace(&mut self.pool[node_handle].parent, Handle::NONE);
// Remove child from parent's children list
if let Some(parent) = self.pool.try_borrow_mut(parent_handle) {
if let Ok(parent) = self.pool.try_borrow_mut(parent_handle) {
if let Some(i) = parent.children().iter().position(|h| *h == node_handle) {
parent.children.remove(i);
}
@@ -1931,22 +2022,25 @@ impl BaseSceneGraph for Graph {
}
#[inline]
fn try_get_node(&self, handle: Handle<Self::Node>) -> Option<&Self::Node> {
fn try_get_node(&self, handle: Handle<Self::Node>) -> Result<&Self::Node, PoolError> {
self.pool.try_borrow(handle)
}
#[inline]
fn try_get_node_mut(&mut self, handle: Handle<Self::Node>) -> Option<&mut Self::Node> {
fn try_get_node_mut(
&mut self,
handle: Handle<Self::Node>,
) -> Result<&mut Self::Node, PoolError> {
self.pool.try_borrow_mut(handle)
}
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Option<Vec<TypeId>> {
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Result<Vec<TypeId>, PoolError> {
self.pool
.try_borrow(handle)
.map(|n| Box::deref(&n.0).query_derived_types().to_vec())
}
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Option<&'static str> {
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Result<&'static str, PoolError> {
self.pool
.try_borrow(handle)
.map(|n| n.0.deref().type_name())
@@ -1970,11 +2064,14 @@ impl SceneGraph for Graph {
self.pool.iter_mut()
}
fn try_get<U: ObjectOrVariant<Node>>(&self, handle: Handle<U>) -> Option<&U> {
fn try_get<U: ObjectOrVariant<Node>>(&self, handle: Handle<U>) -> Result<&U, PoolError> {
self.pool.try_get(handle)
}
fn try_get_mut<U: ObjectOrVariant<Node>>(&mut self, handle: Handle<U>) -> Option<&mut U> {
fn try_get_mut<U: ObjectOrVariant<Node>>(
&mut self,
handle: Handle<U>,
) -> Result<&mut U, PoolError> {
self.pool.try_get_mut(handle)
}
}
@@ -2056,14 +2153,14 @@ mod test {
assert_eq!(
graph.try_get_script_of::<MyScript>(handle),
Some(&MyScript {
Ok(&MyScript {
foo: "Stuff".to_string(),
bar: 123.321,
})
);
assert_eq!(
graph.try_get_script_of_mut::<MyScript>(handle),
Some(&mut MyScript {
Ok(&mut MyScript {
foo: "Stuff".to_string(),
bar: 123.321,
})
@@ -2090,14 +2187,14 @@ mod test {
assert_eq!(
graph.try_get_script_of::<MyOtherScript>(handle),
Some(&MyOtherScript {
Ok(&MyOtherScript {
baz: 321,
foobar: vec![1, 2, 3],
})
);
assert_eq!(
graph.try_get_script_of_mut::<MyOtherScript>(handle),
Some(&mut MyOtherScript {
Ok(&mut MyOtherScript {
baz: 321,
foobar: vec![1, 2, 3],
})
@@ -2482,18 +2579,15 @@ mod test {
let pivot = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
let rigid_body = RigidBodyBuilder::new(BaseBuilder::new()).build(&mut graph);
assert!(graph.pool.try_get(pivot).is_some());
assert!(graph.pool.try_get(pivot.transmute::<Pivot>()).is_some());
assert!(graph.pool.try_get(pivot.transmute::<RigidBody>()).is_none());
assert!(graph.pool.try_get(pivot).is_ok());
assert!(graph.pool.try_get(pivot.transmute::<Pivot>()).is_ok());
assert!(graph.pool.try_get(pivot.transmute::<RigidBody>()).is_err());
assert!(graph.pool.try_get(rigid_body).is_some());
assert!(graph.pool.try_get(rigid_body).is_ok());
assert!(graph
.pool
.try_get(rigid_body.transmute::<RigidBody>())
.is_some());
assert!(graph
.pool
.try_get(rigid_body.transmute::<Pivot>())
.is_none());
.is_ok());
assert!(graph.pool.try_get(rigid_body.transmute::<Pivot>()).is_err());
}
}
+15 -16
View File
@@ -78,7 +78,7 @@ use std::{
};
use strum_macros::{AsRefStr, EnumString, VariantNames};
use fyrox_graph::{BaseSceneGraph, SceneGraphNode};
use fyrox_graph::{BaseSceneGraph, SceneGraph, SceneGraphNode};
pub use rapier3d::geometry::shape::*;
use rapier3d::parry::query::DefaultQueryDispatcher;
use rapier3d::prelude::FrictionModel;
@@ -512,7 +512,7 @@ fn make_trimesh(
let root_inv_transform = owner_inv_transform;
for &source in sources {
if let Some(mesh) = nodes.try_borrow(source.0).and_then(|n| n.cast::<Mesh>()) {
if let Ok(mesh) = nodes.try_get_component_of_type::<Mesh>(source.0) {
let global_transform = root_inv_transform * mesh.global_transform();
for surface in mesh.surfaces() {
@@ -800,12 +800,12 @@ fn collider_shape_into_native_shape(
}
}
ColliderShape::Heightfield(heightfield) => pool
.try_borrow(heightfield.geometry_source.0)
.and_then(|n| n.cast::<Terrain>())
.try_get_component_of_type::<Terrain>(heightfield.geometry_source.0)
.ok()
.and_then(make_heightfield),
ColliderShape::Polyhedron(polyhedron) => pool
.try_borrow(polyhedron.geometry_source.0)
.and_then(|n| n.cast::<Mesh>())
.try_get_component_of_type::<Mesh>(polyhedron.geometry_source.0)
.ok()
.map(|mesh| make_polyhedron_shape(owner_inv_global_transform, mesh)),
}
}
@@ -1334,13 +1334,11 @@ impl PhysicsWorld {
}),
exclude_collider: filter
.exclude_collider
.and_then(|h| graph.try_get_node(h))
.and_then(|n| n.component_ref::<collider::Collider>())
.and_then(|h| graph.try_get_of_type::<collider::Collider>(h).ok())
.map(|c| c.native.get()),
exclude_rigid_body: filter
.exclude_collider
.and_then(|h| graph.try_get_node(h))
.and_then(|n| n.component_ref::<rigidbody::RigidBody>())
.and_then(|h| graph.try_get_of_type::<rigidbody::RigidBody>(h).ok())
.map(|c| c.native.get()),
predicate: Some(&predicate),
};
@@ -1727,9 +1725,8 @@ impl PhysicsWorld {
}
}
}
} else if let Some(parent_body) = nodes
.try_borrow(collider_node.parent())
.and_then(|n| n.cast::<scene::rigidbody::RigidBody>())
} else if let Ok(parent_body) =
nodes.try_get_component_of_type::<scene::rigidbody::RigidBody>(collider_node.parent())
{
if parent_body.native.get() != RigidBodyHandle::invalid() {
let inv_global_transform = isometric_global_transform(nodes, handle)
@@ -1798,12 +1795,12 @@ impl PhysicsWorld {
if let Some(native) = self.joints.set.get_mut(joint.native.get(), false) {
joint.body1.try_sync_model(|v| {
if let Some(rigid_body_node) = nodes.try_get(v) {
if let Ok(rigid_body_node) = nodes.try_get(v) {
native.body1 = rigid_body_node.native.get();
}
});
joint.body2.try_sync_model(|v| {
if let Some(rigid_body_node) = nodes.try_get(v) {
if let Ok(rigid_body_node) = nodes.try_get(v) {
native.body2 = rigid_body_node.native.get();
}
});
@@ -1855,7 +1852,7 @@ impl PhysicsWorld {
let mut local_frames = joint.local_frames.borrow_mut();
if local_frames.is_none() {
if let (Some(body1), Some(body2)) =
if let (Ok(body1), Ok(body2)) =
(nodes.try_get(joint.body1()), nodes.try_get(joint.body2()))
{
let (local_frame1, local_frame2) = calculate_local_frames(joint, body1, body2);
@@ -1874,9 +1871,11 @@ impl PhysicsWorld {
if let (Some(body1), Some(body2)) = (
nodes
.try_get(body1_handle)
.ok()
.filter(|b| self.bodies.get(b.native.get()).is_some()),
nodes
.try_get(body2_handle)
.ok()
.filter(|b| self.bodies.get(b.native.get()).is_some()),
) {
let native_body1 = body1.native.get();
+2 -2
View File
@@ -666,13 +666,13 @@ impl NodeTrait for Joint {
}
fn validate(&self, scene: &Scene) -> Result<(), String> {
if scene.graph.try_get(self.body1()).is_none() {
if scene.graph.try_get(self.body1()).is_err() {
return Err("3D Joint has invalid or unassigned handle to a \
first body, the joint will not operate!"
.to_string());
}
if scene.graph.try_get(self.body2()).is_none() {
if scene.graph.try_get(self.body2()).is_err() {
return Err("3D Joint has invalid or unassigned handle to a \
second body, the joint will not operate!"
.to_string());
+2 -3
View File
@@ -674,7 +674,7 @@ impl NodeTrait for Mesh {
// Special case for skinned meshes.
for surface in self.surfaces.iter() {
for &bone in surface.bones() {
if let Some(node) = context.nodes.try_borrow(bone) {
if let Ok(node) = context.nodes.try_borrow(bone) {
world_aabb.add_point(node.global_position())
}
}
@@ -781,8 +781,7 @@ impl NodeTrait for Mesh {
.bones
.iter()
.map(|bone_handle| {
if let Some(bone_node) =
ctx.graph.try_get_node(*bone_handle)
if let Ok(bone_node) = ctx.graph.try_get_node(*bone_handle)
{
bone_node.global_transform()
* bone_node.inv_bind_pose_transform()
+7 -6
View File
@@ -78,6 +78,7 @@ use crate::{
utils::navmesh::Navmesh,
};
use fxhash::FxHashSet;
use fyrox_core::pool::PoolError;
use std::{
fmt::{Display, Formatter},
ops::{Index, IndexMut},
@@ -130,22 +131,22 @@ impl NavMeshContainer {
}
/// Tries to borrow a navmesh by its index.
pub fn at(&self, i: u32) -> Option<&Navmesh> {
pub fn at(&self, i: u32) -> Result<&Navmesh, PoolError> {
self.pool.at(i)
}
/// Tries to borrow a navmesh by its handle.
pub fn try_get(&self, handle: Handle<Navmesh>) -> Option<&Navmesh> {
pub fn try_get(&self, handle: Handle<Navmesh>) -> Result<&Navmesh, PoolError> {
self.pool.try_borrow(handle)
}
/// Tries to borrow a navmesh by its index.
pub fn at_mut(&mut self, i: u32) -> Option<&mut Navmesh> {
pub fn at_mut(&mut self, i: u32) -> Result<&mut Navmesh, PoolError> {
self.pool.at_mut(i)
}
/// Tries to borrow a navmesh by its handle.
pub fn try_get_mut(&mut self, handle: Handle<Navmesh>) -> Option<&mut Navmesh> {
pub fn try_get_mut(&mut self, handle: Handle<Navmesh>) -> Result<&mut Navmesh, PoolError> {
self.pool.try_borrow_mut(handle)
}
}
@@ -654,12 +655,12 @@ impl SceneContainer {
}
/// Tries to borrow a scene using its handle.
pub fn try_get(&self, handle: Handle<Scene>) -> Option<&Scene> {
pub fn try_get(&self, handle: Handle<Scene>) -> Result<&Scene, PoolError> {
self.pool.try_borrow(handle)
}
/// Tries to borrow a scene using its handle.
pub fn try_get_mut(&mut self, handle: Handle<Scene>) -> Option<&mut Scene> {
pub fn try_get_mut(&mut self, handle: Handle<Scene>) -> Result<&mut Scene, PoolError> {
self.pool.try_borrow_mut(handle)
}
+5 -7
View File
@@ -351,10 +351,9 @@ impl NodeTrait for Ragdoll {
let mut new_lin_vel = None;
let mut new_ang_vel = None;
if *self.is_active && !self.prev_enabled {
if let Some(character_rigid_body) = ctx
if let Ok(character_rigid_body) = ctx
.nodes
.try_borrow_mut(*self.character_rigid_body)
.and_then(|n| n.component_mut::<RigidBody>())
.try_get_component_of_type::<RigidBody>(*self.character_rigid_body)
{
new_lin_vel = Some(character_rigid_body.lin_vel());
new_ang_vel = Some(character_rigid_body.ang_vel());
@@ -475,12 +474,11 @@ impl NodeTrait for Ragdoll {
}
});
if let Some(root_limb_body) = ctx.nodes.try_borrow(self.root_limb.bone) {
if let Ok(root_limb_body) = ctx.nodes.try_borrow(self.root_limb.bone) {
let position = root_limb_body.global_position();
if let Some(character_rigid_body) = ctx
if let Ok(character_rigid_body) = ctx
.nodes
.try_borrow_mut(*self.character_rigid_body)
.and_then(|n| n.component_mut::<RigidBody>())
.try_get_component_of_type_mut::<RigidBody>(*self.character_rigid_body)
{
if *self.is_active {
character_rigid_body.set_lin_vel(Default::default());
+2 -1
View File
@@ -647,6 +647,7 @@ impl NodeTrait for RigidBody {
context
.nodes
.try_borrow(self.parent)
.ok()
.map(|p| p.global_transform())
.unwrap_or_else(Matrix4::identity),
);
@@ -654,7 +655,7 @@ impl NodeTrait for RigidBody {
fn validate(&self, scene: &Scene) -> Result<(), String> {
for &child in self.children() {
if scene.graph.try_get_of_type::<Collider>(child).is_some() {
if scene.graph.try_get_of_type::<Collider>(child).is_ok() {
return Ok(());
}
}
+2 -2
View File
@@ -157,13 +157,13 @@ impl SoundContext {
}
pub(crate) fn set_sound_position(&mut self, sound: &Sound) {
if let Some(source) = self.native.state().try_get_source_mut(sound.native.get()) {
if let Ok(source) = self.native.state().try_get_source_mut(sound.native.get()) {
source.set_position(sound.global_position());
}
}
pub(crate) fn sync_with_sound(&self, sound: &mut Sound) {
if let Some(source) = self.native.state().try_get_source_mut(sound.native.get()) {
if let Ok(source) = self.native.state().try_get_source_mut(sound.native.get()) {
// Sync back.
sound.status.set_value_silent(source.status());
sound
+8 -8
View File
@@ -22,6 +22,7 @@
//! Script is used to add custom logic to scene nodes. See [ScriptTrait] for more info.
use crate::engine::input::InputState;
use crate::{
asset::manager::ResourceManager,
core::{
@@ -39,7 +40,10 @@ use crate::{
plugin::{Plugin, PluginContainer},
scene::{base::NodeScriptMessage, node::Node, Scene},
};
use fyrox_core::pool::PoolError;
use fyrox_core::reflect::FieldMut;
pub use fyrox_core_derive::ScriptMessagePayload;
use fyrox_graph::BaseSceneGraph;
use std::{
any::{Any, TypeId},
fmt::{Debug, Formatter},
@@ -47,14 +51,10 @@ use std::{
str::FromStr,
sync::mpsc::Sender,
};
use crate::engine::input::InputState;
pub use fyrox_core_derive::ScriptMessagePayload;
use fyrox_graph::BaseSceneGraph;
pub mod constructor;
pub(crate) trait UniversalScriptContext {
fn node(&mut self) -> Option<&mut Node>;
fn node(&mut self) -> Result<&mut Node, PoolError>;
fn destroy_script_deferred(&self, script: Script, index: usize);
fn set_script_index(&mut self, index: usize);
}
@@ -417,7 +417,7 @@ pub struct ScriptContext<'a, 'b, 'c> {
}
impl UniversalScriptContext for ScriptContext<'_, '_, '_> {
fn node(&mut self) -> Option<&mut Node> {
fn node(&mut self) -> Result<&mut Node, PoolError> {
self.scene.graph.try_get_node_mut(self.handle)
}
@@ -501,7 +501,7 @@ pub struct ScriptMessageContext<'a, 'b, 'c> {
}
impl UniversalScriptContext for ScriptMessageContext<'_, '_, '_> {
fn node(&mut self) -> Option<&mut Node> {
fn node(&mut self) -> Result<&mut Node, PoolError> {
self.scene.graph.try_get_node_mut(self.handle)
}
@@ -576,7 +576,7 @@ pub struct ScriptDeinitContext<'a, 'b, 'c> {
}
impl UniversalScriptContext for ScriptDeinitContext<'_, '_, '_> {
fn node(&mut self) -> Option<&mut Node> {
fn node(&mut self) -> Result<&mut Node, PoolError> {
self.scene.graph.try_get_node_mut(self.node_handle)
}
+6 -2
View File
@@ -44,6 +44,7 @@ use crate::{
leaf::LeafNode,
},
};
use fyrox_core::pool::PoolError;
use std::{
fmt::Debug,
ops::{Index, IndexMut},
@@ -224,12 +225,15 @@ where
}
/// Tries to get a shared reference to a node by given handle.
pub fn node(&self, handle: Handle<BehaviorNode<B>>) -> Option<&BehaviorNode<B>> {
pub fn node(&self, handle: Handle<BehaviorNode<B>>) -> Result<&BehaviorNode<B>, PoolError> {
self.nodes.try_borrow(handle)
}
/// Tries to get a mutable reference to a node by given handle.
pub fn node_mut(&mut self, handle: Handle<BehaviorNode<B>>) -> Option<&mut BehaviorNode<B>> {
pub fn node_mut(
&mut self,
handle: Handle<BehaviorNode<B>>,
) -> Result<&mut BehaviorNode<B>, PoolError> {
self.nodes.try_borrow_mut(handle)
}
+8 -4
View File
@@ -22,6 +22,7 @@
//! for more info and examples
use crate::effects::{Effect, EffectRenderTrait};
use fyrox_core::pool::PoolError;
use fyrox_core::{
pool::{Handle, Pool, Ticket},
reflect::prelude::*,
@@ -355,7 +356,7 @@ impl AudioBusGraph {
std::mem::replace(&mut self.buses[node_handle].parent_bus, Handle::NONE);
// Remove child from parent's children list
if let Some(parent) = self.buses.try_borrow_mut(parent_handle) {
if let Ok(parent) = self.buses.try_borrow_mut(parent_handle) {
if let Some(i) = parent.children().iter().position(|h| *h == node_handle) {
parent.child_buses.remove(i);
}
@@ -415,12 +416,15 @@ impl AudioBusGraph {
}
/// Tries to borrow an audio bus by its handle.
pub fn try_get_bus_ref(&self, handle: Handle<AudioBus>) -> Option<&AudioBus> {
pub fn try_get_bus_ref(&self, handle: Handle<AudioBus>) -> Result<&AudioBus, PoolError> {
self.buses.try_borrow(handle)
}
/// Tries to borrow an audio bus by its handle.
pub fn try_get_bus_mut(&mut self, handle: Handle<AudioBus>) -> Option<&mut AudioBus> {
pub fn try_get_bus_mut(
&mut self,
handle: Handle<AudioBus>,
) -> Result<&mut AudioBus, PoolError> {
self.buses.try_borrow_mut(handle)
}
@@ -439,7 +443,7 @@ impl AudioBusGraph {
pub fn try_take_reserve_bus(
&mut self,
handle: Handle<AudioBus>,
) -> Option<(Ticket<AudioBus>, AudioBus)> {
) -> Result<(Ticket<AudioBus>, AudioBus), PoolError> {
self.buses.try_take_reserve(handle)
}
+5 -1
View File
@@ -37,6 +37,7 @@ use crate::{
renderer::{render_source_default, Renderer},
source::{SoundSource, Status},
};
use fyrox_core::pool::PoolError;
use fyrox_core::{
pool::{Handle, Pool},
reflect::prelude::*,
@@ -247,7 +248,10 @@ impl State {
}
/// Returns mutable reference to sound source at given handle. If handle is invalid, this method will panic.
pub fn try_get_source_mut(&mut self, handle: Handle<SoundSource>) -> Option<&mut SoundSource> {
pub fn try_get_source_mut(
&mut self,
handle: Handle<SoundSource>,
) -> Result<&mut SoundSource, PoolError> {
self.sources.try_borrow_mut(handle)
}
+4 -5
View File
@@ -34,7 +34,7 @@ use crate::{
};
use fyrox_animation::machine::Parameter;
use fyrox_graph::constructor::{ConstructorProvider, GraphNodeConstructor};
use fyrox_graph::{SceneGraph, SceneGraphNode};
use fyrox_graph::SceneGraph;
use strum_macros::{AsRefStr, EnumString, VariantNames};
/// UI-specific root motion settings.
@@ -179,10 +179,9 @@ define_widget_deref!(AnimationBlendingStateMachine);
impl Control for AnimationBlendingStateMachine {
fn update(&mut self, dt: f32, ui: &mut UserInterface) {
if let Some(animation_player) = ui
if let Ok(animation_player) = ui
.nodes
.try_borrow_mut(*self.animation_player)
.and_then(|n| n.component_mut::<AnimationPlayer>())
.try_get_component_of_type_mut::<AnimationPlayer>(*self.animation_player)
{
// Prevent animation player to apply animation to scene nodes. The animation will
// do than instead.
@@ -316,7 +315,7 @@ impl AbsmEventProvider {
return;
};
let Some(absm) = ui.try_get_mut_of_type::<AnimationBlendingStateMachine>(*self.absm) else {
let Ok(absm) = ui.try_get_mut_of_type::<AnimationBlendingStateMachine>(*self.absm) else {
return;
};
+1 -1
View File
@@ -100,7 +100,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) = ui.try_get_node_mut(*node) {
} else if let Ok(node) = ui.try_get_node_mut(*node) {
node.invalidate_layout();
local_pose.values.apply(node);
+3 -2
View File
@@ -25,6 +25,7 @@ use crate::{
core::pool::Handle, font::FontResource, message::UiMessage, style::resource::StyleResource,
Control, RestrictionEntry, UiNode, UserInterface,
};
use fyrox_core::pool::PoolError;
use fyrox_graph::BaseSceneGraph;
use std::{
ops::{Index, IndexMut},
@@ -148,12 +149,12 @@ impl BuildContext<'_> {
}
/// Tries to fetch the node by its handle. Returns `None` if the handle is invalid.
pub fn try_get_node(&self, node: Handle<UiNode>) -> Option<&UiNode> {
pub fn try_get_node(&self, node: Handle<UiNode>) -> Result<&UiNode, PoolError> {
self.ui.try_get_node(node)
}
/// Tries to fetch the node by its handle. Returns `None` if the handle is invalid.
pub fn try_get_node_mut(&mut self, node: Handle<UiNode>) -> Option<&mut UiNode> {
pub fn try_get_node_mut(&mut self, node: Handle<UiNode>) -> Result<&mut UiNode, PoolError> {
self.ui.nodes.try_borrow_mut(node)
}
+4 -5
View File
@@ -45,7 +45,7 @@ use crate::{
use crate::message::MessageData;
use fyrox_graph::constructor::{ConstructorProvider, GraphNodeConstructor};
use fyrox_graph::BaseSceneGraph;
use fyrox_graph::{BaseSceneGraph, SceneGraph};
use std::cell::Cell;
#[derive(Debug, Clone, PartialEq)]
@@ -251,7 +251,7 @@ impl Control for ColorGradientEditor {
ui.post(self.handle, ColorGradientEditorMessage::Value(gradient));
} else if message.destination() == self.remove_point
&& ui.try_get_node(self.context_menu_target.get()).is_some()
&& ui.try_get_node(self.context_menu_target.get()).is_ok()
{
let gradient = self.fetch_gradient(self.context_menu_target.get(), ui);
@@ -290,9 +290,8 @@ impl Control for ColorGradientEditor {
self.context_menu_target.set(*target);
if message.destination() == self.point_context_menu.handle() {
if let Some(point) = ui
.try_get_node(self.context_menu_target.get())
.and_then(|n| n.query_component::<ColorPoint>())
if let Ok(point) =
ui.try_get_of_type::<ColorPoint>(self.context_menu_target.get())
{
ui.send_with_flags(
self.selector_field,
+2 -3
View File
@@ -149,7 +149,7 @@ fn find_window(
if window_handle.is_none() {
for other_window_handle in windows.iter().cloned() {
if let Some(window_node) = ui.try_get_node(other_window_handle) {
if let Ok(window_node) = ui.try_get_node(other_window_handle) {
if &window_node.name == window_name {
return other_window_handle;
}
@@ -161,8 +161,7 @@ fn find_window(
impl TileDescriptor {
pub(super) fn from_tile_handle(handle: Handle<UiNode>, ui: &UserInterface) -> Self {
ui.try_get_node(handle)
.and_then(|t| t.query_component::<Tile>())
ui.try_get_of_type::<Tile>(handle)
.map(|t| Self {
content: TileContentDescriptor::from_tile(&t.content, ui),
})
+2 -5
View File
@@ -226,7 +226,7 @@ impl DockingManager {
.borrow()
.iter()
.filter_map(|h| {
ui.try_get_node(*h).map(|w| FloatingWindowDescriptor {
ui.try_get_node(*h).ok().map(|w| FloatingWindowDescriptor {
name: w.name.clone(),
position: w.actual_local_position(),
size: w.actual_local_size(),
@@ -250,10 +250,7 @@ impl DockingManager {
let mut windows = Vec::new();
let mut stack = vec![root_tile_handle];
while let Some(tile_handle) = stack.pop() {
if let Some(tile) = ui
.try_get_node(tile_handle)
.and_then(|n| n.query_component::<Tile>())
{
if let Ok(tile) = ui.try_get_of_type::<Tile>(tile_handle) {
match tile.content {
TileContent::Window(window) => {
if ui.is_valid_handle(window) {
+1
View File
@@ -400,6 +400,7 @@ pub fn build_single_folder(
pub fn tree_path(tree_handle: Handle<UiNode>, ui: &UserInterface) -> Option<TreeItemPath> {
ui.try_get(tree_handle)
.ok()
.and_then(|n| n.user_data_cloned::<TreeItemPath>())
}
+1
View File
@@ -230,6 +230,7 @@ impl ItemContextMenu {
fn item_path(&self, ui: &UserInterface) -> Option<TreeItemPath> {
ui.try_get_node(self.base_menu.popup.placement.target())
.ok()
.and_then(|n| n.user_data_cloned::<TreeItemPath>())
}
}
+1 -1
View File
@@ -341,7 +341,7 @@ impl FileBrowser {
if tree_item.is_some() {
let parent_path = parent_path(path);
let parent_tree = fs_tree::find_tree_item(self.tree_root, &parent_path, ui);
if let Some(parent_tree_node) = ui.try_get(parent_tree) {
if let Ok(parent_tree_node) = ui.try_get(parent_tree) {
if parent_tree_node.has_component::<TreeRoot>() {
ui.send(parent_tree, TreeRootMessage::RemoveItem(tree_item))
} else {
+3 -3
View File
@@ -422,7 +422,7 @@ impl Grid {
.iter()
.copied()
.filter(|&c| {
let Some(child_ref) = ui.try_get_node(c) else {
let Ok(child_ref) = ui.try_get_node(c) else {
return false;
};
child_ref.row() == row_index && child_ref.column() == column_index
@@ -446,7 +446,7 @@ impl Grid {
}
}
for handle in self.children() {
let Some(node) = ui.try_get_node(*handle) else {
let Ok(node) = ui.try_get_node(*handle) else {
continue;
};
let Some(row) = rows.get_mut(node.row()) else {
@@ -483,7 +483,7 @@ impl Grid {
measure_width: bool,
measure_height: bool,
) {
let Some(node) = ui.try_get_node(child) else {
let Ok(node) = ui.try_get_node(child) else {
return;
};
let mut rows = self.rows.borrow_mut();
+3 -3
View File
@@ -650,7 +650,7 @@ impl Inspector {
}
if pasted {
if let Some(inspector) = ui.try_get_of_type::<Inspector>(inspector) {
if let Ok(inspector) = ui.try_get_of_type::<Inspector>(inspector) {
let ctx = inspector.context.clone();
if let Err(errs) =
@@ -678,7 +678,7 @@ impl Inspector {
) -> Option<&ContextEntry> {
let mut parent_handle = from;
while let Some(parent) = ui.try_get_node(parent_handle) {
while let Ok(parent) = ui.try_get_node(parent_handle) {
for entry in self.context.entries.iter() {
if entry.property_container == parent_handle {
return Some(entry);
@@ -1467,7 +1467,7 @@ impl Control for Inspector {
if message.direction() == MessageDirection::FromWidget
&& menu.handle() == message.destination()
{
if let Some(popup) = ui.try_get_of_type::<Popup>(menu.handle()) {
if let Ok(popup) = ui.try_get_of_type::<Popup>(menu.handle()) {
if let Some(entry) = self.find_property_container(popup.owner, ui) {
ui.post(
self.handle,
+49 -32
View File
@@ -359,6 +359,7 @@ use strum_macros::{AsRefStr, EnumString, VariantNames};
pub use alignment::*;
pub use build::*;
pub use control::*;
use fyrox_core::pool::PoolError;
pub use fyrox_texture as texture;
pub use node::*;
pub use thickness::*;
@@ -894,7 +895,7 @@ fn invalidate_recursive_up(
node: Handle<UiNode>,
callback: fn(&UiNode),
) {
if let Some(node_ref) = nodes.try_borrow(node) {
if let Ok(node_ref) = nodes.try_borrow(node) {
(callback)(node_ref);
if node_ref.parent().is_some() {
invalidate_recursive_up(nodes, node_ref.parent(), callback);
@@ -954,12 +955,15 @@ impl UiContainer {
}
/// Tries to borrow a user interface using its handle.
pub fn try_get(&self, handle: Handle<UserInterface>) -> Option<&UserInterface> {
pub fn try_get(&self, handle: Handle<UserInterface>) -> Result<&UserInterface, PoolError> {
self.pool.try_borrow(handle)
}
/// Tries to borrow a user interface using its handle.
pub fn try_get_mut(&mut self, handle: Handle<UserInterface>) -> Option<&mut UserInterface> {
pub fn try_get_mut(
&mut self,
handle: Handle<UserInterface>,
) -> Result<&mut UserInterface, PoolError> {
self.pool.try_borrow_mut(handle)
}
@@ -1224,7 +1228,7 @@ impl UserInterface {
for _ in 0..indent {
result.push_str(" ");
}
let Some(node) = self.try_get(current) else {
let Ok(node) = self.try_get(current) else {
use std::fmt::Write;
writeln!(result, "{}: Failed to get", current).unwrap();
return;
@@ -1283,10 +1287,10 @@ impl UserInterface {
.nodes
.try_borrow_dependant_mut(node_handle, |n| n.parent());
if let Some(widget) = widget {
if let Ok(widget) = widget {
self.stack.extend_from_slice(widget.children());
let visibility = if let Some(parent) = parent {
let visibility = if let Ok(parent) = parent {
widget.visibility() && parent.is_globally_visible()
} else {
widget.visibility()
@@ -1316,7 +1320,7 @@ impl UserInterface {
.nodes
.try_borrow_dependant_mut(node_handle, |n| n.parent());
if let Some(widget) = widget {
if let Ok(widget) = widget {
if widget.is_globally_visible() {
self.stack.extend_from_slice(widget.children());
@@ -1325,7 +1329,7 @@ impl UserInterface {
layout_transform[6] = widget.actual_local_position().x;
layout_transform[7] = widget.actual_local_position().y;
let visual_transform = if let Some(parent) = parent {
let visual_transform = if let Ok(parent) = parent {
parent.visual_transform() * layout_transform * widget.render_transform()
} else {
layout_transform * widget.render_transform()
@@ -1370,7 +1374,7 @@ impl UserInterface {
self.update_global_visibility(node);
}
LayoutEvent::ZIndexChanged(node) => {
if let Some(node_ref) = self.nodes.try_borrow(node) {
if let Ok(node_ref) = self.nodes.try_borrow(node) {
// Z index affects the location of the node in its parent's children list.
// Hash set will remove duplicate requests of z-index updates, thus improving
// performance.
@@ -1395,7 +1399,7 @@ impl UserInterface {
func: &mut impl FnMut(Handle<UiNode>),
) {
func(from);
if let Some(node) = graph.try_get_node(from) {
if let Ok(node) = graph.try_get_node(from) {
for &child in node.children() {
traverse_recursive(graph, child, func)
}
@@ -1458,10 +1462,11 @@ impl UserInterface {
self.update_visual_transform(root);
// Recalculate clip bounds, because they depend on the visual transform.
if let Some(root_ref) = self.try_get_node(root) {
if let Ok(root_ref) = self.try_get_node(root) {
self.calculate_clip_bounds(
root,
self.try_get_node(root_ref.parent())
.ok()
.map(|c| c.clip_bounds())
.unwrap_or_else(|| {
Rect::new(0.0, 0.0, self.screen_size.x, self.screen_size.y)
@@ -1529,7 +1534,7 @@ impl UserInterface {
self.style = style;
fn notify_depth_first(node: Handle<UiNode>, ui: &UserInterface) {
if let Some(node_ref) = ui.try_get_node(node) {
if let Ok(node_ref) = ui.try_get_node(node) {
for child in node_ref.children.iter() {
notify_depth_first(*child, ui);
}
@@ -1637,7 +1642,7 @@ impl UserInterface {
}
}
if let Some(keyboard_focus_node) = self.nodes.try_borrow(self.keyboard_focus_node) {
if let Ok(keyboard_focus_node) = self.nodes.try_borrow(self.keyboard_focus_node) {
if keyboard_focus_node.global_visibility && keyboard_focus_node.accepts_input {
let bounds = keyboard_focus_node.screen_bounds().inflate(1.0, 1.0);
self.drawing_context.push_rounded_rect(&bounds, 1.0, 2.0, 6);
@@ -2234,7 +2239,7 @@ impl UserInterface {
}
for &handle in self.methods_registry.preview_message.iter() {
if let Some(node_ref) = self.nodes.try_borrow(handle) {
if let Ok(node_ref) = self.nodes.try_borrow(handle) {
node_ref.preview_message(self, &mut message);
}
}
@@ -2395,7 +2400,7 @@ impl UserInterface {
vertical_alignment,
margin,
} => {
if let (Some(node), Some(relative_node)) = (
if let (Ok(node), Ok(relative_node)) = (
self.try_get_node(message.destination()),
self.try_get_node(*relative_to),
) {
@@ -2453,7 +2458,7 @@ impl UserInterface {
}
}
if let Some(parent) = self.try_get_node(node.parent()) {
if let Ok(parent) = self.try_get_node(node.parent()) {
// Transform screen anchor point into the local coordinate system
// of the parent node.
let local_anchor_point = parent.screen_to_local(screen_anchor_point);
@@ -2466,7 +2471,7 @@ impl UserInterface {
}
WidgetMessage::MouseUp { button, .. } => {
if *button == MouseButton::Right && !message.handled() {
if let Some(picked) = self.nodes.try_borrow(self.picked_node) {
if let Ok(picked) = self.nodes.try_borrow(self.picked_node) {
// Get the context menu from the current node or a parent node
let (context_menu, target) = if picked.context_menu().is_some() {
(picked.context_menu(), self.picked_node)
@@ -2474,7 +2479,7 @@ impl UserInterface {
let parent_handle = picked
.find_by_criteria_up(self, |n| n.context_menu().is_some());
if let Some(parent) = self.nodes.try_borrow(parent_handle) {
if let Ok(parent) = self.nodes.try_borrow(parent_handle) {
(parent.context_menu(), parent_handle)
} else {
(None, Handle::NONE)
@@ -2573,7 +2578,7 @@ impl UserInterface {
} else {
let mut tooltip_owner_hovered = false;
let mut handle = self.picked_node;
while let Some(node) = self.nodes.try_borrow(handle) {
while let Ok(node) = self.nodes.try_borrow(handle) {
if let Some(tooltip) = node.tooltip.as_ref() {
if &entry.tooltip == tooltip {
tooltip_owner_hovered = true;
@@ -2598,7 +2603,7 @@ impl UserInterface {
// Check for hovering over a widget with a tooltip, or hovering over a tooltip.
let mut handle = self.picked_node;
while let Some(node) = self.nodes.try_borrow(handle) {
while let Ok(node) = self.nodes.try_borrow(handle) {
let parent = node.parent();
if let Some(tooltip) = node.tooltip() {
@@ -2874,7 +2879,7 @@ impl UserInterface {
state,
text,
} => {
if let Some(keyboard_focus_node) = self.try_get_node(self.keyboard_focus_node) {
if let Ok(keyboard_focus_node) = self.try_get_node(self.keyboard_focus_node) {
if keyboard_focus_node.is_globally_visible() {
match state {
ButtonState::Pressed => {
@@ -3233,7 +3238,10 @@ impl UserInterface {
}
#[inline]
pub fn try_get_node_mut(&mut self, node_handle: Handle<UiNode>) -> Option<&mut UiNode> {
pub fn try_get_node_mut(
&mut self,
node_handle: Handle<UiNode>,
) -> Result<&mut UiNode, PoolError> {
self.nodes.try_borrow_mut(node_handle)
}
@@ -3353,7 +3361,7 @@ impl UserInterface {
}
}
let Some(node) = self.nodes.try_borrow(node_handle) else {
let Ok(node) = self.nodes.try_borrow(node_handle) else {
return Default::default();
};
@@ -3488,7 +3496,10 @@ impl PrefabData for UserInterface {
}
impl AbstractSceneGraph for UserInterface {
fn try_get_node_untyped(&self, handle: ErasedHandle) -> Option<&dyn AbstractSceneNode> {
fn try_get_node_untyped(
&self,
handle: ErasedHandle,
) -> Result<&dyn AbstractSceneNode, PoolError> {
self.nodes
.try_borrow(handle.into())
.map(|n| n as &dyn AbstractSceneNode)
@@ -3497,7 +3508,7 @@ impl AbstractSceneGraph for UserInterface {
fn try_get_node_untyped_mut(
&mut self,
handle: ErasedHandle,
) -> Option<&mut dyn AbstractSceneNode> {
) -> Result<&mut dyn AbstractSceneNode, PoolError> {
self.nodes
.try_borrow_mut(handle.into())
.map(|n| n as &mut dyn AbstractSceneNode)
@@ -3516,7 +3527,7 @@ impl BaseSceneGraph for UserInterface {
}
#[inline]
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Option<TypeId> {
fn actual_type_id(&self, handle: Handle<Self::Node>) -> Result<TypeId, PoolError> {
self.nodes
.try_borrow(handle)
.map(|n| ControlAsAny::as_any(n.0.deref()).type_id())
@@ -3533,12 +3544,15 @@ impl BaseSceneGraph for UserInterface {
}
#[inline]
fn try_get_node(&self, handle: Handle<Self::Node>) -> Option<&Self::Node> {
fn try_get_node(&self, handle: Handle<Self::Node>) -> Result<&Self::Node, PoolError> {
self.nodes.try_borrow(handle)
}
#[inline]
fn try_get_node_mut(&mut self, handle: Handle<Self::Node>) -> Option<&mut Self::Node> {
fn try_get_node_mut(
&mut self,
handle: Handle<Self::Node>,
) -> Result<&mut Self::Node, PoolError> {
self.nodes.try_borrow_mut(handle)
}
@@ -3626,13 +3640,13 @@ impl BaseSceneGraph for UserInterface {
}
}
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Option<Vec<TypeId>> {
fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Result<Vec<TypeId>, PoolError> {
self.nodes
.try_borrow(handle)
.map(|n| n.0.query_derived_types().to_vec())
}
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Option<&'static str> {
fn actual_type_name(&self, handle: Handle<Self::Node>) -> Result<&'static str, PoolError> {
self.nodes
.try_borrow(handle)
.map(|n| Reflect::type_name(n.0.deref()))
@@ -3656,11 +3670,14 @@ impl SceneGraph for UserInterface {
self.nodes.iter_mut()
}
fn try_get<U: ObjectOrVariant<UiNode>>(&self, handle: Handle<U>) -> Option<&U> {
fn try_get<U: ObjectOrVariant<UiNode>>(&self, handle: Handle<U>) -> Result<&U, PoolError> {
self.nodes.try_get(handle)
}
fn try_get_mut<U: ObjectOrVariant<UiNode>>(&mut self, handle: Handle<U>) -> Option<&mut U> {
fn try_get_mut<U: ObjectOrVariant<UiNode>>(
&mut self,
handle: Handle<U>,
) -> Result<&mut U, PoolError> {
self.nodes.try_get_mut(handle)
}
}
+7 -5
View File
@@ -365,7 +365,7 @@ impl DerefMut for ItemsContainer {
impl ItemsContainer {
fn selected_item_index(&self, ui: &UserInterface) -> Option<usize> {
for (index, item) in self.items.iter().enumerate() {
if let Some(item_ref) = ui.try_get_of_type::<MenuItem>(*item) {
if let Ok(item_ref) = ui.try_get_of_type::<MenuItem>(*item) {
if *item_ref.is_selected {
return Some(index);
}
@@ -388,7 +388,8 @@ impl ItemsContainer {
}
index %= count;
let handle = self.items.get(index as usize).cloned();
if let Some(item) = handle.and_then(|h| ui.try_get_of_type::<MenuItem>(h)) {
if let Some(item) = handle.and_then(|h| ui.try_get_of_type::<MenuItem>(h).ok())
{
if item.enabled() {
return handle;
}
@@ -445,6 +446,7 @@ crate::define_widget_deref!(MenuItem);
impl MenuItem {
fn is_opened(&self, ui: &UserInterface) -> bool {
ui.try_get_of_type::<ContextMenu>(*self.items_panel)
.ok()
.is_some_and(|items_panel| *items_panel.popup.is_open)
}
@@ -496,7 +498,7 @@ fn close_menu_chain(from: Handle<UiNode>, ui: &UserInterface) {
while handle.is_some() {
let popup_handle = ui.find_handle_up(handle, &mut |n| n.has_component::<ContextMenu>());
if let Some(panel) = ui.try_get_of_type::<ContextMenu>(popup_handle) {
if let Ok(panel) = ui.try_get_of_type::<ContextMenu>(popup_handle) {
if *panel.popup.is_open {
ui.send(popup_handle, PopupMessage::Close);
}
@@ -1164,7 +1166,7 @@ impl Control for ContextMenu {
if let Some(WidgetMessage::KeyDown(key_code)) = message.data() {
if !message.handled() {
if let Some(parent_menu_item) = ui.try_get_node(self.parent_menu_item) {
if let Ok(parent_menu_item) = ui.try_get_node(self.parent_menu_item) {
if keyboard_navigation(
ui,
*key_code,
@@ -1255,7 +1257,7 @@ fn keyboard_navigation(
ui.send(selected_item, MenuItemMessage::Open);
if let Some(selected_item_ref) = ui.try_get_of_type::<MenuItem>(selected_item) {
if let Ok(selected_item_ref) = ui.try_get_of_type::<MenuItem>(selected_item) {
if let Some(first_item) = selected_item_ref.items_container.first() {
ui.send(*first_item, MenuItemMessage::Select(true));
}
+4
View File
@@ -339,6 +339,7 @@ impl Popup {
fn right_top_placement(&self, ui: &UserInterface, target: Handle<UiNode>) -> Vector2<f32> {
ui.try_get_node(target)
.ok()
.map(|n| n.screen_position() + Vector2::new(n.actual_global_size().x, 0.0))
.unwrap_or_else(|| {
Vector2::new(ui.screen_size().x - self.widget.actual_global_size().x, 0.0)
@@ -347,12 +348,14 @@ impl Popup {
fn center_placement(&self, ui: &UserInterface, target: Handle<UiNode>) -> Vector2<f32> {
ui.try_get_node(target)
.ok()
.map(|n| n.screen_position() + n.actual_global_size().scale(0.5))
.unwrap_or_else(|| (ui.screen_size - self.widget.actual_global_size()).scale(0.5))
}
fn left_bottom_placement(&self, ui: &UserInterface, target: Handle<UiNode>) -> Vector2<f32> {
ui.try_get_node(target)
.ok()
.map(|n| n.screen_position() + Vector2::new(0.0, n.actual_global_size().y))
.unwrap_or_else(|| {
Vector2::new(0.0, ui.screen_size().y - self.widget.actual_global_size().y)
@@ -361,6 +364,7 @@ impl Popup {
fn right_bottom_placement(&self, ui: &UserInterface, target: Handle<UiNode>) -> Vector2<f32> {
ui.try_get_node(target)
.ok()
.map(|n| n.screen_position() + n.actual_global_size())
.unwrap_or_else(|| ui.screen_size - self.widget.actual_global_size())
}
+1 -1
View File
@@ -182,7 +182,7 @@ impl ScrollPanel {
children_size
}
fn bring_into_view(&self, ui: &UserInterface, handle: Handle<UiNode>) {
let Some(node_to_focus_ref) = ui.try_get_node(handle) else {
let Ok(node_to_focus_ref) = ui.try_get_node(handle) else {
return;
};
let mut parent = handle;
+1 -1
View File
@@ -655,7 +655,7 @@ impl TabControlBuilder {
let tab_count = self.tabs.len();
// Hide everything but initial tab content.
for (i, (_, tab)) in self.tabs.iter().enumerate() {
if let Some(content) = ctx.try_get_node_mut(tab.content) {
if let Ok(content) = ctx.try_get_node_mut(tab.content) {
content.set_visibility(i == self.initial_tab);
}
}
+3 -3
View File
@@ -65,7 +65,7 @@ pub trait UserInterfaceTestingExtension {
}
fn is_enabled(mut handle: Handle<UiNode>, ui: &UserInterface) -> bool {
while let Some(node) = ui.try_get(handle) {
while let Ok(node) = ui.try_get(handle) {
if !node.enabled() {
return false;
}
@@ -158,7 +158,7 @@ impl UserInterfaceTestingExtension for UserInterface {
fn poll_all_messages(&mut self) {
while let Some(msg) = self.poll_message() {
if let Some(widget) = self.try_get(msg.destination()) {
if let Ok(widget) = self.try_get(msg.destination()) {
let ty = Reflect::type_name(widget);
info!("[{ty}]{msg:?}");
}
@@ -170,7 +170,7 @@ impl UserInterfaceTestingExtension for UserInterface {
fn poll_and_count(&mut self, mut pred: impl FnMut(&UiMessage) -> bool) -> usize {
let mut num = 0;
while let Some(msg) = self.poll_message() {
if let Some(widget) = self.try_get(msg.destination()) {
if let Ok(widget) = self.try_get(msg.destination()) {
let ty = Reflect::type_name(widget);
info!("[{ty}]{msg:?}");
}
+1 -1
View File
@@ -1692,7 +1692,7 @@ impl<'a> TextBoxBuilder<'a> {
self.widget_builder.cursor = Some(CursorIcon::Text);
}
let placeholder = self.placeholder.build(&self.text, ctx);
if let Some(placeholder_ref) = ctx.try_get_node_mut(placeholder) {
if let Ok(placeholder_ref) = ctx.try_get_node_mut(placeholder) {
placeholder_ref
.hit_test_visibility
.set_value_and_mark_modified(false);
+3 -9
View File
@@ -865,7 +865,7 @@ impl Control for TreeRoot {
if &self.selected != selected {
let mut items = self.items.clone();
while let Some(handle) = items.pop() {
if let Some(tree_ref) = ui.try_get_of_type::<Tree>(handle) {
if let Ok(tree_ref) = ui.try_get_of_type::<Tree>(handle) {
items.extend_from_slice(&tree_ref.items);
let new_selection_state = if selected.contains(&handle) {
@@ -903,10 +903,7 @@ impl Control for TreeRoot {
}
KeyCode::ArrowLeft => {
if let Some(selection) = self.selected.first() {
if let Some(item) = ui
.try_get_node(*selection)
.and_then(|n| n.component_ref::<Tree>())
{
if let Ok(item) = ui.try_get_of_type::<Tree>(*selection) {
if item.is_expanded {
ui.send(
*selection,
@@ -967,10 +964,7 @@ impl TreeRoot {
fn move_selection(&self, ui: &UserInterface, direction: Direction, expand: bool) {
if let Some(selected_item) = self.selected.first() {
let Some(item) = ui
.try_get_node(*selected_item)
.and_then(|n| n.component_ref::<Tree>())
else {
let Ok(item) = ui.try_get_of_type::<Tree>(*selected_item) else {
return;
};
+1 -1
View File
@@ -1197,7 +1197,7 @@ impl Widget {
) -> Handle<UiNode> {
let mut parent_handle = self.parent;
while parent_handle.is_some() {
if let Some(parent_node) = ui.nodes.try_borrow(parent_handle) {
if let Ok(parent_node) = ui.nodes.try_borrow(parent_handle) {
if func(parent_node) {
return parent_handle;
}
+1 -1
View File
@@ -703,7 +703,7 @@ impl Control for Window {
font,
font_size,
} => {
if ui.try_get_of_type::<Text>(self.title).is_some() {
if ui.try_get_of_type::<Text>(self.title).is_ok() {
// Just modify existing text, this is much faster than
// re-create text everytime.
ui.send(self.title, TextMessage::Text(text.clone()));