1use crate::scene::node::NodeAsAny;
46use crate::{
47 asset::untyped::UntypedResource,
48 core::{
49 algebra::{Matrix4, Rotation3, UnitQuaternion, Vector2, Vector3},
50 instant,
51 log::{Log, MessageKind},
52 math::{aabb::AxisAlignedBoundingBox, Matrix4Ext},
53 pool::{ErasedHandle, Handle, MultiBorrowContext, Pool, Ticket},
54 reflect::prelude::*,
55 visitor::{Visit, VisitResult, Visitor},
56 },
57 graph::{AbstractSceneGraph, AbstractSceneNode, BaseSceneGraph, NodeHandleMap, SceneGraph},
58 material::{MaterialResourceBinding, MaterialTextureBinding},
59 resource::model::{Model, ModelResource, ModelResourceExtension},
60 scene::{
61 base::{NodeMessage, NodeMessageKind, NodeScriptMessage, SceneNodeId},
62 dim2::{self},
63 graph::{
64 event::{GraphEvent, GraphEventBroadcaster},
65 physics::{PhysicsPerformanceStatistics, PhysicsWorld},
66 },
67 mesh::Mesh,
68 navmesh,
69 node::{container::NodeContainer, Node, SyncContext, UpdateContext},
70 pivot::Pivot,
71 sound::context::SoundContext,
72 transform::TransformBuilder,
73 },
74 script::ScriptTrait,
75 utils::lightmap::{self, Lightmap},
76};
77use bitflags::bitflags;
78use fxhash::{FxHashMap, FxHashSet};
79use fyrox_core::pool::ObjectOrVariant;
80use fyrox_graph::SceneGraphNode;
81use std::fmt::Write;
82use std::ops::Deref;
83use std::{
84 any::{Any, TypeId},
85 fmt::Debug,
86 ops::{Index, IndexMut},
87 sync::mpsc::{channel, Receiver, Sender},
88 time::Duration,
89};
90
91pub mod event;
92pub mod physics;
93
94#[derive(Clone, Default, Debug)]
97pub struct GraphPerformanceStatistics {
98 pub hierarchical_properties_time: Duration,
101
102 pub sync_time: Duration,
105
106 pub physics: PhysicsPerformanceStatistics,
108
109 pub physics2d: PhysicsPerformanceStatistics,
111
112 pub sound_update_time: Duration,
114}
115
116impl GraphPerformanceStatistics {
117 pub fn total(&self) -> Duration {
119 self.hierarchical_properties_time
120 + self.sync_time
121 + self.physics.total()
122 + self.physics2d.total()
123 + self.sound_update_time
124 }
125}
126
127pub type NodePool = Pool<Node, NodeContainer>;
129
130#[derive(Reflect)]
132pub struct Graph {
133 #[reflect(hidden)]
134 root: Handle<Node>,
135
136 pool: NodePool,
137
138 #[reflect(hidden)]
139 stack: Vec<Handle<Node>>,
140
141 pub physics: PhysicsWorld,
143
144 pub physics2d: dim2::physics::PhysicsWorld,
146
147 #[reflect(hidden)]
149 pub sound_context: SoundContext,
150
151 #[reflect(hidden)]
153 pub performance_statistics: GraphPerformanceStatistics,
154
155 #[reflect(hidden)]
157 pub event_broadcaster: GraphEventBroadcaster,
158
159 lightmap: Option<Lightmap>,
161
162 #[reflect(hidden)]
163 pub(crate) script_message_sender: Sender<NodeScriptMessage>,
164 #[reflect(hidden)]
165 pub(crate) script_message_receiver: Receiver<NodeScriptMessage>,
166
167 #[reflect(hidden)]
168 pub(crate) message_sender: Sender<NodeMessage>,
169 #[reflect(hidden)]
170 pub(crate) message_receiver: Receiver<NodeMessage>,
171
172 instance_id_map: FxHashMap<SceneNodeId, Handle<Node>>,
173}
174
175impl Debug for Graph {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 f.debug_struct("Graph")
178 .field("physics", &self.physics)
179 .field("physics2d", &self.physics2d)
180 .field("sound_context", &self.sound_context)
181 .field("performance_statistics", &self.performance_statistics)
182 .field("event_broadcaster", &self.event_broadcaster)
183 .field("lightmap", &self.lightmap)
184 .field("instance_id_map", &self.instance_id_map)
185 .finish()?;
186 f.write_char('\n')?;
187 f.write_str(&self.summary())
188 }
189}
190
191impl Clone for Graph {
192 fn clone(&self) -> Self {
193 self.clone_ex(
194 self.root,
195 &mut |_, _| true,
196 &mut |_, _| {},
197 &mut |_, _, _| {},
198 )
199 .0
200 }
201}
202
203impl Default for Graph {
204 fn default() -> Self {
205 let (script_message_sender, script_message_receiver) = channel();
206 let (message_sender, message_receiver) = channel();
207
208 Self {
209 physics: PhysicsWorld::new(),
210 physics2d: dim2::physics::PhysicsWorld::new(),
211 root: Handle::NONE,
212 pool: Pool::new(),
213 stack: Vec::new(),
214 sound_context: Default::default(),
215 performance_statistics: Default::default(),
216 event_broadcaster: Default::default(),
217 script_message_receiver,
218 message_sender,
219 script_message_sender,
220 lightmap: None,
221 instance_id_map: Default::default(),
222 message_receiver,
223 }
224 }
225}
226
227#[derive(Debug)]
234pub struct SubGraph {
235 pub root: (Ticket<Node>, Node),
237
238 pub descendants: Vec<(Ticket<Node>, Node)>,
240
241 pub parent: Handle<Node>,
244}
245
246fn remap_handles(old_new_mapping: &NodeHandleMap<Node>, dest_graph: &mut Graph) {
250 for (_, &new_node_handle) in old_new_mapping.inner().iter() {
252 old_new_mapping.remap_handles(
253 &mut dest_graph.pool[new_node_handle],
254 &[TypeId::of::<UntypedResource>()],
255 );
256 }
257}
258
259pub fn isometric_local_transform(nodes: &NodePool, node: Handle<Node>) -> Matrix4<f32> {
261 let transform = nodes[node].local_transform();
262 TransformBuilder::new()
263 .with_local_position(**transform.position())
264 .with_local_rotation(**transform.rotation())
265 .with_pre_rotation(**transform.pre_rotation())
266 .with_post_rotation(**transform.post_rotation())
267 .build()
268 .matrix()
269}
270
271pub fn isometric_global_transform(nodes: &NodePool, node: Handle<Node>) -> Matrix4<f32> {
273 let parent = nodes[node].parent();
274 if parent.is_some() {
275 isometric_global_transform(nodes, parent) * isometric_local_transform(nodes, node)
276 } else {
277 isometric_local_transform(nodes, node)
278 }
279}
280
281fn clear_links(mut node: Node) -> Node {
285 node.children.clear();
286 node.parent = Handle::NONE;
287 node
288}
289
290#[derive(Debug, Clone, PartialEq, Eq)]
292pub struct GraphUpdateSwitches {
293 pub physics_dt: bool,
295 pub physics2d: bool,
297 pub physics: bool,
299 pub node_overrides: Option<FxHashSet<Handle<Node>>>,
301 pub delete_dead_nodes: bool,
304 pub paused: bool,
307}
308
309impl Default for GraphUpdateSwitches {
310 fn default() -> Self {
311 Self {
312 physics_dt: true,
313 physics2d: true,
314 physics: true,
315 node_overrides: Default::default(),
316 delete_dead_nodes: true,
317 paused: false,
318 }
319 }
320}
321
322impl Graph {
323 #[inline]
325 pub fn new() -> Self {
326 let (script_message_sender, script_message_receiver) = channel();
327 let (message_sender, message_receiver) = channel();
328
329 let mut root_node = Pivot::default();
331 let instance_id = root_node.instance_id;
332 root_node.set_name("__ROOT__");
333
334 let mut pool = Pool::new();
336 let root = pool.spawn(Node::new(root_node));
337 pool[root].on_connected_to_graph(
338 root,
339 message_sender.clone(),
340 script_message_sender.clone(),
341 );
342
343 let instance_id_map = FxHashMap::from_iter([(instance_id, root)]);
344
345 Self {
346 physics: Default::default(),
347 stack: Vec::new(),
348 root,
349 pool,
350 physics2d: Default::default(),
351 sound_context: SoundContext::new(),
352 performance_statistics: Default::default(),
353 event_broadcaster: Default::default(),
354 script_message_receiver,
355 message_sender,
356 script_message_sender,
357 lightmap: None,
358 instance_id_map,
359 message_receiver,
360 }
361 }
362
363 pub fn from_hierarchy(root: Handle<Node>, other_graph: &Self) -> Self {
365 let mut graph = Self::default();
366 other_graph.copy_node(
367 root,
368 &mut graph,
369 &mut |_, _| true,
370 &mut |_, _| {},
371 &mut |_, _, _| {},
372 );
373 graph
374 }
375
376 fn recursive_summary(&self, indent: usize, current: Handle<Node>, result: &mut String) {
377 for _ in 0..indent {
378 result.push_str(" ");
379 }
380 let Some(node) = self.try_get(current) else {
381 use std::fmt::Write;
382 writeln!(result, "{}: Failed to get", current).unwrap();
383 return;
384 };
385 result.push_str(&node.summary());
386 result.push('\n');
387 for script in node.scripts() {
388 for _ in 0..indent + 1 {
389 result.push_str(" ");
390 }
391 result.push_str("+ Script: ");
392 result.push_str(&script.summary());
393 result.push('\n');
394 }
395 for child in node.children() {
396 self.recursive_summary(indent + 1, *child, result);
397 }
398 }
399
400 pub fn change_root_node(&mut self, root: Node) {
403 let prev_root = self.root;
404 self.root = Handle::NONE;
405 let handle = self.add_node(root);
406 assert_eq!(self.root, handle);
407 self.link_nodes(prev_root, handle);
408 }
409
410 pub fn find_references_to(&self, target: Handle<Node>) -> Vec<Handle<Node>> {
414 let mut references = Vec::new();
415 for (node_handle, node) in self.pair_iter() {
416 (node as &dyn Reflect).apply_recursively(
417 &mut |object| {
418 object.as_any(&mut |any| {
419 if let Some(handle) = any.downcast_ref::<Handle<Node>>() {
420 if *handle == target {
421 references.push(node_handle);
422 }
423 }
424 })
425 },
426 &[TypeId::of::<UntypedResource>()],
427 );
428 }
429 references
430 }
431
432 pub fn set_global_position(&mut self, node_handle: Handle<Node>, position: Vector3<f32>) {
446 let (node, parent) = self
447 .pool
448 .try_borrow_dependant_mut(node_handle, |node| node.parent());
449 if let Some(node) = node {
450 if let Some(parent) = parent {
451 let relative_position = parent
452 .global_transform()
453 .try_inverse()
454 .unwrap_or_default()
455 .transform_point(&position.into())
456 .coords;
457 node.local_transform_mut().set_position(relative_position);
458 } else {
459 node.local_transform_mut().set_position(position);
460 }
461 self.update_hierarchical_data_for_descendants(node_handle);
462 }
463 }
464
465 pub fn set_global_rotation(&mut self, node: Handle<Node>, rotation: UnitQuaternion<f32>) {
479 let (node, parent) = self
480 .pool
481 .try_borrow_dependant_mut(node, |node| node.parent());
482 if let Some(node) = node {
483 if let Some(parent) = parent {
484 let basis = parent
485 .global_transform()
486 .try_inverse()
487 .unwrap_or_default()
488 .basis();
489 let relative_rotation = UnitQuaternion::from_matrix(&basis) * rotation;
490 node.local_transform_mut().set_rotation(relative_rotation);
491 } else {
492 node.local_transform_mut().set_rotation(rotation);
493 }
494 }
495 }
496
497 #[inline]
500 pub fn get_two_mut(&mut self, nodes: (Handle<Node>, Handle<Node>)) -> (&mut Node, &mut Node) {
501 self.pool.borrow_two_mut(nodes)
502 }
503
504 #[inline]
507 pub fn get_three_mut(
508 &mut self,
509 nodes: (Handle<Node>, Handle<Node>, Handle<Node>),
510 ) -> (&mut Node, &mut Node, &mut Node) {
511 self.pool.borrow_three_mut(nodes)
512 }
513
514 #[inline]
517 pub fn get_four_mut(
518 &mut self,
519 nodes: (Handle<Node>, Handle<Node>, Handle<Node>, Handle<Node>),
520 ) -> (&mut Node, &mut Node, &mut Node, &mut Node) {
521 self.pool.borrow_four_mut(nodes)
522 }
523
524 #[inline]
526 pub fn get_root(&self) -> Handle<Node> {
527 self.root
528 }
529
530 #[inline]
565 pub fn begin_multi_borrow(&mut self) -> MultiBorrowContext<Node, NodeContainer> {
566 self.pool.begin_multi_borrow()
567 }
568
569 #[inline]
572 pub fn link_nodes_keep_global_transform(&mut self, child: Handle<Node>, parent: Handle<Node>) {
573 let parent_global_transform_inv = self.pool[parent]
574 .global_transform()
575 .try_inverse()
576 .unwrap_or_default();
577 let child_global_transform = self.pool[child].global_transform();
578 let relative_transform = parent_global_transform_inv * child_global_transform;
579 let local_position = relative_transform.position();
580 let parent_inv_global_rotation = self.global_rotation(parent).inverse();
581 let local_rotation = parent_inv_global_rotation * self.global_rotation(child);
582 let local_scale = self
583 .global_scale(child)
584 .component_div(&self.global_scale(parent));
585 self.pool[child]
586 .local_transform_mut()
587 .set_position(local_position)
588 .set_rotation(local_rotation)
589 .set_scale(local_scale);
590 self.link_nodes(child, parent);
591 }
592
593 #[inline]
596 pub fn find_first_by_script<S>(&self, root_node: Handle<Node>) -> Option<(Handle<Node>, &Node)>
597 where
598 S: ScriptTrait,
599 {
600 self.find(root_node, &mut |node| {
601 for script in &node.scripts {
602 if script.as_ref().and_then(|s| s.cast::<S>()).is_some() {
603 return true;
604 }
605 }
606 false
607 })
608 }
609
610 #[inline]
639 pub fn copy_node<F, Pre, Post>(
640 &self,
641 node_handle: Handle<Node>,
642 dest_graph: &mut Graph,
643 filter: &mut F,
644 pre_process_callback: &mut Pre,
645 post_process_callback: &mut Post,
646 ) -> (Handle<Node>, NodeHandleMap<Node>)
647 where
648 F: FnMut(Handle<Node>, &Node) -> bool,
649 Pre: FnMut(Handle<Node>, &mut Node),
650 Post: FnMut(Handle<Node>, Handle<Node>, &mut Node),
651 {
652 let mut old_new_mapping = NodeHandleMap::default();
653 let root_handle = self.copy_node_raw(
654 node_handle,
655 dest_graph,
656 &mut old_new_mapping,
657 filter,
658 pre_process_callback,
659 post_process_callback,
660 );
661
662 remap_handles(&old_new_mapping, dest_graph);
663
664 (root_handle, old_new_mapping)
665 }
666
667 #[inline]
682 pub fn copy_node_inplace<F>(
683 &mut self,
684 node_handle: Handle<Node>,
685 filter: &mut F,
686 ) -> (Handle<Node>, NodeHandleMap<Node>)
687 where
688 F: FnMut(Handle<Node>, &Node) -> bool,
689 {
690 let mut old_new_mapping = NodeHandleMap::default();
691
692 let to_copy = self
693 .traverse_iter(node_handle)
694 .map(|(descendant_handle, descendant)| (descendant_handle, descendant.children.clone()))
695 .collect::<Vec<_>>();
696
697 let mut root_handle = Handle::NONE;
698
699 for (parent, children) in to_copy.iter() {
700 let parent_copy = clear_links(self.pool[*parent].clone_box());
702 let parent_copy_handle = self.add_node(parent_copy);
703 old_new_mapping.insert(*parent, parent_copy_handle);
704
705 if root_handle.is_none() {
706 root_handle = parent_copy_handle;
707 }
708
709 for &child in children {
711 if filter(child, &self.pool[child]) {
712 let child_copy = clear_links(self.pool[child].clone_box());
713 let child_copy_handle = self.add_node(child_copy);
714 old_new_mapping.insert(child, child_copy_handle);
715 self.link_nodes(child_copy_handle, parent_copy_handle);
716 }
717 }
718 }
719
720 remap_handles(&old_new_mapping, self);
721
722 (root_handle, old_new_mapping)
723 }
724
725 #[inline]
731 pub fn copy_single_node(&self, node_handle: Handle<Node>) -> Node {
732 let node = &self.pool[node_handle];
733 let mut clone = clear_links(node.clone_box());
734 if let Some(ref mut mesh) = clone.cast_mut::<Mesh>() {
735 for surface in mesh.surfaces_mut() {
736 surface.bones.clear();
737 }
738 }
739 clone
740 }
741
742 fn copy_node_raw<F, Pre, Post>(
758 &self,
759 root_handle: Handle<Node>,
760 dest_graph: &mut Graph,
761 old_new_mapping: &mut NodeHandleMap<Node>,
762 filter: &mut F,
763 pre_process_callback: &mut Pre,
764 post_process_callback: &mut Post,
765 ) -> Handle<Node>
766 where
767 F: FnMut(Handle<Node>, &Node) -> bool,
768 Pre: FnMut(Handle<Node>, &mut Node),
769 Post: FnMut(Handle<Node>, Handle<Node>, &mut Node),
770 {
771 let src_node = &self.pool[root_handle];
772 let mut dest_node = clear_links(src_node.clone_box());
773 pre_process_callback(root_handle, &mut dest_node);
774 let dest_copy_handle = dest_graph.add_node(dest_node);
775 old_new_mapping.insert(root_handle, dest_copy_handle);
776 for &src_child_handle in src_node.children() {
777 if filter(src_child_handle, &self.pool[src_child_handle]) {
778 let dest_child_handle = self.copy_node_raw(
779 src_child_handle,
780 dest_graph,
781 old_new_mapping,
782 filter,
783 pre_process_callback,
784 post_process_callback,
785 );
786 if !dest_child_handle.is_none() {
787 dest_graph.link_nodes(dest_child_handle, dest_copy_handle);
788 }
789 }
790 }
791 post_process_callback(
792 dest_copy_handle,
793 root_handle,
794 &mut dest_graph[dest_copy_handle],
795 );
796 dest_copy_handle
797 }
798
799 fn restore_dynamic_node_data(&mut self) {
802 for (handle, node) in self.pool.pair_iter_mut() {
803 node.on_connected_to_graph(
804 handle,
805 self.message_sender.clone(),
806 self.script_message_sender.clone(),
807 );
808 }
809 }
810
811 pub(crate) fn mark_ancestor_nodes_as_modified(&mut self) {
814 for node in self.linear_iter_mut() {
815 if node.resource.is_none() {
816 node.mark_inheritable_variables_as_modified();
817 }
818 }
819 }
820
821 pub(crate) fn resolve(&mut self) {
823 Log::writeln(MessageKind::Information, "Resolving graph...");
824
825 self.restore_dynamic_node_data();
826 self.mark_ancestor_nodes_as_modified();
827 self.restore_original_handles_and_inherit_properties(
831 &[TypeId::of::<navmesh::Container>()],
832 |resource_node, node| {
833 node.inv_bind_pose_transform = resource_node.inv_bind_pose_transform;
834 },
835 );
836 self.update_hierarchical_data();
837 let instances = self.restore_integrity(|model, model_data, handle, dest_graph| {
842 ModelResource::instantiate_from(model, model_data, handle, dest_graph, &mut |_, _| {})
843 });
844 self.remap_handles(&instances);
849
850 self.apply_lightmap();
851
852 Log::writeln(MessageKind::Information, "Graph resolved successfully!");
853 }
854
855 pub fn set_lightmap(&mut self, lightmap: Lightmap) -> Result<Option<Lightmap>, &'static str> {
857 for (handle, lightmaps) in lightmap.map.iter() {
859 if let Some(mesh) = self[*handle].cast_mut::<Mesh>() {
860 if mesh.surfaces().len() != lightmaps.len() {
861 return Err("failed to set lightmap, surface count mismatch");
862 }
863
864 for (surface, entry) in mesh.surfaces_mut().iter_mut().zip(lightmaps) {
865 let texture = entry.texture.clone().unwrap();
868 let mut material_state = surface.material().state();
869 if let Some(material) = material_state.data() {
870 material.bind(
871 "lightmapTexture",
872 MaterialResourceBinding::Texture(MaterialTextureBinding {
873 value: Some(texture),
874 }),
875 );
876 }
877 }
878 }
879 }
880 Ok(self.lightmap.replace(lightmap))
881 }
882
883 pub fn lightmap(&self) -> Option<&Lightmap> {
885 self.lightmap.as_ref()
886 }
887
888 fn apply_lightmap(&mut self) {
889 if let Some(lightmap) = self.lightmap.as_mut() {
893 let mut unique_data_set = FxHashMap::default();
896 for &handle in lightmap.map.keys() {
897 if let Some(mesh) = self.pool[handle].cast_mut::<Mesh>() {
898 for surface in mesh.surfaces() {
899 let data = surface.data();
900 unique_data_set.entry(data.key()).or_insert(data);
901 }
902 }
903 }
904
905 for (_, data) in unique_data_set.into_iter() {
906 let mut data = data.data_ref();
907
908 if let Some(patch) = lightmap.patches.get(&data.content_hash()) {
909 lightmap::apply_surface_data_patch(&mut data, &patch.0);
910 } else {
911 Log::writeln(
912 MessageKind::Warning,
913 "Failed to get surface data patch while resolving lightmap!\
914 This means that surface has changed and lightmap must be regenerated!",
915 );
916 }
917 }
918
919 for (&handle, entries) in lightmap.map.iter_mut() {
921 if let Some(mesh) = self.pool[handle].cast_mut::<Mesh>() {
922 for (entry, surface) in entries.iter_mut().zip(mesh.surfaces_mut()) {
923 let mut material_state = surface.material().state();
924 if let Some(material) = material_state.data() {
925 material.bind(
926 "lightmapTexture",
927 MaterialResourceBinding::Texture(MaterialTextureBinding {
928 value: entry.texture.clone(),
929 }),
930 );
931 }
932 }
933 }
934 }
935 }
936 }
937
938 pub fn aabb_of_descendants<F>(
942 &self,
943 root: Handle<Node>,
944 mut filter: F,
945 ) -> Option<AxisAlignedBoundingBox>
946 where
947 F: FnMut(Handle<Node>, &Node) -> bool,
948 {
949 fn aabb_of_descendants_recursive<F>(
950 graph: &Graph,
951 node: Handle<Node>,
952 filter: &mut F,
953 ) -> Option<AxisAlignedBoundingBox>
954 where
955 F: FnMut(Handle<Node>, &Node) -> bool,
956 {
957 graph.try_get_node(node).and_then(|n| {
958 if filter(node, n) {
959 let mut aabb = n.local_bounding_box();
960 if aabb.is_invalid_or_degenerate() {
961 aabb = AxisAlignedBoundingBox::collapsed().transform(&n.global_transform());
962 } else {
963 aabb = aabb.transform(&n.global_transform());
964 }
965 for child in n.children() {
966 if let Some(child_aabb) =
967 aabb_of_descendants_recursive(graph, *child, filter)
968 {
969 aabb.add_box(child_aabb);
970 }
971 }
972 Some(aabb)
973 } else {
974 None
975 }
976 })
977 }
978 aabb_of_descendants_recursive(self, root, &mut filter)
979 }
980
981 pub(crate) fn update_enabled_flag_recursively(nodes: &NodePool, node_handle: Handle<Node>) {
982 let Some(node) = nodes.try_borrow(node_handle) else {
983 return;
984 };
985
986 let parent_enabled = nodes
987 .try_borrow(node.parent())
988 .is_none_or(|p| p.is_globally_enabled());
989 node.global_enabled.set(parent_enabled && node.is_enabled());
990
991 for &child in node.children() {
992 Self::update_enabled_flag_recursively(nodes, child);
993 }
994 }
995
996 pub(crate) fn update_visibility_recursively(nodes: &NodePool, node_handle: Handle<Node>) {
997 let Some(node) = nodes.try_borrow(node_handle) else {
998 return;
999 };
1000
1001 let parent_visibility = nodes
1002 .try_borrow(node.parent())
1003 .is_none_or(|p| p.global_visibility());
1004 node.global_visibility
1005 .set(parent_visibility && node.visibility());
1006
1007 for &child in node.children() {
1008 Self::update_visibility_recursively(nodes, child);
1009 }
1010 }
1011
1012 pub(crate) fn update_global_transform_recursively(
1013 nodes: &NodePool,
1014 sound_context: &mut SoundContext,
1015 physics: &mut PhysicsWorld,
1016 physics2d: &mut dim2::physics::PhysicsWorld,
1017 node_handle: Handle<Node>,
1018 ) {
1019 let Some(node) = nodes.try_borrow(node_handle) else {
1020 return;
1021 };
1022
1023 let parent_global_transform = if let Some(parent) = nodes.try_borrow(node.parent()) {
1024 parent.global_transform()
1025 } else {
1026 Matrix4::identity()
1027 };
1028
1029 let new_global_transform = parent_global_transform * node.local_transform().matrix();
1030
1031 node.on_global_transform_changed(
1033 &new_global_transform,
1034 &mut SyncContext {
1035 nodes,
1036 physics,
1037 physics2d,
1038 sound_context,
1039 switches: None,
1040 },
1041 );
1042
1043 node.global_transform.set(new_global_transform);
1044
1045 for &child in node.children() {
1046 Self::update_global_transform_recursively(
1047 nodes,
1048 sound_context,
1049 physics,
1050 physics2d,
1051 child,
1052 );
1053 }
1054 }
1055
1056 #[inline]
1064 pub fn update_hierarchical_data_for_descendants(&mut self, node_handle: Handle<Node>) {
1065 Self::update_hierarchical_data_recursively(
1066 &self.pool,
1067 &mut self.sound_context,
1068 &mut self.physics,
1069 &mut self.physics2d,
1070 node_handle,
1071 );
1072 }
1073
1074 #[inline]
1082 pub fn update_hierarchical_data(&mut self) {
1083 self.update_hierarchical_data_for_descendants(self.root);
1084 }
1085
1086 pub(crate) fn update_hierarchical_data_recursively(
1087 nodes: &NodePool,
1088 sound_context: &mut SoundContext,
1089 physics: &mut PhysicsWorld,
1090 physics2d: &mut dim2::physics::PhysicsWorld,
1091 node_handle: Handle<Node>,
1092 ) {
1093 Self::update_global_transform_recursively(
1094 nodes,
1095 sound_context,
1096 physics,
1097 physics2d,
1098 node_handle,
1099 );
1100 Self::update_enabled_flag_recursively(nodes, node_handle);
1101 Self::update_visibility_recursively(nodes, node_handle);
1102 }
1103
1104 pub(crate) fn process_node_messages(&mut self, switches: Option<&GraphUpdateSwitches>) {
1114 bitflags! {
1115 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1116 struct Flags: u8 {
1117 const NONE = 0;
1118 const TRANSFORM_CHANGED = 0b0001;
1119 const VISIBILITY_CHANGED = 0b0010;
1120 const ENABLED_FLAG_CHANGED = 0b0100;
1121 }
1122 }
1123
1124 let mut visited_flags = vec![Flags::NONE; self.pool.get_capacity() as usize];
1125 let mut roots = FxHashMap::default();
1126
1127 while let Ok(message) = self.message_receiver.try_recv() {
1128 if let NodeMessageKind::TransformChanged = message.kind {
1129 if let Some(node) = self.pool.try_borrow(message.node) {
1130 node.on_local_transform_changed(&mut SyncContext {
1131 nodes: &self.pool,
1132 physics: &mut self.physics,
1133 physics2d: &mut self.physics2d,
1134 sound_context: &mut self.sound_context,
1135 switches,
1136 })
1137 }
1138 }
1139
1140 let message_flag = match message.kind {
1142 NodeMessageKind::TransformChanged => Flags::TRANSFORM_CHANGED,
1143 NodeMessageKind::VisibilityChanged => Flags::VISIBILITY_CHANGED,
1144 NodeMessageKind::EnabledFlagChanged => Flags::ENABLED_FLAG_CHANGED,
1145 };
1146
1147 let visit_flags = &mut visited_flags[message.node.index() as usize];
1148
1149 if visit_flags.contains(message_flag) {
1150 continue;
1151 }
1152
1153 visit_flags.insert(message_flag);
1154
1155 roots
1156 .entry(message.node)
1157 .or_insert(Flags::NONE)
1158 .insert(message_flag);
1159
1160 fn traverse_recursive(
1162 graph: &Graph,
1163 from: Handle<Node>,
1164 func: &mut impl FnMut(Handle<Node>),
1165 ) {
1166 func(from);
1167 if let Some(node) = graph.try_get_node(from) {
1168 for &child in node.children() {
1169 traverse_recursive(graph, child, func)
1170 }
1171 }
1172 }
1173
1174 traverse_recursive(self, message.node, &mut |h| {
1175 visited_flags[h.index() as usize].insert(message_flag);
1176
1177 if h != message.node {
1179 if let Some(flags) = roots.get_mut(&h) {
1180 flags.remove(message_flag);
1181
1182 if flags.is_empty() {
1183 roots.remove(&h);
1184 }
1185 }
1186 }
1187 })
1188 }
1189
1190 for (node, flags) in roots {
1191 if flags.contains(Flags::TRANSFORM_CHANGED) {
1192 Self::update_global_transform_recursively(
1193 &self.pool,
1194 &mut self.sound_context,
1195 &mut self.physics,
1196 &mut self.physics2d,
1197 node,
1198 );
1199 }
1200 if flags.contains(Flags::VISIBILITY_CHANGED) {
1203 Self::update_visibility_recursively(&self.pool, node);
1204 }
1205 if flags.contains(Flags::ENABLED_FLAG_CHANGED) {
1206 Self::update_enabled_flag_recursively(&self.pool, node)
1207 }
1208 }
1209 }
1210
1211 fn sync_native(&mut self, switches: &GraphUpdateSwitches) {
1212 let mut sync_context = SyncContext {
1213 nodes: &self.pool,
1214 physics: &mut self.physics,
1215 physics2d: &mut self.physics2d,
1216 sound_context: &mut self.sound_context,
1217 switches: Some(switches),
1218 };
1219
1220 for (handle, node) in self.pool.pair_iter() {
1221 node.sync_native(handle, &mut sync_context);
1222 }
1223 }
1224
1225 fn update_node(
1226 &mut self,
1227 handle: Handle<Node>,
1228 frame_size: Vector2<f32>,
1229 dt: f32,
1230 delete_dead_nodes: bool,
1231 ) {
1232 if let Some((ticket, mut node)) = self.pool.try_take_reserve(handle) {
1233 let mut is_alive = node.is_alive();
1234
1235 if node.is_globally_enabled() {
1236 node.update(&mut UpdateContext {
1237 frame_size,
1238 dt,
1239 nodes: &mut self.pool,
1240 physics: &mut self.physics,
1241 physics2d: &mut self.physics2d,
1242 sound_context: &mut self.sound_context,
1243 });
1244
1245 if delete_dead_nodes {
1246 if let Some(lifetime) = node.lifetime.get_value_mut_silent().as_mut() {
1247 *lifetime -= dt;
1248 if *lifetime <= 0.0 {
1249 is_alive = false;
1250 }
1251 }
1252 }
1253 }
1254
1255 self.pool.put_back(ticket, node);
1256
1257 if !is_alive && delete_dead_nodes {
1258 self.remove_node(handle);
1259 }
1260 }
1261 }
1262
1263 pub fn update(&mut self, frame_size: Vector2<f32>, dt: f32, switches: GraphUpdateSwitches) {
1270 self.sound_context.state().pause(switches.paused);
1271
1272 if switches.paused {
1273 return;
1274 }
1275
1276 let last_time = instant::Instant::now();
1277 self.process_node_messages(Some(&switches));
1278 self.performance_statistics.hierarchical_properties_time =
1279 instant::Instant::now() - last_time;
1280
1281 let last_time = instant::Instant::now();
1282 self.sync_native(&switches);
1283 self.performance_statistics.sync_time = instant::Instant::now() - last_time;
1284
1285 if switches.physics {
1286 self.physics.performance_statistics.reset();
1287 self.physics.update(dt, switches.physics_dt);
1288 self.performance_statistics.physics = self.physics.performance_statistics.clone();
1289 }
1290
1291 if switches.physics2d {
1292 self.physics2d.performance_statistics.reset();
1293 self.physics2d.update(dt, switches.physics_dt);
1294 self.performance_statistics.physics2d = self.physics2d.performance_statistics.clone();
1295 }
1296
1297 self.performance_statistics.sound_update_time =
1298 self.sound_context.state().full_render_duration();
1299
1300 if let Some(overrides) = switches.node_overrides.as_ref() {
1301 for handle in overrides {
1302 self.update_node(*handle, frame_size, dt, switches.delete_dead_nodes);
1303 }
1304 } else {
1305 for i in 0..self.pool.get_capacity() {
1306 self.update_node(
1307 self.pool.handle_from_index(i),
1308 frame_size,
1309 dt,
1310 switches.delete_dead_nodes,
1311 );
1312 }
1313 }
1314 }
1315
1316 #[inline]
1336 pub fn capacity(&self) -> u32 {
1337 self.pool.get_capacity()
1338 }
1339
1340 #[inline]
1360 pub fn handle_from_index(&self, index: u32) -> Handle<Node> {
1361 self.pool.handle_from_index(index)
1362 }
1363
1364 #[inline]
1366 pub fn generate_free_handles(&self, amount: usize) -> Vec<Handle<Node>> {
1367 self.pool.generate_free_handles(amount)
1368 }
1369
1370 #[inline]
1373 pub fn linear_iter(&self) -> impl Iterator<Item = &Node> {
1374 self.pool.iter()
1375 }
1376
1377 #[inline]
1379 pub fn pair_iter_mut(&mut self) -> impl Iterator<Item = (Handle<Node>, &mut Node)> {
1380 self.pool.pair_iter_mut()
1381 }
1382
1383 #[inline]
1387 pub fn take_reserve(&mut self, handle: Handle<Node>) -> (Ticket<Node>, Node) {
1388 self.isolate_node(handle);
1389 let (ticket, node) = self.take_reserve_internal(handle);
1390 self.instance_id_map.remove(&node.instance_id);
1391 (ticket, node)
1392 }
1393
1394 pub(crate) fn take_reserve_internal(&mut self, handle: Handle<Node>) -> (Ticket<Node>, Node) {
1395 let (ticket, mut node) = self.pool.take_reserve(handle);
1396 self.instance_id_map.remove(&node.instance_id);
1397 node.on_removed_from_graph(self);
1398 (ticket, node)
1399 }
1400
1401 #[inline]
1403 pub fn put_back(&mut self, ticket: Ticket<Node>, node: Node) -> Handle<Node> {
1404 let handle = self.put_back_internal(ticket, node);
1405 self.link_nodes(handle, self.root);
1406 handle
1407 }
1408
1409 pub(crate) fn put_back_internal(&mut self, ticket: Ticket<Node>, node: Node) -> Handle<Node> {
1410 let instance_id = node.instance_id;
1411 let handle = self.pool.put_back(ticket, node);
1412 self.instance_id_map.insert(instance_id, handle);
1413 handle
1414 }
1415
1416 #[inline]
1418 pub fn forget_ticket(&mut self, ticket: Ticket<Node>, node: Node) -> Node {
1419 self.pool.forget_ticket(ticket);
1420 node
1421 }
1422
1423 #[inline]
1428 pub fn take_reserve_sub_graph(&mut self, root: Handle<Node>) -> SubGraph {
1429 let mut descendants = Vec::new();
1431 let root_ref = &mut self[root];
1432 let mut stack = root_ref.children().to_vec();
1433 let parent = root_ref.parent;
1434 while let Some(handle) = stack.pop() {
1435 stack.extend_from_slice(self[handle].children());
1436 descendants.push(self.take_reserve_internal(handle));
1437 }
1438
1439 SubGraph {
1440 root: self.take_reserve(root),
1442 descendants,
1443 parent,
1444 }
1445 }
1446
1447 #[inline]
1451 pub fn put_sub_graph_back(&mut self, sub_graph: SubGraph) -> Handle<Node> {
1452 for (ticket, node) in sub_graph.descendants {
1453 self.pool.put_back(ticket, node);
1454 }
1455
1456 let (ticket, node) = sub_graph.root;
1457 let root_handle = self.put_back(ticket, node);
1458
1459 self.link_nodes(root_handle, sub_graph.parent);
1460
1461 root_handle
1462 }
1463
1464 #[inline]
1466 pub fn forget_sub_graph(&mut self, sub_graph: SubGraph) {
1467 for (ticket, _) in sub_graph.descendants {
1468 self.pool.forget_ticket(ticket);
1469 }
1470 let (ticket, _) = sub_graph.root;
1471 self.pool.forget_ticket(ticket);
1472 }
1473
1474 #[inline]
1476 pub fn node_count(&self) -> u32 {
1477 self.pool.alive_count()
1478 }
1479
1480 #[inline]
1483 pub fn clone_ex<F, Pre, Post>(
1484 &self,
1485 root: Handle<Node>,
1486 filter: &mut F,
1487 pre_process_callback: &mut Pre,
1488 post_process_callback: &mut Post,
1489 ) -> (Self, NodeHandleMap<Node>)
1490 where
1491 F: FnMut(Handle<Node>, &Node) -> bool,
1492 Pre: FnMut(Handle<Node>, &mut Node),
1493 Post: FnMut(Handle<Node>, Handle<Node>, &mut Node),
1494 {
1495 let mut copy = Self {
1496 sound_context: self.sound_context.deep_clone(),
1497 physics: self.physics.clone(),
1498 physics2d: self.physics2d.clone(),
1499 ..Default::default()
1500 };
1501
1502 let (copy_root, old_new_map) = self.copy_node(
1503 root,
1504 &mut copy,
1505 filter,
1506 pre_process_callback,
1507 post_process_callback,
1508 );
1509 assert_eq!(copy.root, copy_root);
1510
1511 let mut lightmap = self.lightmap.clone();
1512 if let Some(lightmap) = lightmap.as_mut() {
1513 let mut map = FxHashMap::default();
1514 for (mut handle, mut entries) in std::mem::take(&mut lightmap.map) {
1515 for entry in entries.iter_mut() {
1516 for light_handle in entry.lights.iter_mut() {
1517 old_new_map.try_map(light_handle);
1518 }
1519 }
1520
1521 if old_new_map.try_map(&mut handle) {
1522 map.insert(handle, entries);
1523 }
1524 }
1525 lightmap.map = map;
1526 }
1527 copy.lightmap = lightmap;
1528
1529 (copy, old_new_map)
1530 }
1531
1532 #[inline]
1534 pub fn local_transform_no_scale(&self, node: Handle<Node>) -> Matrix4<f32> {
1535 let mut transform = self[node].local_transform().clone();
1536 transform.set_scale(Vector3::new(1.0, 1.0, 1.0));
1537 transform.matrix()
1538 }
1539
1540 #[inline]
1542 pub fn global_transform_no_scale(&self, node: Handle<Node>) -> Matrix4<f32> {
1543 let parent = self[node].parent();
1544 if parent.is_some() {
1545 self.global_transform_no_scale(parent) * self.local_transform_no_scale(node)
1546 } else {
1547 self.local_transform_no_scale(node)
1548 }
1549 }
1550
1551 #[inline]
1554 pub fn isometric_local_transform(&self, node: Handle<Node>) -> Matrix4<f32> {
1555 isometric_local_transform(&self.pool, node)
1556 }
1557
1558 #[inline]
1561 pub fn isometric_global_transform(&self, node: Handle<Node>) -> Matrix4<f32> {
1562 isometric_global_transform(&self.pool, node)
1563 }
1564
1565 #[inline]
1567 pub fn global_scale_matrix(&self, node: Handle<Node>) -> Matrix4<f32> {
1568 Matrix4::new_nonuniform_scaling(&self.global_scale(node))
1569 }
1570
1571 #[inline]
1573 pub fn global_rotation(&self, node: Handle<Node>) -> UnitQuaternion<f32> {
1574 UnitQuaternion::from(Rotation3::from_matrix_eps(
1575 &self.global_transform_no_scale(node).basis(),
1576 f32::EPSILON,
1577 16,
1578 Rotation3::identity(),
1579 ))
1580 }
1581
1582 #[inline]
1584 pub fn isometric_global_rotation(&self, node: Handle<Node>) -> UnitQuaternion<f32> {
1585 UnitQuaternion::from(Rotation3::from_matrix_eps(
1586 &self.isometric_global_transform(node).basis(),
1587 f32::EPSILON,
1588 16,
1589 Rotation3::identity(),
1590 ))
1591 }
1592
1593 #[inline]
1595 pub fn global_rotation_position_no_scale(
1596 &self,
1597 node: Handle<Node>,
1598 ) -> (UnitQuaternion<f32>, Vector3<f32>) {
1599 (self.global_rotation(node), self[node].global_position())
1600 }
1601
1602 #[inline]
1604 pub fn isometric_global_rotation_position(
1605 &self,
1606 node: Handle<Node>,
1607 ) -> (UnitQuaternion<f32>, Vector3<f32>) {
1608 (
1609 self.isometric_global_rotation(node),
1610 self[node].global_position(),
1611 )
1612 }
1613
1614 #[inline]
1616 pub fn global_scale(&self, mut node: Handle<Node>) -> Vector3<f32> {
1617 let mut global_scale = Vector3::repeat(1.0);
1618 while let Some(node_ref) = self.try_get_node(node) {
1619 global_scale = global_scale.component_mul(node_ref.local_transform().scale());
1620 node = node_ref.parent;
1621 }
1622 global_scale
1623 }
1624
1625 #[inline]
1628 pub fn try_get_script_of<T>(&self, node: Handle<Node>) -> Option<&T>
1629 where
1630 T: ScriptTrait,
1631 {
1632 self.try_get_node(node)
1633 .and_then(|node| node.try_get_script::<T>())
1634 }
1635
1636 #[inline]
1640 pub fn try_get_scripts_of<T: ScriptTrait>(
1641 &self,
1642 node: Handle<Node>,
1643 ) -> Option<impl Iterator<Item = &T>> {
1644 self.try_get_node(node).map(|n| n.try_get_scripts())
1645 }
1646
1647 #[inline]
1650 pub fn try_get_script_of_mut<T>(&mut self, node: Handle<Node>) -> Option<&mut T>
1651 where
1652 T: ScriptTrait,
1653 {
1654 self.try_get_node_mut(node)
1655 .and_then(|node| node.try_get_script_mut::<T>())
1656 }
1657
1658 #[inline]
1662 pub fn try_get_scripts_of_mut<T: ScriptTrait>(
1663 &mut self,
1664 node: Handle<Node>,
1665 ) -> Option<impl Iterator<Item = &mut T>> {
1666 self.try_get_node_mut(node).map(|n| n.try_get_scripts_mut())
1667 }
1668
1669 #[inline]
1673 pub fn try_get_script_component_of<C>(&self, node: Handle<Node>) -> Option<&C>
1674 where
1675 C: Any,
1676 {
1677 self.try_get_node(node)
1678 .and_then(|node| node.try_get_script_component())
1679 }
1680
1681 #[inline]
1685 pub fn try_get_script_component_of_mut<C>(&mut self, node: Handle<Node>) -> Option<&mut C>
1686 where
1687 C: Any,
1688 {
1689 self.try_get_node_mut(node)
1690 .and_then(|node| node.try_get_script_component_mut())
1691 }
1692
1693 pub fn id_to_node_handle(&self, id: SceneNodeId) -> Option<&Handle<Node>> {
1695 self.instance_id_map.get(&id)
1696 }
1697
1698 pub fn node_by_id(&self, id: SceneNodeId) -> Option<(Handle<Node>, &Node)> {
1700 self.instance_id_map
1701 .get(&id)
1702 .and_then(|h| self.pool.try_borrow(*h).map(|n| (*h, n)))
1703 }
1704
1705 pub fn node_by_id_mut(&mut self, id: SceneNodeId) -> Option<(Handle<Node>, &mut Node)> {
1707 self.instance_id_map
1708 .get(&id)
1709 .and_then(|h| self.pool.try_borrow_mut(*h).map(|n| (*h, n)))
1710 }
1711}
1712
1713impl<T: ObjectOrVariant<Node>> Index<Handle<T>> for Graph {
1714 type Output = T;
1715
1716 #[inline]
1717 fn index(&self, index: Handle<T>) -> &Self::Output {
1718 self.try_get(index)
1719 .expect("The node handle is invalid or the object it points to has different type.")
1720 }
1721}
1722
1723impl<T: ObjectOrVariant<Node>> IndexMut<Handle<T>> for Graph {
1724 #[inline]
1725 fn index_mut(&mut self, index: Handle<T>) -> &mut Self::Output {
1726 self.try_get_mut(index)
1727 .expect("The node handle is invalid or the object it points to has different type.")
1728 }
1729}
1730
1731impl Visit for Graph {
1732 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1733 if visitor.is_reading() && self.pool.get_capacity() != 0 {
1735 panic!("Graph pool must be empty on load!")
1736 }
1737
1738 let mut region = visitor.enter_region(name)?;
1739
1740 self.root.visit("Root", &mut region)?;
1741 self.pool.visit("Pool", &mut region)?;
1742 self.sound_context.visit("SoundContext", &mut region)?;
1743 self.physics.visit("PhysicsWorld", &mut region)?;
1744 self.physics2d.visit("PhysicsWorld2D", &mut region)?;
1745 let _ = self.lightmap.visit("Lightmap", &mut region);
1746
1747 Ok(())
1748 }
1749}
1750
1751impl AbstractSceneGraph for Graph {
1752 fn try_get_node_untyped(&self, handle: ErasedHandle) -> Option<&dyn AbstractSceneNode> {
1753 self.pool
1754 .try_borrow(handle.into())
1755 .map(|n| n as &dyn AbstractSceneNode)
1756 }
1757
1758 fn try_get_node_untyped_mut(
1759 &mut self,
1760 handle: ErasedHandle,
1761 ) -> Option<&mut dyn AbstractSceneNode> {
1762 self.pool
1763 .try_borrow_mut(handle.into())
1764 .map(|n| n as &mut dyn AbstractSceneNode)
1765 }
1766}
1767
1768impl BaseSceneGraph for Graph {
1769 type Prefab = Model;
1770 type NodeContainer = NodeContainer;
1771 type Node = Node;
1772
1773 fn summary(&self) -> String {
1775 let mut result = String::new();
1776 self.recursive_summary(0, self.root, &mut result);
1777 result
1778 }
1779
1780 #[inline]
1781 fn actual_type_id(&self, handle: Handle<Self::Node>) -> Option<TypeId> {
1782 self.pool
1783 .try_borrow(handle)
1784 .map(|n| NodeAsAny::as_any(n.0.deref()).type_id())
1785 }
1786
1787 #[inline]
1788 fn root(&self) -> Handle<Self::Node> {
1789 self.root
1790 }
1791
1792 #[inline]
1793 fn set_root(&mut self, root: Handle<Self::Node>) {
1794 self.root = root;
1795 }
1796
1797 #[inline]
1798 fn is_valid_handle(&self, handle: Handle<Self::Node>) -> bool {
1799 self.pool.is_valid_handle(handle)
1800 }
1801
1802 #[inline]
1803 fn add_node(&mut self, mut node: Self::Node) -> Handle<Self::Node> {
1804 let children = node.children.clone();
1805 node.children.clear();
1806 let script_count = node.scripts.len();
1807 let handle = self.pool.spawn(node);
1808
1809 if self.root.is_none() {
1810 self.root = handle;
1811 } else {
1812 self.link_nodes(handle, self.root);
1813 }
1814
1815 for child in children {
1816 self.link_nodes(child, handle);
1817 }
1818
1819 self.event_broadcaster.broadcast(GraphEvent::Added(handle));
1820 for i in 0..script_count {
1821 self.script_message_sender
1822 .send(NodeScriptMessage::InitializeScript {
1823 handle,
1824 script_index: i,
1825 })
1826 .unwrap();
1827 }
1828
1829 let script_message_sender = self.script_message_sender.clone();
1830 let message_sender = self.message_sender.clone();
1831 let node = &mut self.pool[handle];
1832 node.on_connected_to_graph(handle, message_sender, script_message_sender);
1833
1834 self.instance_id_map.insert(node.instance_id, handle);
1835
1836 handle
1837 }
1838
1839 #[inline]
1840 fn remove_node(&mut self, node_handle: Handle<Self::Node>) {
1841 self.isolate_node(node_handle);
1842
1843 self.stack.clear();
1844 self.stack.push(node_handle);
1845 while let Some(handle) = self.stack.pop() {
1846 for &child in self.pool[handle].children().iter() {
1847 self.stack.push(child);
1848 }
1849
1850 let mut node = self.pool.free(handle);
1852 self.instance_id_map.remove(&node.instance_id);
1853 node.on_removed_from_graph(self);
1854
1855 self.event_broadcaster
1856 .broadcast(GraphEvent::Removed(handle));
1857 }
1858 }
1859
1860 #[inline]
1861 fn link_nodes(&mut self, child: Handle<Self::Node>, parent: Handle<Self::Node>) {
1862 self.isolate_node(child);
1863 self.pool[child].parent = parent;
1864 self.pool[parent].children.push(child);
1865
1866 self.message_sender
1868 .send(NodeMessage::new(child, NodeMessageKind::TransformChanged))
1869 .unwrap();
1870 }
1871
1872 #[inline]
1873 fn unlink_node(&mut self, node_handle: Handle<Node>) {
1874 self.isolate_node(node_handle);
1875 self.link_nodes(node_handle, self.root);
1876 self.pool[node_handle]
1877 .local_transform_mut()
1878 .set_position(Vector3::default());
1879 }
1880
1881 #[inline]
1882 fn isolate_node(&mut self, node_handle: Handle<Self::Node>) {
1883 let parent_handle = std::mem::replace(&mut self.pool[node_handle].parent, Handle::NONE);
1885
1886 if let Some(parent) = self.pool.try_borrow_mut(parent_handle) {
1888 if let Some(i) = parent.children().iter().position(|h| *h == node_handle) {
1889 parent.children.remove(i);
1890 }
1891 }
1892
1893 let (ticket, mut node) = self.pool.take_reserve(node_handle);
1894 node.on_unlink(self);
1895 self.pool.put_back(ticket, node);
1896 }
1897
1898 #[inline]
1899 fn try_get_node(&self, handle: Handle<Self::Node>) -> Option<&Self::Node> {
1900 self.pool.try_borrow(handle)
1901 }
1902
1903 #[inline]
1904 fn try_get_node_mut(&mut self, handle: Handle<Self::Node>) -> Option<&mut Self::Node> {
1905 self.pool.try_borrow_mut(handle)
1906 }
1907
1908 fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Option<Vec<TypeId>> {
1909 self.pool
1910 .try_borrow(handle)
1911 .map(|n| Box::deref(&n.0).query_derived_types().to_vec())
1912 }
1913
1914 fn actual_type_name(&self, handle: Handle<Self::Node>) -> Option<&'static str> {
1915 self.pool
1916 .try_borrow(handle)
1917 .map(|n| n.0.deref().type_name())
1918 }
1919}
1920
1921impl SceneGraph for Graph {
1922 type ObjectType = Node;
1923 #[inline]
1924 fn pair_iter(&self) -> impl Iterator<Item = (Handle<Self::Node>, &Self::Node)> {
1925 self.pool.pair_iter()
1926 }
1927
1928 #[inline]
1929 fn linear_iter(&self) -> impl Iterator<Item = &Self::Node> {
1930 self.pool.iter()
1931 }
1932
1933 #[inline]
1934 fn linear_iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Node> {
1935 self.pool.iter_mut()
1936 }
1937
1938 fn try_get<U: ObjectOrVariant<Node>>(&self, handle: Handle<U>) -> Option<&U> {
1939 self.pool.try_get(handle)
1940 }
1941
1942 fn try_get_mut<U: ObjectOrVariant<Node>>(&mut self, handle: Handle<U>) -> Option<&mut U> {
1943 self.pool.try_get_mut(handle)
1944 }
1945}
1946
1947#[cfg(test)]
1948mod test {
1949 use crate::scene::rigidbody::{RigidBody, RigidBodyBuilder};
1950 use crate::{
1951 asset::{io::FsResourceIo, manager::ResourceManager},
1952 core::{
1953 algebra::{Matrix4, Vector3},
1954 futures::executor::block_on,
1955 pool::Handle,
1956 reflect::prelude::*,
1957 type_traits::prelude::*,
1958 visitor::prelude::*,
1959 },
1960 engine::{self, SerializationContext},
1961 graph::{BaseSceneGraph, SceneGraph},
1962 resource::model::{Model, ModelResourceExtension},
1963 scene::{
1964 base::BaseBuilder,
1965 graph::Graph,
1966 mesh::{
1967 surface::{SurfaceBuilder, SurfaceData, SurfaceResource},
1968 MeshBuilder,
1969 },
1970 node::Node,
1971 pivot::{Pivot, PivotBuilder},
1972 transform::TransformBuilder,
1973 Scene, SceneLoader,
1974 },
1975 script::ScriptTrait,
1976 };
1977 use fyrox_core::algebra::Vector2;
1978 use fyrox_core::append_extension;
1979 use fyrox_resource::untyped::ResourceKind;
1980 use std::{fs, path::Path, sync::Arc};
1981
1982 #[derive(Clone, Debug, PartialEq, Reflect, Visit, TypeUuidProvider, ComponentProvider)]
1983 #[type_uuid(id = "722feb80-a10b-4ee0-8cef-5d1473df8457")]
1984 struct MyScript {
1985 foo: String,
1986 bar: f32,
1987 }
1988
1989 impl ScriptTrait for MyScript {}
1990
1991 #[derive(Clone, Debug, PartialEq, Reflect, Visit, TypeUuidProvider, ComponentProvider)]
1992 #[type_uuid(id = "722feb80-a10b-4ee0-8cef-5d1473df8458")]
1993 struct MyOtherScript {
1994 baz: u32,
1995 foobar: Vec<u32>,
1996 }
1997
1998 impl ScriptTrait for MyOtherScript {}
1999
2000 #[test]
2001 fn test_graph_scripts() {
2002 let node = PivotBuilder::new(
2003 BaseBuilder::new()
2004 .with_script(MyScript {
2005 foo: "Stuff".to_string(),
2006 bar: 123.321,
2007 })
2008 .with_script(MyScript {
2009 foo: "OtherStuff".to_string(),
2010 bar: 321.123,
2011 })
2012 .with_script(MyOtherScript {
2013 baz: 321,
2014 foobar: vec![1, 2, 3],
2015 }),
2016 )
2017 .build_node();
2018
2019 let mut graph = Graph::new();
2020
2021 let handle = graph.add_node(node);
2022
2023 assert_eq!(
2024 graph.try_get_script_of::<MyScript>(handle),
2025 Some(&MyScript {
2026 foo: "Stuff".to_string(),
2027 bar: 123.321,
2028 })
2029 );
2030 assert_eq!(
2031 graph.try_get_script_of_mut::<MyScript>(handle),
2032 Some(&mut MyScript {
2033 foo: "Stuff".to_string(),
2034 bar: 123.321,
2035 })
2036 );
2037
2038 let mut immutable_iterator = graph
2039 .try_get_scripts_of::<MyScript>(handle)
2040 .expect("The handle expected to be valid!");
2041 assert_eq!(
2042 immutable_iterator.next(),
2043 Some(&MyScript {
2044 foo: "Stuff".to_string(),
2045 bar: 123.321,
2046 })
2047 );
2048 assert_eq!(
2049 immutable_iterator.next(),
2050 Some(&MyScript {
2051 foo: "OtherStuff".to_string(),
2052 bar: 321.123,
2053 })
2054 );
2055 drop(immutable_iterator);
2056
2057 assert_eq!(
2058 graph.try_get_script_of::<MyOtherScript>(handle),
2059 Some(&MyOtherScript {
2060 baz: 321,
2061 foobar: vec![1, 2, 3],
2062 })
2063 );
2064 assert_eq!(
2065 graph.try_get_script_of_mut::<MyOtherScript>(handle),
2066 Some(&mut MyOtherScript {
2067 baz: 321,
2068 foobar: vec![1, 2, 3],
2069 })
2070 );
2071
2072 let mut mutable_iterator = graph
2073 .try_get_scripts_of_mut::<MyScript>(handle)
2074 .expect("The handle expected to be valid!");
2075 assert_eq!(
2076 mutable_iterator.next(),
2077 Some(&mut MyScript {
2078 foo: "Stuff".to_string(),
2079 bar: 123.321,
2080 })
2081 );
2082 assert_eq!(
2083 mutable_iterator.next(),
2084 Some(&mut MyScript {
2085 foo: "OtherStuff".to_string(),
2086 bar: 321.123,
2087 })
2088 );
2089 }
2090
2091 #[test]
2092 fn graph_init_test() {
2093 let graph = Graph::new();
2094 assert_ne!(graph.root, Handle::NONE);
2095 assert_eq!(graph.pool.alive_count(), 1);
2096 }
2097
2098 #[test]
2099 fn graph_node_test() {
2100 let mut graph = Graph::new();
2101 graph.add_node(Node::new(Pivot::default()));
2102 graph.add_node(Node::new(Pivot::default()));
2103 graph.add_node(Node::new(Pivot::default()));
2104 assert_eq!(graph.pool.alive_count(), 4);
2105 }
2106
2107 #[test]
2108 fn test_graph_search() {
2109 let mut graph = Graph::new();
2110
2111 let b;
2117 let c;
2118 let d;
2119 let a = PivotBuilder::new(BaseBuilder::new().with_name("A").with_children(&[
2120 {
2121 b = PivotBuilder::new(BaseBuilder::new().with_name("B")).build(&mut graph);
2122 b
2123 },
2124 {
2125 c = PivotBuilder::new(BaseBuilder::new().with_name("C").with_children(&[{
2126 d = PivotBuilder::new(BaseBuilder::new().with_name("D")).build(&mut graph);
2127 d
2128 }]))
2129 .build(&mut graph);
2130 c
2131 },
2132 ]))
2133 .build(&mut graph);
2134
2135 assert!(graph.find_by_name(a, "X").is_none());
2137 assert_eq!(graph.find_by_name(a, "A").unwrap().0, a);
2138 assert_eq!(graph.find_by_name(a, "D").unwrap().0, d);
2139
2140 let result = graph
2141 .find_map(a, &mut |n| if n.name() == "D" { Some("D") } else { None })
2142 .unwrap();
2143 assert_eq!(result.0, d);
2144 assert_eq!(result.1, "D");
2145
2146 assert!(graph.find_up_by_name(d, "X").is_none());
2148 assert_eq!(graph.find_up_by_name(d, "D").unwrap().0, d);
2149 assert_eq!(graph.find_up_by_name(d, "A").unwrap().0, a);
2150
2151 let result = graph
2152 .find_up_map(d, &mut |n| if n.name() == "A" { Some("A") } else { None })
2153 .unwrap();
2154 assert_eq!(result.0, a);
2155 assert_eq!(result.1, "A");
2156 }
2157
2158 fn create_scene() -> Scene {
2159 let mut scene = Scene::new();
2160
2161 PivotBuilder::new(BaseBuilder::new().with_name("Pivot")).build(&mut scene.graph);
2162
2163 PivotBuilder::new(BaseBuilder::new().with_name("MeshPivot").with_children(&[{
2164 MeshBuilder::new(
2165 BaseBuilder::new().with_name("Mesh").with_local_transform(
2166 TransformBuilder::new()
2167 .with_local_position(Vector3::new(3.0, 2.0, 1.0))
2168 .build(),
2169 ),
2170 )
2171 .with_surfaces(vec![SurfaceBuilder::new(SurfaceResource::new_ok(
2172 Uuid::new_v4(),
2173 ResourceKind::Embedded,
2174 SurfaceData::make_cone(16, 1.0, 1.0, &Matrix4::identity()),
2175 ))
2176 .build()])
2177 .build(&mut scene.graph)
2178 }]))
2179 .build(&mut scene.graph);
2180
2181 scene
2182 }
2183
2184 fn save_scene(scene: &mut Scene, path: &Path) {
2185 let mut visitor = Visitor::new();
2186 scene.save("Scene", &mut visitor).unwrap();
2187 visitor.save_binary_to_file(path).unwrap();
2188 visitor
2189 .save_ascii_to_file(append_extension(path, "txt"))
2190 .unwrap();
2191 }
2192
2193 fn make_resource_manager(root: &Path) -> ResourceManager {
2194 let resource_manager =
2195 ResourceManager::new(Arc::new(FsResourceIo), Arc::new(Default::default()));
2196 resource_manager
2197 .state()
2198 .resource_registry
2199 .lock()
2200 .set_path(root.join("resources.registry"));
2201 engine::initialize_resource_manager_loaders(
2202 &resource_manager,
2203 Arc::new(SerializationContext::new()),
2204 );
2205 resource_manager.update_or_load_registry();
2206 resource_manager
2207 }
2208
2209 #[test]
2210 fn test_restore_integrity() {
2211 let root = Path::new("test_restore_integrity");
2212
2213 if !root.exists() {
2214 fs::create_dir_all(root).unwrap();
2215 }
2216
2217 let root_asset_path = root.join("root2.rgs");
2218 let derived_asset_path = root.join("derived2.rgs");
2219
2220 {
2222 let mut scene = create_scene();
2223 save_scene(&mut scene, &root_asset_path);
2224 }
2225
2226 {
2228 let resource_manager = make_resource_manager(root);
2229 let root_asset = block_on(resource_manager.request::<Model>(&root_asset_path)).unwrap();
2230
2231 let mut derived = Scene::new();
2232 root_asset.instantiate(&mut derived);
2233 save_scene(&mut derived, &derived_asset_path);
2234 }
2235
2236 {
2238 let resource_manager = make_resource_manager(root);
2239 let mut scene = block_on(
2240 block_on(SceneLoader::from_file(
2241 &root_asset_path,
2242 &FsResourceIo,
2243 Arc::new(SerializationContext::new()),
2244 resource_manager.clone(),
2245 ))
2246 .unwrap()
2247 .0
2248 .finish(),
2249 );
2250
2251 PivotBuilder::new(BaseBuilder::new().with_name("AddedLater")).build(&mut scene.graph);
2253
2254 let mesh = scene.graph.find_by_name_from_root("Mesh").unwrap().0;
2256 let pivot = PivotBuilder::new(BaseBuilder::new().with_name("NewChildOfMesh"))
2257 .build(&mut scene.graph);
2258 scene.graph.link_nodes(pivot, mesh);
2259
2260 let existing_pivot = scene.graph.find_by_name_from_root("Pivot").unwrap().0;
2262 scene.graph.remove_node(existing_pivot);
2263
2264 save_scene(&mut scene, &root_asset_path);
2266 }
2267
2268 {
2270 let resource_manager = make_resource_manager(root);
2271 let derived_asset =
2272 block_on(resource_manager.request::<Model>(derived_asset_path)).unwrap();
2273
2274 let derived_data = derived_asset.data_ref();
2275 let derived_scene = derived_data.get_scene();
2276
2277 assert_eq!(
2279 derived_scene
2280 .graph
2281 .find_by_name_from_root("Pivot")
2282 .map(|(h, _)| h),
2283 None
2284 );
2285
2286 let mesh_pivot = derived_scene
2287 .graph
2288 .find_by_name_from_root("MeshPivot")
2289 .expect("Missing MeshPivot")
2290 .0;
2291 let mesh = derived_scene
2292 .graph
2293 .find_by_name(mesh_pivot, "Mesh")
2294 .expect("Missing Mesh")
2295 .0;
2296 derived_scene
2297 .graph
2298 .find_by_name_from_root("AddedLater")
2299 .expect("Missing AddedLater");
2300 derived_scene
2301 .graph
2302 .find_by_name(mesh, "NewChildOfMesh")
2303 .expect("Missing NewChildOfMesh");
2304 }
2305 }
2306
2307 #[test]
2308 fn test_global_scale() {
2309 let mut graph = Graph::new();
2310
2311 let b;
2312 let c;
2313 let a = PivotBuilder::new(
2314 BaseBuilder::new()
2315 .with_local_transform(
2316 TransformBuilder::new()
2317 .with_local_scale(Vector3::new(1.0, 1.0, 2.0))
2318 .build(),
2319 )
2320 .with_children(&[{
2321 b = PivotBuilder::new(
2322 BaseBuilder::new()
2323 .with_local_transform(
2324 TransformBuilder::new()
2325 .with_local_scale(Vector3::new(3.0, 2.0, 1.0))
2326 .build(),
2327 )
2328 .with_children(&[{
2329 c = PivotBuilder::new(
2330 BaseBuilder::new().with_local_transform(
2331 TransformBuilder::new()
2332 .with_local_scale(Vector3::new(1.0, 2.0, 3.0))
2333 .build(),
2334 ),
2335 )
2336 .build(&mut graph);
2337 c
2338 }]),
2339 )
2340 .build(&mut graph);
2341 b
2342 }]),
2343 )
2344 .build(&mut graph);
2345
2346 assert_eq!(graph.global_scale(a), Vector3::new(1.0, 1.0, 2.0));
2347 assert_eq!(graph.global_scale(b), Vector3::new(3.0, 2.0, 2.0));
2348 assert_eq!(graph.global_scale(c), Vector3::new(3.0, 4.0, 6.0));
2349 }
2350
2351 #[test]
2352 fn test_hierarchy_changes_propagation() {
2353 let mut graph = Graph::new();
2354
2355 let b;
2356 let c;
2357 let d;
2358 let a = PivotBuilder::new(
2359 BaseBuilder::new()
2360 .with_local_transform(
2361 TransformBuilder::new()
2362 .with_local_position(Vector3::new(1.0, 0.0, 0.0))
2363 .build(),
2364 )
2365 .with_children(&[
2366 {
2367 b = PivotBuilder::new(
2368 BaseBuilder::new()
2369 .with_visibility(false)
2370 .with_enabled(false)
2371 .with_local_transform(
2372 TransformBuilder::new()
2373 .with_local_position(Vector3::new(0.0, 1.0, 0.0))
2374 .build(),
2375 )
2376 .with_children(&[{
2377 c = PivotBuilder::new(
2378 BaseBuilder::new().with_local_transform(
2379 TransformBuilder::new()
2380 .with_local_position(Vector3::new(0.0, 0.0, 1.0))
2381 .build(),
2382 ),
2383 )
2384 .build(&mut graph);
2385 c
2386 }]),
2387 )
2388 .build(&mut graph);
2389 b
2390 },
2391 {
2392 d = PivotBuilder::new(
2393 BaseBuilder::new().with_local_transform(
2394 TransformBuilder::new()
2395 .with_local_position(Vector3::new(1.0, 1.0, 1.0))
2396 .build(),
2397 ),
2398 )
2399 .build(&mut graph);
2400 d
2401 },
2402 ]),
2403 )
2404 .build(&mut graph);
2405
2406 graph.update(Vector2::new(1.0, 1.0), 1.0 / 60.0, Default::default());
2407
2408 assert_eq!(graph[a].global_position(), Vector3::new(1.0, 0.0, 0.0));
2409 assert_eq!(graph[b].global_position(), Vector3::new(1.0, 1.0, 0.0));
2410 assert_eq!(graph[c].global_position(), Vector3::new(1.0, 1.0, 1.0));
2411 assert_eq!(graph[d].global_position(), Vector3::new(2.0, 1.0, 1.0));
2412
2413 assert!(graph[a].global_visibility());
2414 assert!(!graph[b].global_visibility());
2415 assert!(!graph[c].global_visibility());
2416 assert!(graph[d].global_visibility());
2417
2418 assert!(graph[a].is_globally_enabled());
2419 assert!(!graph[b].is_globally_enabled());
2420 assert!(!graph[c].is_globally_enabled());
2421 assert!(graph[d].is_globally_enabled());
2422
2423 graph[b]
2425 .local_transform_mut()
2426 .set_position(Vector3::new(0.0, 2.0, 0.0));
2427 graph[a].set_enabled(false);
2428 graph[b].set_visibility(true);
2429
2430 graph.update(Vector2::new(1.0, 1.0), 1.0 / 60.0, Default::default());
2431
2432 assert_eq!(graph[a].global_position(), Vector3::new(1.0, 0.0, 0.0));
2433 assert_eq!(graph[b].global_position(), Vector3::new(1.0, 2.0, 0.0));
2434 assert_eq!(graph[c].global_position(), Vector3::new(1.0, 2.0, 1.0));
2435 assert_eq!(graph[d].global_position(), Vector3::new(2.0, 1.0, 1.0));
2436
2437 assert!(graph[a].global_visibility());
2438 assert!(graph[b].global_visibility());
2439 assert!(graph[c].global_visibility());
2440 assert!(graph[d].global_visibility());
2441
2442 assert!(!graph.pool.try_get(a).unwrap().is_globally_enabled());
2443 assert!(!graph[b].is_globally_enabled());
2444 assert!(!graph[c].is_globally_enabled());
2445 assert!(!graph[d].is_globally_enabled());
2446 }
2447
2448 #[test]
2449 fn test_typed_borrow() {
2450 let mut graph = Graph::new();
2451 let pivot = PivotBuilder::new(BaseBuilder::new()).build(&mut graph);
2452 let rigid_body = RigidBodyBuilder::new(BaseBuilder::new()).build(&mut graph);
2453
2454 assert!(graph.pool.try_get(pivot).is_some());
2455 assert!(graph.pool.try_get(pivot.transmute::<Pivot>()).is_some());
2456 assert!(graph.pool.try_get(pivot.transmute::<RigidBody>()).is_none());
2457
2458 assert!(graph.pool.try_get(rigid_body).is_some());
2459 assert!(graph
2460 .pool
2461 .try_get(rigid_body.transmute::<RigidBody>())
2462 .is_some());
2463 assert!(graph
2464 .pool
2465 .try_get(rigid_body.transmute::<Pivot>())
2466 .is_none());
2467 }
2468}