Skip to main content

fyrox_impl/scene/graph/
mod.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Contains all methods and structures to create and manage scene graphs.
22//!
23//! Scene graph is the foundation of the engine. Graph is a hierarchical data
24//! structure where each element called node. Each node can have zero to one parent
25//! node, and any children nodes. Node with no parent node called root, with no
26//! children nodes - leaf. Graphical representation can be something like this:
27//!
28//! ```text
29//!     Root____
30//!       |    |
31//!       D    A___
32//!       |    |  |
33//!       E    C  B
34//!     ............
35//! ```
36//!
37//! This picture clearly shows relations between nodes. Such structure allows us
38//! to create scenes of any complexity by just linking nodes with each other.
39//! Connections between nodes are used to traverse tree, to calculate global
40//! transforms, global visibility and many other things. Most interesting here -
41//! is global transform calculation - it allows you to produce complex movements
42//! just by linking nodes to each other. Good example of this is skeleton which
43//! is used in skinning (animating 3d model by set of bones).
44
45use crate::{
46    asset::untyped::UntypedResource,
47    core::{
48        algebra::{Matrix4, Rotation3, UnitQuaternion, Vector2, Vector3},
49        dyntype::DynTypeContainer,
50        instant,
51        log::{Log, MessageKind},
52        math::{aabb::AxisAlignedBoundingBox, Matrix4Ext},
53        pool::{Handle, MultiBorrowContext, ObjectOrVariant, Pool, PoolError, Ticket},
54        reflect::prelude::*,
55        visitor::{Visit, VisitResult, Visitor},
56    },
57    graph::{NodeHandleMap, SceneGraph, SceneGraphNode},
58    material::{MaterialResourceBinding, MaterialTextureBinding},
59    resource::model::{Model, ModelResource, ModelResourceExtension},
60    scene::{
61        base::{NodeMessage, NodeMessageKind, NodeScriptMessage, SceneNodeId},
62        dim2::{self},
63        graph::{
64            event::{GraphEvent, GraphEventBroadcaster},
65            physics::{PhysicsPerformanceStatistics, PhysicsWorld},
66        },
67        mesh::Mesh,
68        navmesh,
69        node::{container::NodeContainer, Node, NodeAsAny, SyncContext, UpdateContext},
70        pivot::Pivot,
71        sound::context::SoundContext,
72        transform::TransformBuilder,
73    },
74    script::ScriptTrait,
75    utils::lightmap::{self, Lightmap},
76};
77use bitflags::bitflags;
78use fxhash::{FxHashMap, FxHashSet};
79use fyrox_material::MaterialResourceExtension;
80use std::{
81    any::{Any, TypeId},
82    fmt::{Debug, Display, Formatter, Write},
83    ops::{Deref, Index, IndexMut},
84    sync::mpsc::{channel, Receiver, Sender},
85    time::Duration,
86};
87
88pub mod event;
89pub mod physics;
90
91/// Graph performance statistics. Allows you to find out "hot" parts of the scene graph, which
92/// parts takes the most time to update.
93#[derive(Clone, Default, Debug)]
94pub struct GraphPerformanceStatistics {
95    /// Amount of time that was needed to update global transform, visibility, and every other
96    /// property of every object which depends on the state of a parent node.
97    pub hierarchical_properties_time: Duration,
98
99    /// Amount of time that was needed to synchronize state of the graph with the state of
100    /// backing native objects (Rapier's rigid bodies, colliders, joints, sound sources, etc.)
101    pub sync_time: Duration,
102
103    /// Physics performance statistics.
104    pub physics: PhysicsPerformanceStatistics,
105
106    /// 2D Physics performance statistics.
107    pub physics2d: PhysicsPerformanceStatistics,
108
109    /// A time which was required to render sounds.
110    pub sound_update_time: Duration,
111}
112
113impl GraphPerformanceStatistics {
114    /// Returns total amount of time.
115    pub fn total(&self) -> Duration {
116        self.hierarchical_properties_time
117            + self.sync_time
118            + self.physics.total()
119            + self.physics2d.total()
120            + self.sound_update_time
121    }
122}
123
124/// A helper type alias for node pool.
125pub type NodePool = Pool<Node, NodeContainer>;
126
127/// See module docs.
128#[derive(Reflect)]
129pub struct Graph {
130    #[reflect(hidden)]
131    root: Handle<Node>,
132
133    pool: NodePool,
134
135    #[reflect(hidden)]
136    stack: Vec<Handle<Node>>,
137
138    /// User-defined data. Could be any registered [`crate::core::dyntype::DynType`] instance.
139    pub user_data: DynTypeContainer,
140
141    /// Backing physics "world". It is responsible for the physics simulation.
142    pub physics: PhysicsWorld,
143
144    /// Backing 2D physics "world". It is responsible for the 2D physics simulation.
145    pub physics2d: dim2::physics::PhysicsWorld,
146
147    /// Backing sound context. It is responsible for sound rendering.
148    #[reflect(hidden)]
149    pub sound_context: SoundContext,
150
151    /// Performance statistics of a last [`Graph::update`] call.
152    #[reflect(hidden)]
153    pub performance_statistics: GraphPerformanceStatistics,
154
155    /// Allows you to "subscribe" for graph events.
156    #[reflect(hidden)]
157    pub event_broadcaster: GraphEventBroadcaster,
158
159    /// Current lightmap.
160    lightmap: Option<Lightmap>,
161
162    #[reflect(hidden)]
163    pub(crate) script_message_sender: Sender<NodeScriptMessage>,
164    #[reflect(hidden)]
165    pub(crate) script_message_receiver: Receiver<NodeScriptMessage>,
166
167    #[reflect(hidden)]
168    pub(crate) message_sender: Sender<NodeMessage>,
169    #[reflect(hidden)]
170    pub(crate) message_receiver: Receiver<NodeMessage>,
171
172    #[reflect(read_only)]
173    instance_id_map: FxHashMap<SceneNodeId, Handle<Node>>,
174}
175
176impl Debug for Graph {
177    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178        f.debug_struct("Graph")
179            .field("physics", &self.physics)
180            .field("physics2d", &self.physics2d)
181            .field("sound_context", &self.sound_context)
182            .field("performance_statistics", &self.performance_statistics)
183            .field("event_broadcaster", &self.event_broadcaster)
184            .field("lightmap", &self.lightmap)
185            .field("instance_id_map", &self.instance_id_map)
186            .finish()?;
187        f.write_char('\n')?;
188        f.write_str(&self.summary())
189    }
190}
191
192impl Clone for Graph {
193    fn clone(&self) -> Self {
194        self.clone_ex(
195            self.root,
196            true,
197            &mut |_, _| true,
198            &mut |_, _| {},
199            &mut |_, _, _| {},
200        )
201        .0
202    }
203}
204
205impl Default for Graph {
206    fn default() -> Self {
207        let (script_message_sender, script_message_receiver) = channel();
208        let (message_sender, message_receiver) = channel();
209
210        Self {
211            physics: PhysicsWorld::new(),
212            physics2d: dim2::physics::PhysicsWorld::new(),
213            root: Handle::NONE,
214            pool: Pool::new(),
215            stack: Vec::new(),
216            sound_context: Default::default(),
217            performance_statistics: Default::default(),
218            event_broadcaster: Default::default(),
219            script_message_receiver,
220            message_sender,
221            script_message_sender,
222            lightmap: None,
223            instance_id_map: Default::default(),
224            message_receiver,
225            user_data: Default::default(),
226        }
227    }
228}
229
230/// Sub-graph is a piece of graph that was extracted from a graph. It has ownership
231/// over its nodes. It is used to temporarily take ownership of a sub-graph. This could
232/// be used if you're making a scene editor with a command stack - once you reverted a command,
233/// that created a complex nodes hierarchy (for example you loaded a model) you must store
234/// all added nodes somewhere to be able to put nodes back into graph when user decide to re-do
235/// command. Sub-graph allows you to do this without invalidating handles to nodes.
236#[derive(Debug)]
237pub struct SubGraph {
238    /// A root node and its [ticket](/fyrox-core/model/struct.Ticket.html).
239    pub root: (Ticket<Node>, Node),
240
241    /// A set of descendant nodes with their tickets.
242    pub descendants: Vec<(Ticket<Node>, Node)>,
243
244    /// A handle to the parent node from which the sub-graph was extracted (it it parent node of
245    /// the root of this sub-graph).
246    pub parent: Handle<Node>,
247}
248
249/// Perform remapping for every node in the destination graph that is included
250/// in the given `old_new_mapping`. This uses reflection to update every node handle
251/// that is part of the data of each node.
252fn remap_handles(old_new_mapping: &NodeHandleMap<Node>, dest_graph: &mut Graph) {
253    // Iterate over instantiated nodes and remap handles.
254    for (_, &new_node_handle) in old_new_mapping.inner().iter() {
255        old_new_mapping.remap_handles(
256            &mut dest_graph.pool[new_node_handle],
257            &[TypeId::of::<UntypedResource>()],
258        );
259    }
260}
261
262/// Calculates local transform of a scene node without scaling.
263pub fn isometric_local_transform(
264    nodes: &NodePool,
265    node: Handle<impl ObjectOrVariant<Node>>,
266) -> Matrix4<f32> {
267    let transform = nodes[node.to_base()].local_transform();
268    TransformBuilder::new()
269        .with_local_position(**transform.position())
270        .with_local_rotation(**transform.rotation())
271        .with_pre_rotation(**transform.pre_rotation())
272        .with_post_rotation(**transform.post_rotation())
273        .build()
274        .matrix()
275}
276
277/// Calculates global transform of a scene node without scaling.
278pub fn isometric_global_transform(
279    nodes: &NodePool,
280    node: Handle<impl ObjectOrVariant<Node>>,
281) -> Matrix4<f32> {
282    let node = node.to_base();
283    let parent = nodes[node].parent();
284    if parent.is_some() {
285        isometric_global_transform(nodes, parent) * isometric_local_transform(nodes, node)
286    } else {
287        isometric_local_transform(nodes, node)
288    }
289}
290
291// Clears all information about parent-child relations of a given node. This is needed in some
292// cases (mostly when copying a node), because `Graph::add_node` uses children list to attach
293// children to the given node, and when copying a node it is important that this step is skipped.
294fn clear_links(mut node: Node) -> Node {
295    node.children.clear();
296    node.parent = Handle::NONE;
297    node
298}
299
300/// A set of switches that allows you to disable a particular step of graph update pipeline.
301#[derive(Debug, Clone, PartialEq, Eq)]
302pub struct GraphUpdateSwitches {
303    /// Enables the physics update to have a non-zero `dt`.
304    pub physics_dt: bool,
305    /// Enables or disables update of the 2D physics.
306    pub physics2d: bool,
307    /// Enables or disables update of the 3D physics.
308    pub physics: bool,
309    /// A set of nodes that will be updated, everything else won't be updated.
310    pub node_overrides: Option<FxHashSet<Handle<Node>>>,
311    /// Enables or disables deletion of the nodes with ended lifetime (lifetime <= 0.0). If set to `false` the lifetime
312    /// of the nodes won't be changed.
313    pub delete_dead_nodes: bool,
314    /// Whether the graph update is paused or not. Paused graphs won't be updated and their sound content will be also paused
315    /// so it won't emit any sounds.
316    pub paused: bool,
317}
318
319impl Default for GraphUpdateSwitches {
320    fn default() -> Self {
321        Self {
322            physics_dt: true,
323            physics2d: true,
324            physics: true,
325            node_overrides: Default::default(),
326            delete_dead_nodes: true,
327            paused: false,
328        }
329    }
330}
331
332/// A set of potential errors that may occur when using the [`Graph`] API.
333#[derive(PartialEq)]
334pub enum GraphError {
335    /// An error from the underlying scene node storage. See [`PoolError`] for more info.
336    PoolError(PoolError),
337    /// There's no script of the requested type.
338    NoScript {
339        /// Handle of the node.
340        handle: Handle<Node>,
341        /// Type name of the script.
342        script_type_name: &'static str,
343    },
344    /// There's no script component of the requested type.
345    NoScriptComponent {
346        /// Handle of the node.
347        handle: Handle<Node>,
348        /// Type name of the script component.
349        component_type_name: &'static str,
350    },
351    /// There's no scene node with the given id.
352    UnknownId(SceneNodeId),
353}
354
355impl Display for GraphError {
356    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
357        match self {
358            GraphError::PoolError(err) => std::fmt::Display::fmt(&err, f),
359            GraphError::NoScript {
360                handle,
361                script_type_name,
362            } => {
363                write!(
364                    f,
365                    "There's no script {script_type_name} on the scene node {handle}"
366                )
367            }
368            GraphError::NoScriptComponent {
369                handle,
370                component_type_name,
371            } => {
372                write!(
373                    f,
374                    "There's no script component {component_type_name} on the scene node {handle}"
375                )
376            }
377            GraphError::UnknownId(id) => {
378                write!(f, "There's no scene node with {id:?} id!")
379            }
380        }
381    }
382}
383
384impl Debug for GraphError {
385    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
386        write!(f, "{}", self)
387    }
388}
389
390impl std::error::Error for GraphError {}
391
392impl From<PoolError> for GraphError {
393    fn from(value: PoolError) -> Self {
394        Self::PoolError(value)
395    }
396}
397
398impl Graph {
399    /// Creates new graph instance with single root node.
400    #[inline]
401    pub fn new() -> Self {
402        let (script_message_sender, script_message_receiver) = channel();
403        let (message_sender, message_receiver) = channel();
404
405        // Create root node.
406        let mut root_node = Pivot::default();
407        let instance_id = root_node.instance_id;
408        root_node.set_name("__ROOT__");
409
410        // Add it to the pool.
411        let mut pool = Pool::new();
412        let root = pool.spawn(Node::new(root_node));
413        pool[root].on_connected_to_graph(
414            root,
415            message_sender.clone(),
416            script_message_sender.clone(),
417        );
418
419        let instance_id_map = FxHashMap::from_iter([(instance_id, root)]);
420
421        Self {
422            physics: Default::default(),
423            stack: Vec::new(),
424            root,
425            pool,
426            physics2d: Default::default(),
427            sound_context: SoundContext::new(),
428            performance_statistics: Default::default(),
429            event_broadcaster: Default::default(),
430            script_message_receiver,
431            message_sender,
432            script_message_sender,
433            lightmap: None,
434            instance_id_map,
435            message_receiver,
436            user_data: Default::default(),
437        }
438    }
439
440    /// Begins multi-borrowing and gives access to the 3D physics world at the same time. The physics
441    /// world could be used to perform shape or ray casting while having the ability to modify scene
442    /// nodes.
443    pub fn begin_multi_borrow_with_physics_3d(
444        &mut self,
445    ) -> (MultiBorrowContext<Node, NodeContainer>, &PhysicsWorld) {
446        (self.pool.begin_multi_borrow(), &self.physics)
447    }
448
449    /// Begins multi-borrowing and gives access to the 2D physics world at the same time. The physics
450    /// world could be used to perform shape or ray casting while having the ability to modify scene
451    /// nodes.
452    pub fn begin_multi_borrow_with_physics_2d(
453        &mut self,
454    ) -> (MultiBorrowContext<Node, NodeContainer>, &PhysicsWorld) {
455        (self.pool.begin_multi_borrow(), &mut self.physics)
456    }
457
458    /// Begins multi-borrowing and gives access to the 3D and 2D physics world at the same time. The
459    /// physics world could be used to perform shape or ray casting while having the ability to modify
460    /// scene nodes.
461    pub fn begin_multi_borrow_with_physics(
462        &mut self,
463    ) -> (
464        MultiBorrowContext<Node, NodeContainer>,
465        &PhysicsWorld,
466        &dim2::physics::PhysicsWorld,
467    ) {
468        (
469            self.pool.begin_multi_borrow(),
470            &self.physics,
471            &self.physics2d,
472        )
473    }
474
475    /// Creates a new graph using a hierarchy of nodes specified by the `root`.
476    pub fn from_hierarchy(root: Handle<Node>, other_graph: &Self) -> Self {
477        let mut graph = Self::default();
478        other_graph.copy_node(
479            root,
480            &mut graph,
481            false,
482            &mut |_, _| true,
483            &mut |_, _| {},
484            &mut |_, _, _| {},
485        );
486        graph
487    }
488
489    fn recursive_summary(
490        &self,
491        indent: usize,
492        current: Handle<impl ObjectOrVariant<Node>>,
493        result: &mut String,
494    ) {
495        let current = current.to_base();
496        for _ in 0..indent {
497            result.push_str("  ");
498        }
499        let Ok(node) = self.try_get(current) else {
500            use std::fmt::Write;
501            writeln!(result, "{}: Failed to get", current).unwrap();
502            return;
503        };
504        result.push_str(&node.summary());
505        result.push('\n');
506        for script in node.scripts() {
507            for _ in 0..indent + 1 {
508                result.push_str("  ");
509            }
510            result.push_str("+ Script: ");
511            result.push_str(&script.summary());
512            result.push('\n');
513        }
514        for child in node.children() {
515            self.recursive_summary(indent + 1, *child, result);
516        }
517    }
518
519    /// Sets new root of the graph and attaches the old root to the new root. Old root becomes a child
520    /// node of the new root.
521    pub fn change_root_node(&mut self, root: Node) {
522        let prev_root = self.root;
523        self.root = Handle::NONE;
524        let handle = self.add_node(root);
525        assert_eq!(self.root, handle);
526        self.link_nodes(prev_root, handle);
527    }
528
529    /// Tries to find references of the given node in other scene nodes. It could be used to check if the node is
530    /// used by some other scene node or not. Returns an array of nodes, that references the given node. This method
531    /// is reflection-based, so it is quite slow and should not be used every frame.
532    pub fn find_references_to(
533        &self,
534        target: Handle<impl ObjectOrVariant<Node>>,
535    ) -> Vec<Handle<Node>> {
536        let mut references = Vec::new();
537        for (node_handle, node) in self.pair_iter() {
538            (node as &dyn Reflect).apply_recursively(
539                &mut |object| {
540                    object.as_any(&mut |any| {
541                        if let Some(handle) = any.downcast_ref::<Handle<Node>>() {
542                            if *handle == target {
543                                references.push(node_handle);
544                            }
545                        }
546                    })
547                },
548                &[TypeId::of::<UntypedResource>()],
549            );
550        }
551        references
552    }
553
554    /// Sets global position of a scene node. Internally, this method converts the given position
555    /// to the local space of the parent node of the given scene node and sets it as local position
556    /// of the node. In other words, this method does not modify global position itself, but calculates
557    /// new local position of the given node so that its global position will be as requested.
558    ///
559    /// ## Important
560    ///
561    /// This method relies on pre-calculated global transformation of the hierarchy. This may give
562    /// unexpected results if you've modified transforms of ancestors in the hierarchy of the node
563    /// and then called this method. This happens because global transform calculation is deferred
564    /// to the end of the frame. If you want to ensure that everything works as expected, call
565    /// [`Self::update_hierarchical_data`] before calling this method. It is not called automatically,
566    /// because it is quite heavy, and in most cases this method works ok without it.
567    pub fn set_global_position(
568        &mut self,
569        node_handle: Handle<impl ObjectOrVariant<Node>>,
570        position: Vector3<f32>,
571    ) {
572        let node_handle = node_handle.to_base();
573        let (node, parent) = self
574            .pool
575            .try_borrow_dependant_mut(node_handle, |node| node.parent());
576        if let Ok(node) = node {
577            if let Ok(parent) = parent {
578                let relative_position = parent
579                    .global_transform()
580                    .try_inverse()
581                    .unwrap_or_default()
582                    .transform_point(&position.into())
583                    .coords;
584                node.local_transform_mut().set_position(relative_position);
585            } else {
586                node.local_transform_mut().set_position(position);
587            }
588            self.update_hierarchical_data_for_descendants(node_handle);
589        }
590    }
591
592    /// Sets global rotation of a scene node. Internally, this method converts the given rotation
593    /// to the local space of the parent node of the given scene node and sets it as local rotation
594    /// of the node. In other words, this method does not modify global rotation itself, but calculates
595    /// new local rotation of the given node so that its global rotation will be as requested.
596    ///
597    /// ## Important
598    ///
599    /// This method relies on pre-calculated global transformation of the hierarchy. This may give
600    /// unexpected results if you've modified transforms of ancestors in the hierarchy of the node
601    /// and then called this method. This happens because global transform calculation is deferred
602    /// to the end of the frame. If you want to ensure that everything works as expected, call
603    /// [`Self::update_hierarchical_data`] before calling this method. It is not called automatically,
604    /// because it is quite heavy, and in most cases this method works ok without it.
605    pub fn set_global_rotation(
606        &mut self,
607        node: Handle<impl ObjectOrVariant<Node>>,
608        rotation: UnitQuaternion<f32>,
609    ) {
610        let node = node.to_base();
611        let (node, parent) = self
612            .pool
613            .try_borrow_dependant_mut(node, |node| node.parent());
614        if let Ok(node) = node {
615            if let Ok(parent) = parent {
616                let basis = parent
617                    .global_transform()
618                    .try_inverse()
619                    .unwrap_or_default()
620                    .basis();
621                let relative_rotation = UnitQuaternion::from_matrix(&basis) * rotation;
622                node.local_transform_mut().set_rotation(relative_rotation);
623            } else {
624                node.local_transform_mut().set_rotation(rotation);
625            }
626        }
627    }
628
629    /// Tries to borrow mutable references to two nodes at the same time by given handles. Will
630    /// panic if handles overlaps (points to same node).
631    #[inline]
632    pub fn get_two_mut(&mut self, nodes: (Handle<Node>, Handle<Node>)) -> (&mut Node, &mut Node) {
633        self.pool.borrow_two_mut(nodes)
634    }
635
636    /// Tries to borrow mutable references to three nodes at the same time by given handles. Will
637    /// return Err of handles overlaps (points to same node).
638    #[inline]
639    pub fn get_three_mut(
640        &mut self,
641        nodes: (Handle<Node>, Handle<Node>, Handle<Node>),
642    ) -> (&mut Node, &mut Node, &mut Node) {
643        self.pool.borrow_three_mut(nodes)
644    }
645
646    /// Tries to borrow mutable references to four nodes at the same time by given handles. Will
647    /// panic if handles overlaps (points to same node).
648    #[inline]
649    pub fn get_four_mut(
650        &mut self,
651        nodes: (Handle<Node>, Handle<Node>, Handle<Node>, Handle<Node>),
652    ) -> (&mut Node, &mut Node, &mut Node, &mut Node) {
653        self.pool.borrow_four_mut(nodes)
654    }
655
656    /// Returns root node of current graph.
657    #[inline]
658    pub fn get_root(&self) -> Handle<Node> {
659        self.root
660    }
661
662    /// Begins multi-borrow that allows you borrow to as many shared references to the graph
663    /// nodes as you need and only one mutable reference to a node. See
664    /// [`MultiBorrowContext::try_get`] for more info.
665    ///
666    /// ## Examples
667    ///
668    /// ```rust
669    /// # use fyrox_impl::{
670    /// #     core::pool::Handle,
671    /// #     scene::{base::BaseBuilder, graph::Graph, node::Node, pivot::PivotBuilder},
672    /// # };
673    /// #
674    /// let mut graph = Graph::new();
675    ///
676    /// let handle1 = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
677    /// let handle2 = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
678    /// let handle3 = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
679    /// let handle4 = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
680    ///
681    /// let mut ctx = graph.begin_multi_borrow();
682    ///
683    /// let node1 = ctx.try_get(handle1);
684    /// let node2 = ctx.try_get(handle2);
685    /// let node3 = ctx.try_get(handle3);
686    /// let node4 = ctx.try_get(handle4);
687    ///
688    /// assert!(node1.is_ok());
689    /// assert!(node2.is_ok());
690    /// assert!(node3.is_ok());
691    /// assert!(node4.is_ok());
692    ///
693    /// // An attempt to borrow the same node twice as immutable and mutable will fail.
694    /// assert!(ctx.try_get_mut(handle1).is_err());
695    /// ```
696    #[inline]
697    pub fn begin_multi_borrow(&mut self) -> MultiBorrowContext<Node, NodeContainer> {
698        self.pool.begin_multi_borrow()
699    }
700
701    /// Links specified child with specified parent while keeping the
702    /// child's global position and rotation.
703    #[inline]
704    pub fn link_nodes_keep_global_transform(
705        &mut self,
706        child: Handle<impl ObjectOrVariant<Node>>,
707        parent: Handle<impl ObjectOrVariant<Node>>,
708    ) {
709        let child = child.to_base();
710        let parent = parent.to_base();
711        let parent_global_transform_inv = self.pool[parent]
712            .global_transform()
713            .try_inverse()
714            .unwrap_or_default();
715        let child_global_transform = self.pool[child].global_transform();
716        let relative_transform = parent_global_transform_inv * child_global_transform;
717        let local_position = relative_transform.position();
718        let parent_inv_global_rotation = self.global_rotation(parent).inverse();
719        let local_rotation = parent_inv_global_rotation * self.global_rotation(child);
720        let local_scale = self
721            .global_scale(child)
722            .component_div(&self.global_scale(parent));
723        self.pool[child]
724            .local_transform_mut()
725            .set_position(local_position)
726            .set_rotation(local_rotation)
727            .set_scale(local_scale);
728        self.link_nodes(child, parent);
729    }
730
731    /// Searches for a **first** node with a script of the given type `S` in the hierarchy starting from the
732    /// given `root_node`.
733    #[inline]
734    pub fn find_first_by_script<S>(
735        &self,
736        root_node: Handle<impl ObjectOrVariant<Node>>,
737    ) -> Option<(Handle<Node>, &Node)>
738    where
739        S: ScriptTrait,
740    {
741        self.find(root_node, &mut |node| {
742            for script in &node.scripts {
743                if script.as_ref().and_then(|s| s.cast::<S>()).is_some() {
744                    return true;
745                }
746            }
747            false
748        })
749    }
750
751    /// Creates deep copy of node with all children. This is relatively heavy operation!
752    /// In case if any error happened it returns `Handle::NONE`. This method can be used
753    /// to create exact copy of given node hierarchy. For example you can prepare rocket
754    /// model: case of rocket will be mesh, and fire from nozzle will be particle system,
755    /// and when you fire from rocket launcher you just need to create a copy of such
756    /// "prefab".
757    ///
758    /// * `node_handle`: The handle of the node to copy.
759    /// * `dest_graph`: A mutable borrow of the node graph that will contain the newly created copy.
760    /// * `filter`: A function that takes a node handle and a borrow of a node and returns a bool.
761    ///   The is called with the handle and node of each child of `node_handle` to determine if
762    ///   that child should be recursively copied, and then the same filter is applied to each recursive step.
763    /// * `pre_processing_callback`: A function that takes a node handle and a mutable node.
764    ///   The handle belongs to the original node in this graph. The node is a copy of the original
765    ///   node, except that parent handle and child handles have been removed. This is a node
766    ///   that will be inserted into `dest_graph`.
767    /// * `post_processing_callback`: A function much like `pre_processing_callback` except that
768    ///   it is called after the new node and all its children have been inserted into the graph.
769    ///   The function takes (new handle, original handle, node) as parameters. The node has handles
770    ///   for its newly copied children, but no handle for its parent.
771    ///
772    /// # Implementation notes
773    ///
774    /// Returns tuple where first element is handle to copy of node, and second element -
775    /// old-to-new hash map, which can be used to easily find copy of node by its original.
776    ///
777    /// Filter allows to exclude some nodes from copied hierarchy. It must return false for
778    /// odd nodes. Filtering applied only to descendant nodes.
779    #[inline]
780    pub fn copy_node<F, Pre, Post>(
781        &self,
782        node_handle: Handle<impl ObjectOrVariant<Node>>,
783        dest_graph: &mut Graph,
784        preserve_handles: bool,
785        filter: &mut F,
786        pre_process_callback: &mut Pre,
787        post_process_callback: &mut Post,
788    ) -> (Handle<Node>, NodeHandleMap<Node>)
789    where
790        F: FnMut(Handle<Node>, &Node) -> bool,
791        Pre: FnMut(Handle<Node>, &mut Node),
792        Post: FnMut(Handle<Node>, Handle<Node>, &mut Node),
793    {
794        let mut old_new_mapping = NodeHandleMap::default();
795        let root_handle = self.copy_node_raw(
796            node_handle,
797            dest_graph,
798            preserve_handles,
799            &mut old_new_mapping,
800            filter,
801            pre_process_callback,
802            post_process_callback,
803        );
804
805        remap_handles(&old_new_mapping, dest_graph);
806
807        (root_handle, old_new_mapping)
808    }
809
810    /// Creates deep copy of node with all children. This is relatively heavy operation!
811    /// In case if any error happened it returns `Handle::NONE`. This method can be used
812    /// to create exact copy of given node hierarchy. For example you can prepare rocket
813    /// model: case of rocket will be mesh, and fire from nozzle will be particle system,
814    /// and when you fire from rocket launcher you just need to create a copy of such
815    /// "prefab".
816    ///
817    /// # Implementation notes
818    ///
819    /// Returns tuple where first element is handle to copy of node, and second element -
820    /// old-to-new hash map, which can be used to easily find copy of node by its original.
821    ///
822    /// Filter allows to exclude some nodes from copied hierarchy. It must return false for
823    /// odd nodes. Filtering applied only to descendant nodes.
824    #[inline]
825    pub fn copy_node_inplace<F>(
826        &mut self,
827        node_handle: Handle<Node>,
828        filter: &mut F,
829    ) -> (Handle<Node>, NodeHandleMap<Node>)
830    where
831        F: FnMut(Handle<Node>, &Node) -> bool,
832    {
833        let mut old_new_mapping = NodeHandleMap::default();
834
835        let to_copy = self
836            .traverse_iter(node_handle)
837            .map(|(descendant_handle, descendant)| (descendant_handle, descendant.children.clone()))
838            .collect::<Vec<_>>();
839
840        let mut root_handle = Handle::NONE;
841
842        for (parent, children) in to_copy.iter() {
843            // Copy parent first.
844            let parent_copy = clear_links(self.pool[*parent].clone_box());
845            let parent_copy_handle = self.add_node(parent_copy);
846            old_new_mapping.insert(*parent, parent_copy_handle);
847
848            if root_handle.is_none() {
849                root_handle = parent_copy_handle;
850            }
851
852            // Copy children and link to new parent.
853            for &child in children {
854                if filter(child, &self.pool[child]) {
855                    let child_copy = clear_links(self.pool[child].clone_box());
856                    let child_copy_handle = self.add_node(child_copy);
857                    old_new_mapping.insert(child, child_copy_handle);
858                    self.link_nodes(child_copy_handle, parent_copy_handle);
859                }
860            }
861        }
862
863        remap_handles(&old_new_mapping, self);
864
865        (root_handle, old_new_mapping)
866    }
867
868    /// Creates copy of a node and breaks all connections with other nodes. Keep in mind that
869    /// this method may give unexpected results when the node has connections with other nodes.
870    /// For example if you'll try to copy a skinned mesh, its copy won't be skinned anymore -
871    /// you'll get just a "shallow" mesh. Also unlike [copy_node](struct.Graph.html#method.copy_node)
872    /// this method returns copied node directly, it does not inserts it in any graph.
873    #[inline]
874    pub fn copy_single_node(&self, node_handle: Handle<Node>) -> Node {
875        let node = &self.pool[node_handle];
876        let mut clone = clear_links(node.clone_box());
877        if let Some(ref mut mesh) = clone.cast_mut::<Mesh>() {
878            for surface in mesh.surfaces_mut() {
879                surface.bones.clear();
880            }
881        }
882        clone
883    }
884
885    /// * `node_handle`: The handle of the node to copy.
886    /// * `dest_graph`: A mutable borrow of the node graph that will contain the newly created copy.
887    /// * `old_new_mapping`: A mutable hashmap of node handles which records which original nodes were copied to
888    ///   become which new nodes.
889    /// * `filter`: A function that takes a node handle and a borrow of a node and returns a bool.
890    ///   The is called with the handle and node of each child of `node_handle` to determine if
891    ///   that child should be recursively copied, and then the same filter is applied to each recursive step.
892    /// * `pre_processing_callback`: A function that takes a node handle and a mutable node.
893    ///   The handle belongs to the original node in this graph. The node is a copy of the original
894    ///   node, except that parent handle and child handles have been removed. This is a node
895    ///   that will be inserted into `dest_graph`.
896    /// * `post_processing_callback`: A function much like `pre_processing_callback` except that
897    ///   it is called after the new node and all its children have been inserted into the graph.
898    ///   The function takes (new handle, original handle, node) as parameters. The node has handles
899    ///   for its newly copied children, but no handle for its parent.
900    fn copy_node_raw<F, Pre, Post>(
901        &self,
902        root_handle: Handle<impl ObjectOrVariant<Node>>,
903        dest_graph: &mut Graph,
904        preserve_handles: bool,
905        old_new_mapping: &mut NodeHandleMap<Node>,
906        filter: &mut F,
907        pre_process_callback: &mut Pre,
908        post_process_callback: &mut Post,
909    ) -> Handle<Node>
910    where
911        F: FnMut(Handle<Node>, &Node) -> bool,
912        Pre: FnMut(Handle<Node>, &mut Node),
913        Post: FnMut(Handle<Node>, Handle<Node>, &mut Node),
914    {
915        let root_handle = root_handle.to_base();
916        let src_node = &self.pool[root_handle];
917        let mut dest_node = clear_links(src_node.clone_box());
918        pre_process_callback(root_handle, &mut dest_node);
919        let dest_copy_handle = if preserve_handles {
920            dest_graph.add_node_at_handle(dest_node, root_handle);
921            root_handle
922        } else {
923            dest_graph.add_node(dest_node)
924        };
925        old_new_mapping.insert(root_handle, dest_copy_handle);
926        for &src_child_handle in src_node.children() {
927            if filter(src_child_handle, &self.pool[src_child_handle]) {
928                let dest_child_handle = self.copy_node_raw(
929                    src_child_handle,
930                    dest_graph,
931                    preserve_handles,
932                    old_new_mapping,
933                    filter,
934                    pre_process_callback,
935                    post_process_callback,
936                );
937                if !dest_child_handle.is_none() {
938                    dest_graph.link_nodes(dest_child_handle, dest_copy_handle);
939                }
940            }
941        }
942        post_process_callback(
943            dest_copy_handle,
944            root_handle,
945            &mut dest_graph[dest_copy_handle],
946        );
947        dest_copy_handle
948    }
949
950    /// Reconnects every node to the graph by calling its [`Base::on_connected_to_graph`](crate::scene::base::Base::on_connected_to_graph)
951    /// method, giving the node its `self_handle` and the graph's `message_sender` and `script_message_sender`.
952    fn restore_dynamic_node_data(&mut self) {
953        for (handle, node) in self.pool.pair_iter_mut() {
954            node.on_connected_to_graph(
955                handle,
956                self.message_sender.clone(),
957                self.script_message_sender.clone(),
958            );
959        }
960    }
961
962    /// Fix property flags for scenes made before inheritance system was fixed. By default, all inheritable properties
963    /// must be marked as modified in nodes without any parent resource.
964    pub(crate) fn mark_ancestor_nodes_as_modified(&mut self) {
965        for node in self.linear_iter_mut() {
966            if node.resource.is_none() {
967                node.mark_inheritable_variables_as_modified();
968            }
969        }
970    }
971
972    /// Synchronizes the state of the graph with external resources.
973    pub(crate) fn resolve(&mut self) {
974        Log::writeln(MessageKind::Information, "Resolving graph...");
975
976        self.restore_dynamic_node_data();
977        self.mark_ancestor_nodes_as_modified();
978        // Since the parent resources may have changed, iterate through every node and try to find
979        // the corresponding node in its resource, either by name or by handle depending on the resource's
980        // 'NodeMapping`. If a corresponding node cannot be found in the resource, then delete the node.
981        self.restore_original_handles_and_inherit_properties(
982            &[TypeId::of::<navmesh::Container>()],
983            |resource_node, node| {
984                node.inv_bind_pose_transform = resource_node.inv_bind_pose_transform;
985            },
986        );
987        self.update_hierarchical_data();
988        // Create a list of (handle, resource) pairs where the handle points to a node that is the root of some instance
989        // of the resource within this graph. At the same time, modify each node so that its unmodified values match the
990        // corresponding values from within the instance's resource, so if the resource has changed the nodes will now
991        // reflect that change.
992        let instances = self.restore_integrity(|model, model_data, handle, dest_graph| {
993            ModelResource::instantiate_from(model, model_data, handle, dest_graph, &mut |_, _| {})
994        });
995        // Iterate through the list of (handle, resource) pairs and use reflection to replace each handle within each instance
996        // with the handle that corresponds to the associated copy in this graph. This is necessary because after
997        // `restore_original_handles_and_inherit_properties` the handles will have been reset back to their original values
998        // which refer to nodes *within* the resource instead of nodes in this graph.
999        self.remap_handles(&instances);
1000
1001        self.apply_lightmap();
1002
1003        Log::writeln(MessageKind::Information, "Graph resolved successfully!");
1004    }
1005
1006    /// Tries to set new lightmap to scene.
1007    pub fn set_lightmap(
1008        &mut self,
1009        new_lightmap: Option<Lightmap>,
1010    ) -> Result<Option<Lightmap>, &'static str> {
1011        if let Some(lightmap) = new_lightmap.as_ref() {
1012            // Assign textures to surfaces.
1013            for (handle, lightmaps) in lightmap.map.iter() {
1014                if let Ok(mesh) = self.try_get_mut_of_type::<Mesh>(*handle) {
1015                    if mesh.surfaces().len() != lightmaps.len() {
1016                        return Err("failed to set lightmap, surface count mismatch");
1017                    }
1018
1019                    for (surface, entry) in mesh.surfaces_mut().iter_mut().zip(lightmaps) {
1020                        // This unwrap() call must never panic in normal conditions, because texture wrapped in Option
1021                        // only to implement Default trait to be serializable.
1022                        let texture = entry.texture.clone().unwrap();
1023                        let material = surface.material.deep_copy();
1024                        let mut material_state = material.state();
1025                        if let Some(material) = material_state.data() {
1026                            material.bind(
1027                                &lightmap.texture_name,
1028                                MaterialResourceBinding::Texture(MaterialTextureBinding {
1029                                    value: Some(texture),
1030                                }),
1031                            );
1032                        }
1033                        drop(material_state);
1034                        surface.material.set_value_and_mark_modified(material);
1035                    }
1036                }
1037            }
1038        } else if let Some(existing_lightmap) = self.lightmap.as_ref() {
1039            let texture_name = existing_lightmap.texture_name.clone();
1040            for node in self.linear_iter_mut() {
1041                if let Some(mesh) = node.cast_mut::<Mesh>() {
1042                    for surface in mesh.surfaces_mut() {
1043                        let mut material_state = surface.material().state();
1044                        if let Some(material) = material_state.data() {
1045                            material.bind(
1046                                &texture_name,
1047                                MaterialResourceBinding::Texture(MaterialTextureBinding {
1048                                    value: None,
1049                                }),
1050                            );
1051                        }
1052                    }
1053                }
1054            }
1055        }
1056        Ok(std::mem::replace(&mut self.lightmap, new_lightmap))
1057    }
1058
1059    /// Returns current lightmap.
1060    pub fn lightmap(&self) -> Option<&Lightmap> {
1061        self.lightmap.as_ref()
1062    }
1063
1064    fn apply_lightmap(&mut self) {
1065        // Re-apply lightmap if any. This has to be done after resolve because we must patch surface
1066        // data at this stage, but if we'd do this before we wouldn't be able to do this because
1067        // meshes contains invalid surface data.
1068        if let Some(lightmap) = self.lightmap.as_mut() {
1069            // Patch surface data first. To do this we gather all surface data instances and
1070            // look in patch data if we have patch for data.
1071            let mut unique_data_set = FxHashMap::default();
1072            for &handle in lightmap.map.keys() {
1073                if let Some(mesh) = self.pool[handle].cast_mut::<Mesh>() {
1074                    for surface in mesh.surfaces() {
1075                        let data = surface.data();
1076                        unique_data_set.entry(data.key()).or_insert(data);
1077                    }
1078                }
1079            }
1080
1081            for (_, surface_data) in unique_data_set.into_iter() {
1082                let mut data = surface_data.data_ref();
1083
1084                if let Some(patch) = lightmap.patches.get(&data.content_hash()) {
1085                    lightmap::apply_surface_data_patch(
1086                        &mut data,
1087                        &patch.0,
1088                        lightmap.second_tex_coord_location,
1089                    );
1090                }
1091            }
1092
1093            // Apply textures.
1094            for (&handle, entries) in lightmap.map.iter_mut() {
1095                if let Some(mesh) = self.pool[handle].cast_mut::<Mesh>() {
1096                    for (entry, surface) in entries.iter_mut().zip(mesh.surfaces_mut()) {
1097                        let material = surface.material.deep_copy();
1098                        let mut material_state = material.state();
1099                        if let Some(material) = material_state.data() {
1100                            material.bind(
1101                                &lightmap.texture_name,
1102                                MaterialResourceBinding::Texture(MaterialTextureBinding {
1103                                    value: entry.texture.clone(),
1104                                }),
1105                            );
1106                        }
1107                        drop(material_state);
1108                        surface.material.set_value_and_mark_modified(material);
1109                    }
1110                }
1111            }
1112        }
1113    }
1114
1115    /// Tries to compute combined axis-aligned bounding box (AABB) in world-space of the hierarchy starting from the given
1116    /// scene node. It will return [`None`] if the scene node handle is invalid, otherwise it will return AABB that enclosing
1117    /// all the nodes in the hierarchy.
1118    pub fn aabb_of_descendants<F>(
1119        &self,
1120        root: Handle<impl ObjectOrVariant<Node>>,
1121        mut filter: F,
1122    ) -> Option<AxisAlignedBoundingBox>
1123    where
1124        F: FnMut(Handle<Node>, &Node) -> bool,
1125    {
1126        let root = root.to_base();
1127        fn aabb_of_descendants_recursive<F>(
1128            graph: &Graph,
1129            node: Handle<Node>,
1130            filter: &mut F,
1131        ) -> Option<AxisAlignedBoundingBox>
1132        where
1133            F: FnMut(Handle<Node>, &Node) -> bool,
1134        {
1135            graph.try_get_node(node).ok().and_then(|n| {
1136                if filter(node, n) {
1137                    let mut aabb = n.local_bounding_box();
1138                    if aabb.is_invalid_or_degenerate() {
1139                        aabb = AxisAlignedBoundingBox::collapsed().transform(&n.global_transform());
1140                    } else {
1141                        aabb = aabb.transform(&n.global_transform());
1142                    }
1143                    for child in n.children() {
1144                        if let Some(child_aabb) =
1145                            aabb_of_descendants_recursive(graph, *child, filter)
1146                        {
1147                            aabb.add_box(child_aabb);
1148                        }
1149                    }
1150                    Some(aabb)
1151                } else {
1152                    None
1153                }
1154            })
1155        }
1156        aabb_of_descendants_recursive(self, root, &mut filter)
1157    }
1158
1159    pub(crate) fn update_enabled_flag_recursively(nodes: &NodePool, node_handle: Handle<Node>) {
1160        let Ok(node) = nodes.try_borrow(node_handle) else {
1161            return;
1162        };
1163
1164        let parent_enabled = nodes
1165            .try_borrow(node.parent())
1166            .ok()
1167            .is_none_or(|p| p.is_globally_enabled());
1168        node.global_enabled.set(parent_enabled && node.is_enabled());
1169
1170        for &child in node.children() {
1171            Self::update_enabled_flag_recursively(nodes, child);
1172        }
1173    }
1174
1175    pub(crate) fn update_visibility_recursively(nodes: &NodePool, node_handle: Handle<Node>) {
1176        let Ok(node) = nodes.try_borrow(node_handle) else {
1177            return;
1178        };
1179
1180        let parent_visibility = nodes
1181            .try_borrow(node.parent())
1182            .ok()
1183            .is_none_or(|p| p.global_visibility());
1184        node.global_visibility
1185            .set(parent_visibility && node.visibility());
1186
1187        for &child in node.children() {
1188            Self::update_visibility_recursively(nodes, child);
1189        }
1190    }
1191
1192    pub(crate) fn update_global_transform_recursively(
1193        nodes: &NodePool,
1194        sound_context: &mut SoundContext,
1195        physics: &mut PhysicsWorld,
1196        physics2d: &mut dim2::physics::PhysicsWorld,
1197        node_handle: Handle<Node>,
1198    ) {
1199        let Ok(node) = nodes.try_borrow(node_handle) else {
1200            return;
1201        };
1202
1203        let parent_global_transform = if let Ok(parent) = nodes.try_borrow(node.parent()) {
1204            parent.global_transform()
1205        } else {
1206            Matrix4::identity()
1207        };
1208
1209        let new_global_transform = parent_global_transform * node.local_transform().matrix();
1210
1211        // TODO: Detect changes from user code here.
1212        node.on_global_transform_changed(
1213            &new_global_transform,
1214            &mut SyncContext {
1215                nodes,
1216                physics,
1217                physics2d,
1218                sound_context,
1219                switches: None,
1220            },
1221        );
1222
1223        node.global_transform.set(new_global_transform);
1224
1225        for &child in node.children() {
1226            Self::update_global_transform_recursively(
1227                nodes,
1228                sound_context,
1229                physics,
1230                physics2d,
1231                child,
1232            );
1233        }
1234    }
1235
1236    /// Calculates local and global transform, global visibility for each node in graph starting from the
1237    /// specified node and down the tree. The main use case of the method is to update global position (etc.)
1238    /// of an hierarchy of the nodes of some new prefab instance.
1239    ///
1240    /// # Important Notes
1241    ///
1242    /// This method could be slow for large hierarchies. You should call it only when absolutely needed.
1243    #[inline]
1244    pub fn update_hierarchical_data_for_descendants(
1245        &mut self,
1246        node_handle: Handle<impl ObjectOrVariant<Node>>,
1247    ) {
1248        Self::update_hierarchical_data_recursively(
1249            &self.pool,
1250            &mut self.sound_context,
1251            &mut self.physics,
1252            &mut self.physics2d,
1253            node_handle.to_base(),
1254        );
1255    }
1256
1257    /// Calculates local and global transform, global visibility for each node in graph starting from the
1258    /// specified node and down the tree. The main use case of the method is to update global position (etc.)
1259    /// of an hierarchy of the nodes of some new prefab instance.
1260    ///
1261    /// # Important Notes
1262    ///
1263    /// This method could be slow for large graph. You should call it only when absolutely needed.
1264    #[inline]
1265    pub fn update_hierarchical_data(&mut self) {
1266        self.update_hierarchical_data_for_descendants(self.root);
1267    }
1268
1269    pub(crate) fn update_hierarchical_data_recursively(
1270        nodes: &NodePool,
1271        sound_context: &mut SoundContext,
1272        physics: &mut PhysicsWorld,
1273        physics2d: &mut dim2::physics::PhysicsWorld,
1274        node_handle: Handle<Node>,
1275    ) {
1276        Self::update_global_transform_recursively(
1277            nodes,
1278            sound_context,
1279            physics,
1280            physics2d,
1281            node_handle,
1282        );
1283        Self::update_enabled_flag_recursively(nodes, node_handle);
1284        Self::update_visibility_recursively(nodes, node_handle);
1285    }
1286
1287    // This method processes messages from scene nodes and propagates changes on descendant nodes
1288    // in the hierarchy. Scene nodes have global transform, visibility and enabled flags and their
1289    // values depend on the values of ancestors in the hierarchy. This method uses optimized changes
1290    // propagation that propagates changes on small "chains" of nodes instead of updating the entire
1291    // graph. This is much faster since most scene nodes remain unchanged most of the time.
1292    //
1293    // Performance of this method is detached from the amount of scene nodes in the graph and only
1294    // correlates with the amount of changing nodes, allowing to have large scene graphs with tons
1295    // of static nodes.
1296    pub(crate) fn process_node_messages(&mut self, switches: Option<&GraphUpdateSwitches>) {
1297        bitflags! {
1298            #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1299            struct Flags: u8 {
1300                const NONE = 0;
1301                const TRANSFORM_CHANGED = 0b0001;
1302                const VISIBILITY_CHANGED = 0b0010;
1303                const ENABLED_FLAG_CHANGED = 0b0100;
1304            }
1305        }
1306
1307        let mut visited_flags = vec![Flags::NONE; self.pool.get_capacity() as usize];
1308        let mut roots = FxHashMap::default();
1309
1310        while let Ok(message) = self.message_receiver.try_recv() {
1311            if let NodeMessageKind::TransformChanged = message.kind {
1312                if let Ok(node) = self.pool.try_borrow(message.node) {
1313                    node.on_local_transform_changed(&mut SyncContext {
1314                        nodes: &self.pool,
1315                        physics: &mut self.physics,
1316                        physics2d: &mut self.physics2d,
1317                        sound_context: &mut self.sound_context,
1318                        switches,
1319                    })
1320                }
1321            }
1322
1323            // Prepare for hierarchy propagation.
1324            let message_flag = match message.kind {
1325                NodeMessageKind::TransformChanged => Flags::TRANSFORM_CHANGED,
1326                NodeMessageKind::VisibilityChanged => Flags::VISIBILITY_CHANGED,
1327                NodeMessageKind::EnabledFlagChanged => Flags::ENABLED_FLAG_CHANGED,
1328            };
1329
1330            let visit_flags = &mut visited_flags[message.node.index() as usize];
1331
1332            if visit_flags.contains(message_flag) {
1333                continue;
1334            }
1335
1336            visit_flags.insert(message_flag);
1337
1338            roots
1339                .entry(message.node)
1340                .or_insert(Flags::NONE)
1341                .insert(message_flag);
1342
1343            // Mark the entire hierarchy as visited.
1344            fn traverse_recursive(
1345                graph: &Graph,
1346                from: Handle<Node>,
1347                func: &mut impl FnMut(Handle<Node>),
1348            ) {
1349                func(from);
1350                if let Ok(node) = graph.try_get_node(from) {
1351                    for &child in node.children() {
1352                        traverse_recursive(graph, child, func)
1353                    }
1354                }
1355            }
1356
1357            traverse_recursive(self, message.node, &mut |h| {
1358                visited_flags[h.index() as usize].insert(message_flag);
1359
1360                // Remove a descendant from the list of potential roots.
1361                if h != message.node {
1362                    if let Some(flags) = roots.get_mut(&h) {
1363                        flags.remove(message_flag);
1364
1365                        if flags.is_empty() {
1366                            roots.remove(&h);
1367                        }
1368                    }
1369                }
1370            })
1371        }
1372
1373        for (node, flags) in roots {
1374            if flags.contains(Flags::TRANSFORM_CHANGED) {
1375                Self::update_global_transform_recursively(
1376                    &self.pool,
1377                    &mut self.sound_context,
1378                    &mut self.physics,
1379                    &mut self.physics2d,
1380                    node,
1381                );
1382            }
1383            // All these calls could be combined into one with the above, but visibility/enabled
1384            // flags changes so rare, that it isn't worth spending CPU cycles on useless checks.
1385            if flags.contains(Flags::VISIBILITY_CHANGED) {
1386                Self::update_visibility_recursively(&self.pool, node);
1387            }
1388            if flags.contains(Flags::ENABLED_FLAG_CHANGED) {
1389                Self::update_enabled_flag_recursively(&self.pool, node)
1390            }
1391        }
1392    }
1393
1394    fn sync_native(&mut self, switches: &GraphUpdateSwitches) {
1395        let mut sync_context = SyncContext {
1396            nodes: &self.pool,
1397            physics: &mut self.physics,
1398            physics2d: &mut self.physics2d,
1399            sound_context: &mut self.sound_context,
1400            switches: Some(switches),
1401        };
1402
1403        for (handle, node) in self.pool.pair_iter() {
1404            node.sync_native(handle, &mut sync_context);
1405        }
1406    }
1407
1408    fn update_node(
1409        &mut self,
1410        handle: Handle<Node>,
1411        frame_size: Vector2<f32>,
1412        dt: f32,
1413        delete_dead_nodes: bool,
1414    ) {
1415        if let Ok((ticket, mut node)) = self.pool.try_take_reserve(handle) {
1416            let mut is_alive = node.is_alive();
1417
1418            if node.is_globally_enabled() {
1419                node.update(&mut UpdateContext {
1420                    frame_size,
1421                    dt,
1422                    nodes: &mut self.pool,
1423                    physics: &mut self.physics,
1424                    physics2d: &mut self.physics2d,
1425                    sound_context: &mut self.sound_context,
1426                });
1427
1428                if delete_dead_nodes {
1429                    if let Some(lifetime) = node.lifetime.get_value_mut_silent().as_mut() {
1430                        *lifetime -= dt;
1431                        if *lifetime <= 0.0 {
1432                            is_alive = false;
1433                        }
1434                    }
1435                }
1436            }
1437
1438            self.pool.put_back(ticket, node);
1439
1440            if !is_alive && delete_dead_nodes {
1441                self.remove_node(handle);
1442            }
1443        }
1444    }
1445
1446    /// Updates nodes in the graph using given delta time.
1447    ///
1448    /// # Update Switches
1449    ///
1450    /// Update switches allows you to disable update for parts of the update pipeline, it could be useful for editors
1451    /// where you need to have preview mode to update only specific set of nodes, etc.
1452    pub fn update(&mut self, frame_size: Vector2<f32>, dt: f32, switches: GraphUpdateSwitches) {
1453        self.sound_context.state().pause(switches.paused);
1454
1455        if switches.paused {
1456            return;
1457        }
1458
1459        let last_time = instant::Instant::now();
1460        self.process_node_messages(Some(&switches));
1461        self.performance_statistics.hierarchical_properties_time =
1462            instant::Instant::now() - last_time;
1463
1464        let last_time = instant::Instant::now();
1465        self.sync_native(&switches);
1466        self.performance_statistics.sync_time = instant::Instant::now() - last_time;
1467
1468        if switches.physics {
1469            self.physics.performance_statistics.reset();
1470            self.physics.update(dt, switches.physics_dt);
1471            self.performance_statistics.physics = self.physics.performance_statistics.clone();
1472        }
1473
1474        if switches.physics2d {
1475            self.physics2d.performance_statistics.reset();
1476            self.physics2d.update(dt, switches.physics_dt);
1477            self.performance_statistics.physics2d = self.physics2d.performance_statistics.clone();
1478        }
1479
1480        self.performance_statistics.sound_update_time =
1481            self.sound_context.state().full_render_duration();
1482
1483        if let Some(overrides) = switches.node_overrides.as_ref() {
1484            for handle in overrides {
1485                self.update_node(*handle, frame_size, dt, switches.delete_dead_nodes);
1486            }
1487        } else {
1488            for i in 0..self.pool.get_capacity() {
1489                self.update_node(
1490                    self.pool.handle_from_index(i),
1491                    frame_size,
1492                    dt,
1493                    switches.delete_dead_nodes,
1494                );
1495            }
1496        }
1497    }
1498
1499    /// Returns capacity of internal pool. Can be used to iterate over all **potentially**
1500    /// available indices and try to convert them to handles.
1501    ///
1502    /// ```
1503    /// # use fyrox_impl::scene::node::Node;
1504    /// # use fyrox_impl::scene::graph::Graph;
1505    /// # use fyrox_impl::scene::pivot::Pivot;
1506    /// # use fyrox_graph::SceneGraph;
1507    /// let mut graph = Graph::new();
1508    /// graph.add_node(Node::new(Pivot::default()));
1509    /// graph.add_node(Node::new(Pivot::default()));
1510    /// for i in 0..graph.capacity() {
1511    ///     let handle = graph.handle_from_index(i);
1512    ///     if handle.is_some() {
1513    ///         let node = &mut graph[handle];
1514    ///         // Do something with node.
1515    ///     }
1516    /// }
1517    /// ```
1518    #[inline]
1519    pub fn capacity(&self) -> u32 {
1520        self.pool.get_capacity()
1521    }
1522
1523    /// Makes new handle from given index. Handle will be none if index was either out-of-bounds
1524    /// or point to a vacant pool entry.
1525    ///
1526    /// ```
1527    /// # use fyrox_impl::scene::node::Node;
1528    /// # use fyrox_impl::scene::graph::Graph;
1529    /// # use fyrox_impl::scene::pivot::Pivot;
1530    /// # use fyrox_graph::SceneGraph;
1531    /// let mut graph = Graph::new();
1532    /// graph.add_node(Node::new(Pivot::default()));
1533    /// graph.add_node(Node::new(Pivot::default()));
1534    /// for i in 0..graph.capacity() {
1535    ///     let handle = graph.handle_from_index(i);
1536    ///     if handle.is_some() {
1537    ///         let node = &mut graph[handle];
1538    ///         // Do something with node.
1539    ///     }
1540    /// }
1541    /// ```
1542    #[inline]
1543    pub fn handle_from_index(&self, index: u32) -> Handle<Node> {
1544        self.pool.handle_from_index(index)
1545    }
1546
1547    /// Generates a set of handles that could be used to spawn a set of nodes.
1548    #[inline]
1549    pub fn generate_free_handles(&self, amount: usize) -> Vec<Handle<Node>> {
1550        self.pool.generate_free_handles(amount)
1551    }
1552
1553    /// Creates an iterator that has linear iteration order over internal collection
1554    /// of nodes. It does *not* perform any tree traversal!
1555    #[inline]
1556    pub fn linear_iter(&self) -> impl Iterator<Item = &Node> {
1557        self.pool.iter()
1558    }
1559
1560    /// Creates new iterator that iterates over internal collection giving (handle; node) pairs.
1561    #[inline]
1562    pub fn pair_iter_mut(&mut self) -> impl Iterator<Item = (Handle<Node>, &mut Node)> {
1563        self.pool.pair_iter_mut()
1564    }
1565
1566    /// Extracts node from graph and reserves its handle. It is used to temporarily take
1567    /// ownership over node, and then put node back using given ticket. Extracted node is
1568    /// detached from its parent!
1569    #[inline]
1570    pub fn take_reserve(&mut self, handle: Handle<Node>) -> (Ticket<Node>, Node) {
1571        self.isolate_node(handle);
1572        let (ticket, node) = self.take_reserve_internal(handle);
1573        self.instance_id_map.remove(&node.instance_id);
1574        (ticket, node)
1575    }
1576
1577    pub(crate) fn take_reserve_internal(&mut self, handle: Handle<Node>) -> (Ticket<Node>, Node) {
1578        let (ticket, mut node) = self.pool.take_reserve(handle);
1579        self.instance_id_map.remove(&node.instance_id);
1580        node.on_removed_from_graph(self);
1581        (ticket, node)
1582    }
1583
1584    /// Puts node back by given ticket. Attaches back to root node of graph.
1585    #[inline]
1586    pub fn put_back(&mut self, ticket: Ticket<Node>, node: Node) -> Handle<Node> {
1587        let handle = self.put_back_internal(ticket, node);
1588        self.link_nodes(handle, self.root);
1589        handle
1590    }
1591
1592    pub(crate) fn put_back_internal(&mut self, ticket: Ticket<Node>, node: Node) -> Handle<Node> {
1593        let instance_id = node.instance_id;
1594        let handle = self.pool.put_back(ticket, node);
1595        self.instance_id_map.insert(instance_id, handle);
1596        handle
1597    }
1598
1599    /// Makes node handle vacant again.
1600    #[inline]
1601    pub fn forget_ticket(&mut self, ticket: Ticket<Node>, node: Node) -> Node {
1602        self.pool.forget_ticket(ticket);
1603        node
1604    }
1605
1606    /// Extracts sub-graph starting from a given node. All handles to extracted nodes
1607    /// becomes reserved and will be marked as "occupied", an attempt to borrow a node
1608    /// at such handle will result in panic!. Please note that root node will be
1609    /// detached from its parent!
1610    #[inline]
1611    pub fn take_reserve_sub_graph(&mut self, root: Handle<Node>) -> SubGraph {
1612        // Take out descendants first.
1613        let mut descendants = Vec::new();
1614        let root_ref = &mut self[root];
1615        let mut stack = root_ref.children().to_vec();
1616        let parent = root_ref.parent;
1617        while let Some(handle) = stack.pop() {
1618            stack.extend_from_slice(self[handle].children());
1619            descendants.push(self.take_reserve_internal(handle));
1620        }
1621
1622        SubGraph {
1623            // Root must be extracted with detachment from its parent (if any).
1624            root: self.take_reserve(root),
1625            descendants,
1626            parent,
1627        }
1628    }
1629
1630    /// Puts previously extracted sub-graph into graph. Handles to nodes will become valid
1631    /// again. After that you probably want to re-link returned handle with its previous
1632    /// parent.
1633    #[inline]
1634    pub fn put_sub_graph_back(&mut self, sub_graph: SubGraph) -> Handle<Node> {
1635        for (ticket, node) in sub_graph.descendants {
1636            self.pool.put_back(ticket, node);
1637        }
1638
1639        let (ticket, node) = sub_graph.root;
1640        let root_handle = self.put_back(ticket, node);
1641
1642        self.link_nodes(root_handle, sub_graph.parent);
1643
1644        root_handle
1645    }
1646
1647    /// Forgets the entire sub-graph making handles to nodes invalid.
1648    #[inline]
1649    pub fn forget_sub_graph(&mut self, sub_graph: SubGraph) {
1650        for (ticket, _) in sub_graph.descendants {
1651            self.pool.forget_ticket(ticket);
1652        }
1653        let (ticket, _) = sub_graph.root;
1654        self.pool.forget_ticket(ticket);
1655    }
1656
1657    /// Returns the number of nodes in the graph.
1658    #[inline]
1659    pub fn node_count(&self) -> u32 {
1660        self.pool.alive_count()
1661    }
1662
1663    /// Creates deep copy of graph. Allows filtering while copying, returns copy and
1664    /// old-to-new node mapping.
1665    #[inline]
1666    pub fn clone_ex<F, Pre, Post>(
1667        &self,
1668        root: Handle<impl ObjectOrVariant<Node>>,
1669        preserve_handles: bool,
1670        filter: &mut F,
1671        pre_process_callback: &mut Pre,
1672        post_process_callback: &mut Post,
1673    ) -> (Self, NodeHandleMap<Node>)
1674    where
1675        F: FnMut(Handle<Node>, &Node) -> bool,
1676        Pre: FnMut(Handle<Node>, &mut Node),
1677        Post: FnMut(Handle<Node>, Handle<Node>, &mut Node),
1678    {
1679        let root = root.to_base();
1680
1681        let mut copy = Self {
1682            sound_context: self.sound_context.deep_clone(),
1683            physics: self.physics.clone(),
1684            physics2d: self.physics2d.clone(),
1685            user_data: self.user_data.clone(),
1686            ..Default::default()
1687        };
1688
1689        let (copy_root, old_new_map) = self.copy_node(
1690            root,
1691            &mut copy,
1692            preserve_handles,
1693            filter,
1694            pre_process_callback,
1695            post_process_callback,
1696        );
1697        assert_eq!(copy.root, copy_root);
1698
1699        let mut lightmap = self.lightmap.clone();
1700        if let Some(lightmap) = lightmap.as_mut() {
1701            let mut map = FxHashMap::default();
1702            for (mut handle, mut entries) in std::mem::take(&mut lightmap.map) {
1703                for entry in entries.iter_mut() {
1704                    for light_handle in entry.lights.iter_mut() {
1705                        old_new_map.try_map(light_handle);
1706                    }
1707                }
1708
1709                if old_new_map.try_map(&mut handle) {
1710                    map.insert(handle, entries);
1711                }
1712            }
1713            lightmap.map = map;
1714        }
1715        copy.lightmap = lightmap;
1716
1717        if let Some(user_data) = copy.user_data.0.as_mut() {
1718            old_new_map.remap_handles_any(
1719                user_data,
1720                "UserData",
1721                &[TypeId::of::<UntypedResource>()],
1722            );
1723        }
1724
1725        (copy, old_new_map)
1726    }
1727
1728    /// Returns local transformation matrix of a node without scale.
1729    #[inline]
1730    pub fn local_transform_no_scale(
1731        &self,
1732        node: Handle<impl ObjectOrVariant<Node>>,
1733    ) -> Matrix4<f32> {
1734        let mut transform = self[node.to_base()].local_transform().clone();
1735        transform.set_scale(Vector3::new(1.0, 1.0, 1.0));
1736        transform.matrix()
1737    }
1738
1739    /// Returns world transformation matrix of a node without scale.
1740    #[inline]
1741    pub fn global_transform_no_scale(
1742        &self,
1743        node: Handle<impl ObjectOrVariant<Node>>,
1744    ) -> Matrix4<f32> {
1745        let node = node.to_base();
1746        let parent = self[node].parent();
1747        if parent.is_some() {
1748            self.global_transform_no_scale(parent) * self.local_transform_no_scale(node)
1749        } else {
1750            self.local_transform_no_scale(node)
1751        }
1752    }
1753
1754    /// Returns isometric local transformation matrix of a node. Such transform has
1755    /// only translation and rotation.
1756    #[inline]
1757    pub fn isometric_local_transform(
1758        &self,
1759        node: Handle<impl ObjectOrVariant<Node>>,
1760    ) -> Matrix4<f32> {
1761        isometric_local_transform(&self.pool, node)
1762    }
1763
1764    /// Returns world transformation matrix of a node only.  Such transform has
1765    /// only translation and rotation.
1766    #[inline]
1767    pub fn isometric_global_transform(
1768        &self,
1769        node: Handle<impl ObjectOrVariant<Node>>,
1770    ) -> Matrix4<f32> {
1771        isometric_global_transform(&self.pool, node)
1772    }
1773
1774    /// Returns global scale matrix of a node.
1775    #[inline]
1776    pub fn global_scale_matrix(&self, node: Handle<impl ObjectOrVariant<Node>>) -> Matrix4<f32> {
1777        Matrix4::new_nonuniform_scaling(&self.global_scale(node))
1778    }
1779
1780    /// Returns rotation quaternion of a node in world coordinates.
1781    #[inline]
1782    pub fn global_rotation(&self, node: Handle<impl ObjectOrVariant<Node>>) -> UnitQuaternion<f32> {
1783        UnitQuaternion::from(Rotation3::from_matrix_eps(
1784            &self.global_transform_no_scale(node).basis(),
1785            f32::EPSILON,
1786            16,
1787            Rotation3::identity(),
1788        ))
1789    }
1790
1791    /// Returns rotation quaternion of a node in world coordinates without pre- and post-rotations.
1792    #[inline]
1793    pub fn isometric_global_rotation(
1794        &self,
1795        node: Handle<impl ObjectOrVariant<Node>>,
1796    ) -> UnitQuaternion<f32> {
1797        UnitQuaternion::from(Rotation3::from_matrix_eps(
1798            &self.isometric_global_transform(node).basis(),
1799            f32::EPSILON,
1800            16,
1801            Rotation3::identity(),
1802        ))
1803    }
1804
1805    /// Returns rotation quaternion and position of a node in world coordinates, scale is eliminated.
1806    #[inline]
1807    pub fn global_rotation_position_no_scale(
1808        &self,
1809        node: Handle<impl ObjectOrVariant<Node>>,
1810    ) -> (UnitQuaternion<f32>, Vector3<f32>) {
1811        let node = node.to_base();
1812        (self.global_rotation(node), self[node].global_position())
1813    }
1814
1815    /// Returns isometric global rotation and position.
1816    #[inline]
1817    pub fn isometric_global_rotation_position(
1818        &self,
1819        node: Handle<impl ObjectOrVariant<Node>>,
1820    ) -> (UnitQuaternion<f32>, Vector3<f32>) {
1821        let node = node.to_base();
1822        (
1823            self.isometric_global_rotation(node),
1824            self[node].global_position(),
1825        )
1826    }
1827
1828    /// Returns global scale of a node.
1829    #[inline]
1830    pub fn global_scale(&self, handle: Handle<impl ObjectOrVariant<Node>>) -> Vector3<f32> {
1831        let mut handle = handle.to_base();
1832        let mut global_scale = Vector3::repeat(1.0);
1833        while let Ok(node_ref) = self.try_get_node(handle) {
1834            global_scale = global_scale.component_mul(node_ref.local_transform().scale());
1835            handle = node_ref.parent;
1836        }
1837        global_scale
1838    }
1839
1840    /// Tries to borrow a node using the given handle and searches the script buffer for a script
1841    /// of type T and cast the first script, that could be found to the specified type.
1842    #[inline]
1843    pub fn try_get_script_of<T>(
1844        &self,
1845        handle: Handle<impl ObjectOrVariant<Node>>,
1846    ) -> Result<&T, GraphError>
1847    where
1848        T: ScriptTrait,
1849    {
1850        let handle = handle.to_base();
1851        let node = self.try_get_node(handle)?;
1852        node.try_get_script::<T>()
1853            .ok_or_else(|| GraphError::NoScript {
1854                handle,
1855                script_type_name: std::any::type_name::<T>(),
1856            })
1857    }
1858
1859    /// Tries to borrow a node and query all scripts of the given type `T`. This method returns
1860    /// [`None`] if the given node handle is invalid, otherwise it returns an iterator over the
1861    /// scripts of the type `T`.
1862    #[inline]
1863    pub fn try_get_scripts_of<T: ScriptTrait>(
1864        &self,
1865        handle: Handle<impl ObjectOrVariant<Node>>,
1866    ) -> Result<impl Iterator<Item = &T>, GraphError> {
1867        let handle = handle.to_base();
1868        let node = self.try_get_node(handle)?;
1869        Ok(node.try_get_scripts())
1870    }
1871
1872    /// Tries to borrow a node using the given handle and searches the script buffer for a script
1873    /// of type T and cast the first script, that could be found to the specified type.
1874    #[inline]
1875    pub fn try_get_script_of_mut<T>(
1876        &mut self,
1877        handle: Handle<impl ObjectOrVariant<Node>>,
1878    ) -> Result<&mut T, GraphError>
1879    where
1880        T: ScriptTrait,
1881    {
1882        let handle = handle.to_base();
1883        let node = self.try_get_node_mut(handle)?;
1884        node.try_get_script_mut::<T>()
1885            .ok_or_else(|| GraphError::NoScript {
1886                handle,
1887                script_type_name: std::any::type_name::<T>(),
1888            })
1889    }
1890
1891    /// Tries to borrow a node and query all scripts of the given type `T`. This method returns
1892    /// [`None`] if the given node handle is invalid, otherwise it returns an iterator over the
1893    /// scripts of the type `T`.
1894    #[inline]
1895    pub fn try_get_scripts_of_mut<T>(
1896        &mut self,
1897        handle: Handle<impl ObjectOrVariant<Node>>,
1898    ) -> Result<impl Iterator<Item = &mut T>, GraphError>
1899    where
1900        T: ScriptTrait,
1901    {
1902        let handle = handle.to_base();
1903        let node = self.try_get_node_mut(handle)?;
1904        Ok(node.try_get_scripts_mut())
1905    }
1906
1907    /// Tries to borrow a node and find a component of the given type `C` across **all** available
1908    /// scripts of the node. If you want to search a component `C` in a particular script, then use
1909    /// [`Self::try_get_script_of`] and then search for component in it.
1910    #[inline]
1911    pub fn try_get_script_component_of<C>(
1912        &self,
1913        handle: Handle<impl ObjectOrVariant<Node>>,
1914    ) -> Result<&C, GraphError>
1915    where
1916        C: Any,
1917    {
1918        let handle = handle.to_base();
1919        let node = self.try_get_node(handle)?;
1920        node.try_get_script_component()
1921            .ok_or_else(|| GraphError::NoScriptComponent {
1922                handle,
1923                component_type_name: std::any::type_name::<C>(),
1924            })
1925    }
1926
1927    /// Tries to borrow a node and find a component of the given type `C` across **all** available
1928    /// scripts of the node. If you want to search a component `C` in a particular script, then use
1929    /// [`Self::try_get_script_of_mut`] and then search for component in it.
1930    #[inline]
1931    pub fn try_get_script_component_of_mut<C>(
1932        &mut self,
1933        handle: Handle<impl ObjectOrVariant<Node>>,
1934    ) -> Result<&mut C, GraphError>
1935    where
1936        C: Any,
1937    {
1938        let handle = handle.to_base();
1939        let node = self.try_get_node_mut(handle)?;
1940        node.try_get_script_component_mut()
1941            .ok_or_else(|| GraphError::NoScriptComponent {
1942                handle,
1943                component_type_name: std::any::type_name::<C>(),
1944            })
1945    }
1946
1947    /// Returns a handle of the node that has the given id.
1948    pub fn id_to_node_handle(&self, id: SceneNodeId) -> Option<&Handle<Node>> {
1949        self.instance_id_map.get(&id)
1950    }
1951
1952    /// Tries to borrow a node by its id.
1953    pub fn node_by_id(&self, id: SceneNodeId) -> Result<(Handle<Node>, &Node), GraphError> {
1954        self.instance_id_map
1955            .get(&id)
1956            .ok_or(GraphError::UnknownId(id))
1957            .and_then(|h| Ok(self.pool.try_borrow(*h).map(|n| (*h, n))?))
1958    }
1959
1960    /// Tries to borrow a node by its id.
1961    pub fn node_by_id_mut(
1962        &mut self,
1963        id: SceneNodeId,
1964    ) -> Result<(Handle<Node>, &mut Node), GraphError> {
1965        self.instance_id_map
1966            .get(&id)
1967            .ok_or(GraphError::UnknownId(id))
1968            .and_then(|h| Ok(self.pool.try_borrow_mut(*h).map(|n| (*h, n))?))
1969    }
1970}
1971
1972impl<T: ObjectOrVariant<Node>> Index<Handle<T>> for Graph {
1973    type Output = T;
1974
1975    #[inline]
1976    fn index(&self, index: Handle<T>) -> &Self::Output {
1977        self.try_get(index).unwrap()
1978    }
1979}
1980
1981impl<T: ObjectOrVariant<Node>> IndexMut<Handle<T>> for Graph {
1982    #[inline]
1983    fn index_mut(&mut self, index: Handle<T>) -> &mut Self::Output {
1984        self.try_get_mut(index).unwrap()
1985    }
1986}
1987
1988impl Visit for Graph {
1989    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1990        // Pool must be empty, otherwise handles will be invalid and everything will blow up.
1991        if visitor.is_reading() && self.pool.get_capacity() != 0 {
1992            panic!("Graph pool must be empty on load!")
1993        }
1994
1995        let mut region = visitor.enter_region(name)?;
1996
1997        self.root.visit("Root", &mut region)?;
1998        self.pool.visit("Pool", &mut region)?;
1999        self.sound_context.visit("SoundContext", &mut region)?;
2000        self.physics.visit("PhysicsWorld", &mut region)?;
2001        self.physics2d.visit("PhysicsWorld2D", &mut region)?;
2002        self.lightmap.visit("Lightmap", &mut region)?;
2003
2004        Log::verify(self.user_data.visit("UserData", &mut region));
2005
2006        Ok(())
2007    }
2008}
2009
2010impl SceneGraph for Graph {
2011    type Prefab = Model;
2012    type NodeContainer = NodeContainer;
2013    type Node = Node;
2014
2015    /// Create a brief debug summary of the contents of this graph.
2016    fn summary(&self) -> String {
2017        let mut result = String::new();
2018        self.recursive_summary(0, self.root, &mut result);
2019        result
2020    }
2021
2022    #[inline]
2023    fn actual_type_id(&self, handle: Handle<Self::Node>) -> Result<TypeId, PoolError> {
2024        self.pool
2025            .try_borrow(handle)
2026            .map(|n| NodeAsAny::as_any(n.0.deref()).type_id())
2027    }
2028
2029    #[inline]
2030    fn root(&self) -> Handle<Self::Node> {
2031        self.root
2032    }
2033
2034    #[inline]
2035    fn set_root(&mut self, root: Handle<Self::Node>) {
2036        self.root = root;
2037    }
2038
2039    #[inline]
2040    fn is_valid_handle(&self, handle: Handle<impl ObjectOrVariant<Self::Node>>) -> bool {
2041        self.pool.is_valid_handle(handle)
2042    }
2043
2044    #[inline]
2045    fn add_node(&mut self, node: Self::Node) -> Handle<Self::Node> {
2046        let handle = self.pool.next_free_handle();
2047        self.add_node_at_handle(node, handle);
2048        handle
2049    }
2050
2051    fn add_node_at_handle(&mut self, mut node: Self::Node, handle: Handle<Self::Node>) {
2052        let children = node.children.clone();
2053        node.children.clear();
2054        let script_count = node.scripts.len();
2055        self.pool
2056            .spawn_at_handle(handle, node)
2057            .expect("The handle must be valid!");
2058
2059        if self.root.is_none() {
2060            self.root = handle;
2061        } else {
2062            self.link_nodes(handle, self.root);
2063        }
2064
2065        for child in children {
2066            self.link_nodes(child, handle);
2067        }
2068
2069        self.event_broadcaster.broadcast(GraphEvent::Added(handle));
2070        for i in 0..script_count {
2071            self.script_message_sender
2072                .send(NodeScriptMessage::InitializeScript {
2073                    handle,
2074                    script_index: i,
2075                })
2076                .unwrap();
2077        }
2078
2079        let script_message_sender = self.script_message_sender.clone();
2080        let message_sender = self.message_sender.clone();
2081        let node = &mut self.pool[handle];
2082        node.on_connected_to_graph(handle, message_sender, script_message_sender);
2083
2084        self.instance_id_map.insert(node.instance_id, handle);
2085    }
2086
2087    #[inline]
2088    fn remove_node(&mut self, node_handle: Handle<impl ObjectOrVariant<Self::Node>>) {
2089        let node_handle = node_handle.to_base();
2090
2091        self.isolate_node(node_handle);
2092
2093        self.stack.clear();
2094        self.stack.push(node_handle);
2095        while let Some(handle) = self.stack.pop() {
2096            for &child in self.pool[handle].children().iter() {
2097                self.stack.push(child);
2098            }
2099
2100            // Remove associated entities.
2101            let mut node = self.pool.free(handle);
2102            self.instance_id_map.remove(&node.instance_id);
2103            node.on_removed_from_graph(self);
2104
2105            self.event_broadcaster
2106                .broadcast(GraphEvent::Removed(handle));
2107        }
2108    }
2109
2110    #[inline]
2111    fn link_nodes(
2112        &mut self,
2113        child: Handle<impl ObjectOrVariant<Self::Node>>,
2114        parent: Handle<impl ObjectOrVariant<Self::Node>>,
2115    ) {
2116        let child = child.to_base();
2117        let parent = parent.to_base();
2118
2119        self.isolate_node(child);
2120        self.pool[child].parent = parent;
2121        self.pool[parent].children.push(child);
2122
2123        // Force update of global transform of the node being attached.
2124        self.message_sender
2125            .send(NodeMessage::new(child, NodeMessageKind::TransformChanged))
2126            .unwrap();
2127    }
2128
2129    #[inline]
2130    fn unlink_node(&mut self, node_handle: Handle<impl ObjectOrVariant<Self::Node>>) {
2131        let node_handle = node_handle.to_base();
2132        self.isolate_node(node_handle);
2133        self.link_nodes(node_handle, self.root);
2134        self.pool[node_handle]
2135            .local_transform_mut()
2136            .set_position(Vector3::default());
2137    }
2138
2139    #[inline]
2140    fn isolate_node(&mut self, node_handle: Handle<impl ObjectOrVariant<Self::Node>>) {
2141        let node_handle = node_handle.to_base();
2142        // Replace parent handle of child
2143        let parent_handle = std::mem::replace(&mut self.pool[node_handle].parent, Handle::NONE);
2144
2145        // Remove child from parent's children list
2146        if let Ok(parent) = self.pool.try_borrow_mut(parent_handle) {
2147            if let Some(i) = parent.children().iter().position(|h| *h == node_handle) {
2148                parent.children.remove(i);
2149            }
2150        }
2151
2152        let (ticket, mut node) = self.pool.take_reserve(node_handle);
2153        node.on_unlink(self);
2154        self.pool.put_back(ticket, node);
2155    }
2156
2157    #[inline]
2158    fn try_get_node(&self, handle: Handle<Self::Node>) -> Result<&Self::Node, PoolError> {
2159        self.pool.try_borrow(handle)
2160    }
2161
2162    #[inline]
2163    fn try_get_node_mut(
2164        &mut self,
2165        handle: Handle<Self::Node>,
2166    ) -> Result<&mut Self::Node, PoolError> {
2167        self.pool.try_borrow_mut(handle)
2168    }
2169
2170    fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Result<Vec<TypeId>, PoolError> {
2171        self.pool
2172            .try_borrow(handle)
2173            .map(|n| Box::deref(&n.0).query_derived_types().to_vec())
2174    }
2175
2176    fn actual_type_name(&self, handle: Handle<Self::Node>) -> Result<&'static str, PoolError> {
2177        self.pool
2178            .try_borrow(handle)
2179            .map(|n| n.0.deref().type_name())
2180    }
2181
2182    #[inline]
2183    fn pair_iter(&self) -> impl Iterator<Item = (Handle<Self::Node>, &Self::Node)> {
2184        self.pool.pair_iter()
2185    }
2186
2187    #[inline]
2188    fn linear_iter(&self) -> impl Iterator<Item = &Self::Node> {
2189        self.pool.iter()
2190    }
2191
2192    #[inline]
2193    fn linear_iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Node> {
2194        self.pool.iter_mut()
2195    }
2196
2197    fn try_get<U: ObjectOrVariant<Node>>(&self, handle: Handle<U>) -> Result<&U, PoolError> {
2198        self.pool.try_get(handle)
2199    }
2200
2201    fn try_get_mut<U: ObjectOrVariant<Node>>(
2202        &mut self,
2203        handle: Handle<U>,
2204    ) -> Result<&mut U, PoolError> {
2205        self.pool.try_get_mut(handle)
2206    }
2207}
2208
2209#[cfg(test)]
2210mod test {
2211    use crate::scene::rigidbody::{RigidBody, RigidBodyBuilder};
2212    use crate::{
2213        asset::{io::FsResourceIo, manager::ResourceManager},
2214        core::{
2215            algebra::{Matrix4, Vector3},
2216            futures::executor::block_on,
2217            pool::Handle,
2218            reflect::prelude::*,
2219            type_traits::prelude::*,
2220            visitor::prelude::*,
2221        },
2222        engine::{self, SerializationContext},
2223        graph::SceneGraph,
2224        resource::model::{Model, ModelResourceExtension},
2225        scene::{
2226            base::BaseBuilder,
2227            graph::Graph,
2228            mesh::{
2229                surface::{SurfaceBuilder, SurfaceData, SurfaceResource},
2230                MeshBuilder,
2231            },
2232            node::Node,
2233            pivot::{Pivot, PivotBuilder},
2234            transform::TransformBuilder,
2235            Scene, SceneLoader,
2236        },
2237        script::ScriptTrait,
2238    };
2239    use fyrox_core::algebra::Vector2;
2240    use fyrox_resource::untyped::ResourceKind;
2241    use std::{fs, path::Path, sync::Arc};
2242
2243    #[derive(Clone, Debug, PartialEq, Reflect, Visit, TypeUuidProvider, ComponentProvider)]
2244    #[type_uuid(id = "722feb80-a10b-4ee0-8cef-5d1473df8457")]
2245    struct MyScript {
2246        foo: String,
2247        bar: f32,
2248    }
2249
2250    impl ScriptTrait for MyScript {}
2251
2252    #[derive(Clone, Debug, PartialEq, Reflect, Visit, TypeUuidProvider, ComponentProvider)]
2253    #[type_uuid(id = "722feb80-a10b-4ee0-8cef-5d1473df8458")]
2254    struct MyOtherScript {
2255        baz: u32,
2256        foobar: Vec<u32>,
2257    }
2258
2259    impl ScriptTrait for MyOtherScript {}
2260
2261    #[test]
2262    fn test_graph_scripts() {
2263        let node = PivotBuilder::new(
2264            BaseBuilder::new()
2265                .with_script(MyScript {
2266                    foo: "Stuff".to_string(),
2267                    bar: 123.321,
2268                })
2269                .with_script(MyScript {
2270                    foo: "OtherStuff".to_string(),
2271                    bar: 321.123,
2272                })
2273                .with_script(MyOtherScript {
2274                    baz: 321,
2275                    foobar: vec![1, 2, 3],
2276                }),
2277        )
2278        .build_node();
2279
2280        let mut graph = Graph::new();
2281
2282        let handle = graph.add_node(node);
2283
2284        assert_eq!(
2285            graph.try_get_script_of::<MyScript>(handle),
2286            Ok(&MyScript {
2287                foo: "Stuff".to_string(),
2288                bar: 123.321,
2289            })
2290        );
2291        assert_eq!(
2292            graph.try_get_script_of_mut::<MyScript>(handle),
2293            Ok(&mut MyScript {
2294                foo: "Stuff".to_string(),
2295                bar: 123.321,
2296            })
2297        );
2298
2299        let mut immutable_iterator = graph
2300            .try_get_scripts_of::<MyScript>(handle)
2301            .expect("The handle expected to be valid!");
2302        assert_eq!(
2303            immutable_iterator.next(),
2304            Some(&MyScript {
2305                foo: "Stuff".to_string(),
2306                bar: 123.321,
2307            })
2308        );
2309        assert_eq!(
2310            immutable_iterator.next(),
2311            Some(&MyScript {
2312                foo: "OtherStuff".to_string(),
2313                bar: 321.123,
2314            })
2315        );
2316        drop(immutable_iterator);
2317
2318        assert_eq!(
2319            graph.try_get_script_of::<MyOtherScript>(handle),
2320            Ok(&MyOtherScript {
2321                baz: 321,
2322                foobar: vec![1, 2, 3],
2323            })
2324        );
2325        assert_eq!(
2326            graph.try_get_script_of_mut::<MyOtherScript>(handle),
2327            Ok(&mut MyOtherScript {
2328                baz: 321,
2329                foobar: vec![1, 2, 3],
2330            })
2331        );
2332
2333        let mut mutable_iterator = graph
2334            .try_get_scripts_of_mut::<MyScript>(handle)
2335            .expect("The handle expected to be valid!");
2336        assert_eq!(
2337            mutable_iterator.next(),
2338            Some(&mut MyScript {
2339                foo: "Stuff".to_string(),
2340                bar: 123.321,
2341            })
2342        );
2343        assert_eq!(
2344            mutable_iterator.next(),
2345            Some(&mut MyScript {
2346                foo: "OtherStuff".to_string(),
2347                bar: 321.123,
2348            })
2349        );
2350    }
2351
2352    #[test]
2353    fn graph_init_test() {
2354        let graph = Graph::new();
2355        assert_ne!(graph.root, Handle::<Node>::NONE);
2356        assert_eq!(graph.pool.alive_count(), 1);
2357    }
2358
2359    #[test]
2360    fn graph_node_test() {
2361        let mut graph = Graph::new();
2362        graph.add_node(Node::new(Pivot::default()));
2363        graph.add_node(Node::new(Pivot::default()));
2364        graph.add_node(Node::new(Pivot::default()));
2365        assert_eq!(graph.pool.alive_count(), 4);
2366    }
2367
2368    #[test]
2369    fn test_graph_search() {
2370        let mut graph = Graph::new();
2371
2372        // Root_
2373        //      |_A_
2374        //          |_B
2375        //          |_C_
2376        //             |_D
2377        let b;
2378        let c;
2379        let d;
2380        let a = PivotBuilder::new(
2381            BaseBuilder::new()
2382                .with_name("A")
2383                .with_child({
2384                    b = PivotBuilder::new(BaseBuilder::new().with_name("B")).build(&mut graph);
2385                    b
2386                })
2387                .with_child({
2388                    c = PivotBuilder::new(BaseBuilder::new().with_name("C").with_child({
2389                        d = PivotBuilder::new(BaseBuilder::new().with_name("D")).build(&mut graph);
2390                        d
2391                    }))
2392                    .build(&mut graph);
2393                    c
2394                }),
2395        )
2396        .build(&mut graph);
2397
2398        // Test down search.
2399        assert!(graph.find_by_name(a, "X").is_none());
2400        assert_eq!(graph.find_by_name(a, "A").unwrap().0, a);
2401        assert_eq!(graph.find_by_name(a, "D").unwrap().0, d);
2402
2403        let result = graph
2404            .find_map(a, &mut |n| if n.name() == "D" { Some("D") } else { None })
2405            .unwrap();
2406        assert_eq!(result.0, d);
2407        assert_eq!(result.1, "D");
2408
2409        // Test up search.
2410        assert!(graph.find_up_by_name(d, "X").is_none());
2411        assert_eq!(graph.find_up_by_name(d, "D").unwrap().0, d);
2412        assert_eq!(graph.find_up_by_name(d, "A").unwrap().0, a);
2413
2414        let result = graph
2415            .find_up_map(d, &mut |n| if n.name() == "A" { Some("A") } else { None })
2416            .unwrap();
2417        assert_eq!(result.0, a);
2418        assert_eq!(result.1, "A");
2419    }
2420
2421    fn create_scene() -> Scene {
2422        let mut scene = Scene::new();
2423
2424        PivotBuilder::new(BaseBuilder::new().with_name("Pivot")).build(&mut scene.graph);
2425
2426        PivotBuilder::new(BaseBuilder::new().with_name("MeshPivot").with_child({
2427            MeshBuilder::new(
2428                BaseBuilder::new().with_name("Mesh").with_local_transform(
2429                    TransformBuilder::new()
2430                        .with_local_position(Vector3::new(3.0, 2.0, 1.0))
2431                        .build(),
2432                ),
2433            )
2434            .with_surfaces(vec![SurfaceBuilder::new(SurfaceResource::new_ok(
2435                Uuid::new_v4(),
2436                ResourceKind::Embedded,
2437                SurfaceData::make_cone(16, 1.0, 1.0, &Matrix4::identity()),
2438            ))
2439            .build()])
2440            .build(&mut scene.graph)
2441        }))
2442        .build(&mut scene.graph);
2443
2444        scene
2445    }
2446
2447    fn save_scene(scene: &mut Scene, path: &Path) {
2448        let mut visitor = Visitor::new();
2449        scene.save("Scene", &mut visitor).unwrap();
2450        visitor.save_ascii_to_file(path).unwrap();
2451    }
2452
2453    fn make_resource_manager(root: &Path) -> ResourceManager {
2454        let resource_manager =
2455            ResourceManager::new(Arc::new(FsResourceIo), Arc::new(Default::default()));
2456        resource_manager
2457            .state()
2458            .resource_registry
2459            .lock()
2460            .set_path(root.join("resources.registry"));
2461        engine::initialize_resource_manager_loaders(
2462            &resource_manager,
2463            Arc::new(SerializationContext::new()),
2464            Default::default(),
2465            Default::default(),
2466        );
2467        resource_manager.update_or_load_registry();
2468        resource_manager
2469    }
2470
2471    #[test]
2472    fn test_restore_integrity() {
2473        let root = Path::new("test_restore_integrity");
2474
2475        if !root.exists() {
2476            fs::create_dir_all(root).unwrap();
2477        }
2478
2479        let root_asset_path = root.join("root2.rgs");
2480        let derived_asset_path = root.join("derived2.rgs");
2481
2482        // Create root scene and save it.
2483        {
2484            let mut scene = create_scene();
2485            save_scene(&mut scene, &root_asset_path);
2486        }
2487
2488        // Create root resource instance in a derived resource. This creates a derived asset.
2489        {
2490            let resource_manager = make_resource_manager(root);
2491            let root_asset = block_on(resource_manager.request::<Model>(&root_asset_path)).unwrap();
2492
2493            let mut derived = Scene::new();
2494            root_asset.instantiate(&mut derived);
2495            save_scene(&mut derived, &derived_asset_path);
2496        }
2497
2498        // Now load the root asset, modify it, save it back and reload the derived asset.
2499        {
2500            let resource_manager = make_resource_manager(root);
2501            let mut scene = block_on(
2502                block_on(SceneLoader::from_file(
2503                    &root_asset_path,
2504                    &FsResourceIo,
2505                    Arc::new(SerializationContext::new()),
2506                    Default::default(),
2507                    resource_manager.clone(),
2508                ))
2509                .unwrap()
2510                .0
2511                .finish(),
2512            );
2513
2514            // Add a new node to the root node of the scene.
2515            PivotBuilder::new(BaseBuilder::new().with_name("AddedLater")).build(&mut scene.graph);
2516
2517            // Add a new node to the mesh.
2518            let mesh = scene.graph.find_by_name_from_root("Mesh").unwrap().0;
2519            let pivot = PivotBuilder::new(BaseBuilder::new().with_name("NewChildOfMesh"))
2520                .build(&mut scene.graph);
2521            scene.graph.link_nodes(pivot, mesh);
2522
2523            // Remove existing nodes.
2524            let existing_pivot = scene.graph.find_by_name_from_root("Pivot").unwrap().0;
2525            scene.graph.remove_node(existing_pivot);
2526
2527            // Save the scene back.
2528            save_scene(&mut scene, &root_asset_path);
2529        }
2530
2531        // Load the derived scene and check if its content was synced with the content of the root asset.
2532        {
2533            let resource_manager = make_resource_manager(root);
2534            let derived_asset =
2535                block_on(resource_manager.request::<Model>(derived_asset_path)).unwrap();
2536
2537            let derived_data = derived_asset.data_ref();
2538            let derived_scene = derived_data.get_scene();
2539
2540            // Pivot must also be removed from the derived asset, because it is deleted in the root asset.
2541            assert_eq!(
2542                derived_scene
2543                    .graph
2544                    .find_by_name_from_root("Pivot")
2545                    .map(|(h, _)| h),
2546                None
2547            );
2548
2549            let mesh_pivot = derived_scene
2550                .graph
2551                .find_by_name_from_root("MeshPivot")
2552                .expect("Missing MeshPivot")
2553                .0;
2554            let mesh = derived_scene
2555                .graph
2556                .find_by_name(mesh_pivot, "Mesh")
2557                .expect("Missing Mesh")
2558                .0;
2559            derived_scene
2560                .graph
2561                .find_by_name_from_root("AddedLater")
2562                .expect("Missing AddedLater");
2563            derived_scene
2564                .graph
2565                .find_by_name(mesh, "NewChildOfMesh")
2566                .expect("Missing NewChildOfMesh");
2567        }
2568    }
2569
2570    #[test]
2571    fn test_global_scale() {
2572        let mut graph = Graph::new();
2573
2574        let b;
2575        let c;
2576        let a = PivotBuilder::new(
2577            BaseBuilder::new()
2578                .with_local_transform(
2579                    TransformBuilder::new()
2580                        .with_local_scale(Vector3::new(1.0, 1.0, 2.0))
2581                        .build(),
2582                )
2583                .with_child({
2584                    b = PivotBuilder::new(
2585                        BaseBuilder::new()
2586                            .with_local_transform(
2587                                TransformBuilder::new()
2588                                    .with_local_scale(Vector3::new(3.0, 2.0, 1.0))
2589                                    .build(),
2590                            )
2591                            .with_child({
2592                                c = PivotBuilder::new(
2593                                    BaseBuilder::new().with_local_transform(
2594                                        TransformBuilder::new()
2595                                            .with_local_scale(Vector3::new(1.0, 2.0, 3.0))
2596                                            .build(),
2597                                    ),
2598                                )
2599                                .build(&mut graph);
2600                                c
2601                            }),
2602                    )
2603                    .build(&mut graph);
2604                    b
2605                }),
2606        )
2607        .build(&mut graph);
2608
2609        assert_eq!(graph.global_scale(a), Vector3::new(1.0, 1.0, 2.0));
2610        assert_eq!(graph.global_scale(b), Vector3::new(3.0, 2.0, 2.0));
2611        assert_eq!(graph.global_scale(c), Vector3::new(3.0, 4.0, 6.0));
2612    }
2613
2614    #[test]
2615    fn test_hierarchy_changes_propagation() {
2616        let mut graph = Graph::new();
2617
2618        let b;
2619        let c;
2620        let d;
2621        let a = PivotBuilder::new(
2622            BaseBuilder::new()
2623                .with_local_transform(
2624                    TransformBuilder::new()
2625                        .with_local_position(Vector3::new(1.0, 0.0, 0.0))
2626                        .build(),
2627                )
2628                .with_child({
2629                    b = PivotBuilder::new(
2630                        BaseBuilder::new()
2631                            .with_visibility(false)
2632                            .with_enabled(false)
2633                            .with_local_transform(
2634                                TransformBuilder::new()
2635                                    .with_local_position(Vector3::new(0.0, 1.0, 0.0))
2636                                    .build(),
2637                            )
2638                            .with_child({
2639                                c = PivotBuilder::new(
2640                                    BaseBuilder::new().with_local_transform(
2641                                        TransformBuilder::new()
2642                                            .with_local_position(Vector3::new(0.0, 0.0, 1.0))
2643                                            .build(),
2644                                    ),
2645                                )
2646                                .build(&mut graph);
2647                                c
2648                            }),
2649                    )
2650                    .build(&mut graph);
2651                    b
2652                })
2653                .with_child({
2654                    d = PivotBuilder::new(
2655                        BaseBuilder::new().with_local_transform(
2656                            TransformBuilder::new()
2657                                .with_local_position(Vector3::new(1.0, 1.0, 1.0))
2658                                .build(),
2659                        ),
2660                    )
2661                    .build(&mut graph);
2662                    d
2663                }),
2664        )
2665        .build(&mut graph);
2666
2667        graph.update(Vector2::new(1.0, 1.0), 1.0 / 60.0, Default::default());
2668
2669        assert_eq!(graph[a].global_position(), Vector3::new(1.0, 0.0, 0.0));
2670        assert_eq!(graph[b].global_position(), Vector3::new(1.0, 1.0, 0.0));
2671        assert_eq!(graph[c].global_position(), Vector3::new(1.0, 1.0, 1.0));
2672        assert_eq!(graph[d].global_position(), Vector3::new(2.0, 1.0, 1.0));
2673
2674        assert!(graph[a].global_visibility());
2675        assert!(!graph[b].global_visibility());
2676        assert!(!graph[c].global_visibility());
2677        assert!(graph[d].global_visibility());
2678
2679        assert!(graph[a].is_globally_enabled());
2680        assert!(!graph[b].is_globally_enabled());
2681        assert!(!graph[c].is_globally_enabled());
2682        assert!(graph[d].is_globally_enabled());
2683
2684        // Change something
2685        graph[b]
2686            .local_transform_mut()
2687            .set_position(Vector3::new(0.0, 2.0, 0.0));
2688        graph[a].set_enabled(false);
2689        graph[b].set_visibility(true);
2690
2691        graph.update(Vector2::new(1.0, 1.0), 1.0 / 60.0, Default::default());
2692
2693        assert_eq!(graph[a].global_position(), Vector3::new(1.0, 0.0, 0.0));
2694        assert_eq!(graph[b].global_position(), Vector3::new(1.0, 2.0, 0.0));
2695        assert_eq!(graph[c].global_position(), Vector3::new(1.0, 2.0, 1.0));
2696        assert_eq!(graph[d].global_position(), Vector3::new(2.0, 1.0, 1.0));
2697
2698        assert!(graph[a].global_visibility());
2699        assert!(graph[b].global_visibility());
2700        assert!(graph[c].global_visibility());
2701        assert!(graph[d].global_visibility());
2702
2703        assert!(!graph.pool.try_get(a).unwrap().is_globally_enabled());
2704        assert!(!graph[b].is_globally_enabled());
2705        assert!(!graph[c].is_globally_enabled());
2706        assert!(!graph[d].is_globally_enabled());
2707    }
2708
2709    #[test]
2710    fn test_typed_borrow() {
2711        let mut graph = Graph::new();
2712        let pivot = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
2713        let rigid_body = RigidBodyBuilder::new(BaseBuilder::new()).build(&mut graph);
2714
2715        assert!(graph.pool.try_get(pivot).is_ok());
2716        assert!(graph.pool.try_get(pivot.transmute::<Pivot>()).is_ok());
2717        assert!(graph.pool.try_get(pivot.transmute::<RigidBody>()).is_err());
2718
2719        assert!(graph.pool.try_get(rigid_body).is_ok());
2720        assert!(graph
2721            .pool
2722            .try_get(rigid_body.transmute::<RigidBody>())
2723            .is_ok());
2724        assert!(graph.pool.try_get(rigid_body.transmute::<Pivot>()).is_err());
2725    }
2726}