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