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