1use 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#[derive(Clone, Default, Debug)]
95pub struct GraphPerformanceStatistics {
96 pub hierarchical_properties_time: Duration,
99
100 pub sync_time: Duration,
103
104 pub physics: PhysicsPerformanceStatistics,
106
107 pub physics2d: PhysicsPerformanceStatistics,
109
110 pub sound_update_time: Duration,
112}
113
114impl GraphPerformanceStatistics {
115 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
125pub type NodePool = Pool<Node, NodeContainer>;
127
128#[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 pub physics: PhysicsWorld,
141
142 pub physics2d: dim2::physics::PhysicsWorld,
144
145 #[reflect(hidden)]
147 pub sound_context: SoundContext,
148
149 #[reflect(hidden)]
151 pub performance_statistics: GraphPerformanceStatistics,
152
153 #[reflect(hidden)]
155 pub event_broadcaster: GraphEventBroadcaster,
156
157 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#[derive(Debug)]
204pub struct SubGraph {
205 pub root: (Ticket<Node>, Node),
207
208 pub descendants: Vec<(Ticket<Node>, Node)>,
210
211 pub parent: Handle<Node>,
214}
215
216fn remap_handles(old_new_mapping: &NodeHandleMap<Node>, dest_graph: &mut Graph) {
217 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
226pub 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
238pub 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
248fn clear_links(mut node: Node) -> Node {
252 node.children.clear();
253 node.parent = Handle::NONE;
254 node
255}
256
257#[derive(Clone, PartialEq, Eq)]
259pub struct GraphUpdateSwitches {
260 pub physics2d: bool,
262 pub physics: bool,
264 pub node_overrides: Option<FxHashSet<Handle<Node>>>,
266 pub delete_dead_nodes: bool,
269 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 #[inline]
289 pub fn new() -> Self {
290 let (script_message_sender, script_message_receiver) = channel();
291 let (message_sender, message_receiver) = channel();
292
293 let mut root_node = Pivot::default();
295 let instance_id = root_node.instance_id;
296 root_node.set_name("__ROOT__");
297
298 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 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 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 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 #[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 #[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 #[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 #[inline]
401 pub fn get_root(&self) -> Handle<Node> {
402 self.root
403 }
404
405 #[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 #[inline]
446 pub fn begin_multi_borrow(&mut self) -> MultiBorrowContext<Node, NodeContainer> {
447 self.pool.begin_multi_borrow()
448 }
449
450 #[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 #[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 #[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 #[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 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 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 #[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 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 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 pub fn set_lightmap(&mut self, lightmap: Lightmap) -> Result<Option<Lightmap>, &'static str> {
703 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 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 pub fn lightmap(&self) -> Option<&Lightmap> {
731 self.lightmap.as_ref()
732 }
733
734 fn apply_lightmap(&mut self) {
735 if let Some(lightmap) = self.lightmap.as_mut() {
739 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 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 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 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 #[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 #[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 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 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 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 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 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 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 #[inline]
1182 pub fn capacity(&self) -> u32 {
1183 self.pool.get_capacity()
1184 }
1185
1186 #[inline]
1206 pub fn handle_from_index(&self, index: u32) -> Handle<Node> {
1207 self.pool.handle_from_index(index)
1208 }
1209
1210 #[inline]
1212 pub fn generate_free_handles(&self, amount: usize) -> Vec<Handle<Node>> {
1213 self.pool.generate_free_handles(amount)
1214 }
1215
1216 #[inline]
1219 pub fn linear_iter(&self) -> impl Iterator<Item = &Node> {
1220 self.pool.iter()
1221 }
1222
1223 #[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 #[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 #[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 #[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 #[inline]
1274 pub fn take_reserve_sub_graph(&mut self, root: Handle<Node>) -> SubGraph {
1275 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: self.take_reserve(root),
1288 descendants,
1289 parent,
1290 }
1291 }
1292
1293 #[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 #[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 #[inline]
1322 pub fn node_count(&self) -> u32 {
1323 self.pool.alive_count()
1324 }
1325
1326 #[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 #[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 #[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 #[inline]
1400 pub fn isometric_local_transform(&self, node: Handle<Node>) -> Matrix4<f32> {
1401 isometric_local_transform(&self.pool, node)
1402 }
1403
1404 #[inline]
1407 pub fn isometric_global_transform(&self, node: Handle<Node>) -> Matrix4<f32> {
1408 isometric_global_transform(&self.pool, node)
1409 }
1410
1411 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 pub fn id_to_node_handle(&self, id: SceneNodeId) -> Option<&Handle<Node>> {
1543 self.instance_id_map.get(&id)
1544 }
1545
1546 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 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 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 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 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 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 let parent_handle = std::mem::replace(&mut self.pool[node_handle].parent, Handle::NONE);
1762
1763 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 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 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 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 {
2063 let mut scene = create_scene();
2064 save_scene(&mut scene, root_asset_path);
2065 }
2066
2067 {
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 {
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 PivotBuilder::new(BaseBuilder::new().with_name("AddedLater")).build(&mut scene.graph);
2094
2095 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 let existing_pivot = scene.graph.find_by_name_from_root("Pivot").unwrap().0;
2103 scene.graph.remove_node(existing_pivot);
2104
2105 save_scene(&mut scene, root_asset_path);
2107 }
2108
2109 {
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 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 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}