Skip to main content

fyrox_impl/scene/
base.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Contains all structures and methods to create and manage base scene graph nodes.
22//!
23//! For more info see [`Base`]
24
25use super::collider::BitMask;
26use crate::{
27    core::{
28        algebra::{Matrix4, Vector3},
29        log::Log,
30        math::{aabb::AxisAlignedBoundingBox, Matrix4Ext},
31        pool::{ErasedHandle, Handle},
32        reflect::prelude::*,
33        type_traits::prelude::*,
34        variable::InheritableVariable,
35        visitor::{Visit, VisitResult, Visitor},
36        ImmutableString,
37    },
38    engine::SerializationContext,
39    graph::SceneGraph,
40    resource::model::ModelResource,
41    scene::{node::Node, transform::Transform},
42    script::{Script, ScriptTrait},
43};
44use fyrox_core::algebra::UnitQuaternion;
45use fyrox_core::pool::ObjectOrVariant;
46use fyrox_core::visitor::error::VisitError;
47use serde::{Deserialize, Serialize};
48use std::{
49    any::Any,
50    cell::Cell,
51    ops::{Deref, DerefMut},
52    sync::mpsc::Sender,
53};
54use strum_macros::{AsRefStr, EnumString, VariantNames};
55
56/// Level of detail is a collection of objects for given normalized distance range.
57/// Objects will be rendered **only** if they're in specified range.
58/// Normalized distance is a distance in (0; 1) range where 0 - closest to camera,
59/// 1 - farthest. Real distance can be obtained by multiplying normalized distance
60/// with z_far of current projection matrix.
61#[derive(Debug, Default, Clone, Visit, Reflect, PartialEq, TypeUuidProvider)]
62#[type_uuid(id = "576b31a2-2b39-4c79-95dd-26aeaf381d8b")]
63pub struct LevelOfDetail {
64    /// Beginning of the range in which the level will be visible. It is expressed in normalized
65    /// coordinates: where 0.0 - closest to camera, 1.0 - farthest from camera.
66    begin: f32,
67    /// End of the range in which the level will be visible. It is expressed in normalized coordinates:
68    /// where 0.0 - closest to camera, 1.0 - farthest from camera.
69    end: f32,
70    /// List of objects, where each object represents level of detail of parent's LOD group.
71    pub objects: Vec<Handle<Node>>,
72}
73
74impl LevelOfDetail {
75    /// Creates new level of detail.
76    pub fn new(begin: f32, end: f32, objects: Vec<Handle<Node>>) -> Self {
77        for object in objects.iter() {
78            // Invalid handles are not allowed.
79            assert!(object.is_some());
80        }
81        let begin = begin.min(end);
82        let end = end.max(begin);
83        Self {
84            begin: begin.clamp(0.0, 1.0),
85            end: end.clamp(0.0, 1.0),
86            objects,
87        }
88    }
89
90    /// Sets new starting point in distance range. Input value will be clamped in
91    /// (0; 1) range.
92    pub fn set_begin(&mut self, percent: f32) {
93        self.begin = percent.clamp(0.0, 1.0);
94        if self.begin > self.end {
95            std::mem::swap(&mut self.begin, &mut self.end);
96        }
97    }
98
99    /// Returns starting point of the range.
100    pub fn begin(&self) -> f32 {
101        self.begin
102    }
103
104    /// Sets new end point in distance range. Input value will be clamped in
105    /// (0; 1) range.
106    pub fn set_end(&mut self, percent: f32) {
107        self.end = percent.clamp(0.0, 1.0);
108        if self.end < self.begin {
109            std::mem::swap(&mut self.begin, &mut self.end);
110        }
111    }
112
113    /// Returns end point of the range.
114    pub fn end(&self) -> f32 {
115        self.end
116    }
117}
118
119/// LOD (Level-Of-Detail) group is a set of cascades (levels), where each cascade takes specific
120/// distance range. Each cascade contains list of objects that should or shouldn't be rendered
121/// if distance satisfy cascade range. LOD may significantly improve performance if your scene
122/// contains lots of high poly objects and objects may be far away from camera. Distant objects
123/// in this case will be rendered with lower details freeing precious GPU resources for other
124/// useful tasks.
125///
126/// Lod group must contain non-overlapping cascades, each cascade with its own set of objects
127/// that belongs to level of detail. Engine does not care if you create overlapping cascades,
128/// it is your responsibility to create non-overlapping cascades.
129#[derive(Debug, Default, Clone, Visit, Reflect, PartialEq, TypeUuidProvider)]
130#[type_uuid(id = "8e7b18b1-c1e0-47d7-b952-4394c1d049e5")]
131pub struct LodGroup {
132    /// Set of cascades.
133    pub levels: Vec<LevelOfDetail>,
134}
135
136/// A property value.
137#[derive(
138    Debug, Visit, Reflect, PartialEq, Clone, AsRefStr, EnumString, VariantNames, TypeUuidProvider,
139)]
140#[type_uuid(id = "cce94b60-a57e-48ba-b6f4-e5e84788f7f8")]
141pub enum PropertyValue {
142    /// A node handle.
143    ///
144    /// # Important notes
145    ///
146    /// The value of the property will be remapped when owning node is cloned, this means that the
147    /// handle will always be correct.
148    NodeHandle(Handle<Node>),
149    /// An arbitrary, type-erased handle.
150    ///
151    /// # Important notes
152    ///
153    /// The value of the property will **not** be remapped when owning node is cloned, this means
154    /// that the handle correctness is not guaranteed on copy.
155    Handle(ErasedHandle),
156    /// A string value.
157    String(String),
158    /// A 64-bit signed integer value.
159    I64(i64),
160    /// A 64-bit unsigned integer value.
161    U64(u64),
162    /// A 32-bit signed integer value.
163    I32(i32),
164    /// A 32-bit unsigned integer value.
165    U32(u32),
166    /// A 16-bit signed integer value.
167    I16(i16),
168    /// A 16-bit unsigned integer value.
169    U16(u16),
170    /// A 8-bit signed integer value.
171    I8(i8),
172    /// A 8-bit unsigned integer value.
173    U8(u8),
174    /// A 32-bit floating point value.
175    F32(f32),
176    /// A 64-bit floating point value.
177    F64(f64),
178}
179
180impl Default for PropertyValue {
181    fn default() -> Self {
182        Self::I8(0)
183    }
184}
185
186/// A custom property.
187#[derive(Debug, Visit, Reflect, Default, Clone, PartialEq, TypeUuidProvider)]
188#[type_uuid(id = "fc87fd21-a5e6-40d5-a79d-19f96b25d6c9")]
189pub struct Property {
190    /// Name of the property.
191    pub name: String,
192    /// A value of the property.
193    pub value: PropertyValue,
194}
195
196/// A script message from scene node. It is used for deferred initialization/deinitialization.
197pub enum NodeScriptMessage {
198    /// A script was set to a node and needs to be initialized.
199    InitializeScript {
200        /// Node handle.
201        handle: Handle<Node>,
202        /// Index of the script.
203        script_index: usize,
204    },
205    /// A node script must be destroyed. It can happen if the script was replaced with some other
206    /// or a node was destroyed.
207    DestroyScript {
208        /// Script instance.
209        script: Script,
210        /// Node handle.
211        handle: Handle<Node>,
212        /// Index of the script.
213        script_index: usize,
214    },
215}
216
217/// Unique id of a node, that could be used as a reliable "index" of the node. This id is mostly
218/// useful for network games.
219#[derive(
220    Clone,
221    Copy,
222    Eq,
223    Hash,
224    Ord,
225    PartialEq,
226    PartialOrd,
227    Default,
228    Debug,
229    Reflect,
230    Serialize,
231    Deserialize,
232)]
233#[repr(transparent)]
234pub struct SceneNodeId(pub Uuid);
235
236impl Visit for SceneNodeId {
237    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
238        self.0.visit(name, visitor)
239    }
240}
241
242/// A script container record.
243#[derive(Clone, Reflect, Debug, Default, TypeUuidProvider)]
244#[type_uuid(id = "51bc577b-5a50-4a97-9b31-eda2f3d46c9d")]
245pub struct ScriptRecord {
246    // Script is wrapped into `Option` to be able to do take-return trick to bypass borrow checker
247    // issues.
248    pub(crate) script: Option<Script>,
249    #[reflect(hidden)]
250    pub(crate) should_be_deleted: bool,
251}
252
253impl ScriptRecord {
254    pub(crate) fn new(script: Script) -> Self {
255        Self {
256            script: Some(script),
257            should_be_deleted: false,
258        }
259    }
260}
261
262impl Deref for ScriptRecord {
263    type Target = Option<Script>;
264
265    fn deref(&self) -> &Self::Target {
266        &self.script
267    }
268}
269
270impl DerefMut for ScriptRecord {
271    fn deref_mut(&mut self) -> &mut Self::Target {
272        &mut self.script
273    }
274}
275
276impl Visit for ScriptRecord {
277    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
278        visit_opt_script(name, &mut self.script, visitor)
279    }
280}
281
282#[allow(clippy::enum_variant_names)] // STFU
283#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
284pub(crate) enum NodeMessageKind {
285    TransformChanged,
286    VisibilityChanged,
287    EnabledFlagChanged,
288}
289
290#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
291pub(crate) struct NodeMessage {
292    pub node: Handle<Node>,
293    pub kind: NodeMessageKind,
294}
295
296impl NodeMessage {
297    pub fn new(node: Handle<Node>, kind: NodeMessageKind) -> Self {
298        Self { node, kind }
299    }
300}
301
302#[derive(Clone, Debug)]
303struct TrackedProperty<T> {
304    property: T,
305    node_message_kind: NodeMessageKind,
306    node_handle: Handle<Node>,
307    sender: Option<Sender<NodeMessage>>,
308}
309
310impl<T> TrackedProperty<T> {
311    fn unbound(property: T, kind: NodeMessageKind) -> Self {
312        Self {
313            property,
314            node_message_kind: kind,
315            node_handle: Default::default(),
316            sender: None,
317        }
318    }
319
320    fn set_message_data(&mut self, sender: Sender<NodeMessage>, node_handle: Handle<Node>) {
321        self.sender = Some(sender);
322        self.node_handle = node_handle;
323    }
324}
325
326impl<T: Visit> Visit for TrackedProperty<T> {
327    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
328        self.property.visit(name, visitor)
329    }
330}
331
332impl<T> Deref for TrackedProperty<T> {
333    type Target = T;
334
335    fn deref(&self) -> &Self::Target {
336        &self.property
337    }
338}
339
340impl<T> DerefMut for TrackedProperty<T> {
341    fn deref_mut(&mut self) -> &mut Self::Target {
342        if let Some(sender) = self.sender.as_ref() {
343            Log::verify(sender.send(NodeMessage {
344                node: self.node_handle,
345                kind: self.node_message_kind,
346            }))
347        }
348        &mut self.property
349    }
350}
351
352/// Base scene graph node is a simplest possible node, it is used to build more complex ones using composition.
353/// It contains all fundamental properties for each scene graph nodes, like local and global transforms, name,
354/// lifetime, etc. Base node is a building block for all complex node hierarchies - it contains list of children
355/// and handle to parent node.
356///
357/// # Example
358///
359/// ```
360/// # use fyrox_impl::scene::base::BaseBuilder;
361/// # use fyrox_impl::scene::graph::Graph;
362/// # use fyrox_impl::scene::node::Node;
363/// # use fyrox_impl::core::pool::Handle;
364/// # use fyrox_impl::scene::pivot::{Pivot, PivotBuilder};
365///
366/// fn create_pivot_node(graph: &mut Graph) -> Handle<Pivot> {
367///     PivotBuilder::new(BaseBuilder::new()
368///         .with_name("BaseNode"))
369///         .build(graph)
370/// }
371/// ```
372#[derive(Debug, Reflect, Clone)]
373pub struct Base {
374    #[reflect(hidden)]
375    self_handle: Handle<Node>,
376
377    #[reflect(hidden)]
378    script_message_sender: Option<Sender<NodeScriptMessage>>,
379
380    #[reflect(hidden)]
381    message_sender: Option<Sender<NodeMessage>>,
382
383    // Name is not inheritable, because property inheritance works bad with external 3D models.
384    // They use names to search "original" nodes.
385    #[reflect(setter = "set_name_internal")]
386    pub(crate) name: ImmutableString,
387
388    #[reflect(deref)]
389    local_transform: TrackedProperty<Transform>,
390
391    #[reflect(deref)]
392    visibility: TrackedProperty<InheritableVariable<bool>>,
393
394    #[reflect(deref)]
395    enabled: TrackedProperty<InheritableVariable<bool>>,
396
397    /// Control whether this node should be rendered. A node should be rendered only if its render mask shares
398    /// some set bits in common with the render mask of the camera.
399    pub render_mask: InheritableVariable<BitMask>,
400
401    /// Maximum amount of Some(time) that node will \"live\" or None if the node has unlimited lifetime.
402    pub(crate) lifetime: InheritableVariable<Option<f32>>,
403
404    #[reflect(setter = "set_lod_group")]
405    lod_group: InheritableVariable<Option<LodGroup>>,
406
407    #[reflect(setter = "set_tag")]
408    tag: InheritableVariable<String>,
409
410    #[reflect(setter = "set_cast_shadows")]
411    cast_shadows: InheritableVariable<bool>,
412
413    /// A set of custom properties that can hold almost any data. It can be used to set additional
414    /// properties to scene nodes.
415    #[reflect(setter = "set_properties")]
416    pub properties: InheritableVariable<Vec<Property>>,
417
418    #[reflect(setter = "set_frustum_culling")]
419    frustum_culling: InheritableVariable<bool>,
420
421    /// When `true` it means that this node is instance of `resource`.
422    /// More precisely - this node is root of whole descendant nodes
423    /// hierarchy which was instantiated from resource.
424    #[reflect(read_only)]
425    pub(crate) is_resource_instance_root: bool,
426
427    #[reflect(read_only)]
428    pub(crate) global_visibility: Cell<bool>,
429
430    #[reflect(hidden)]
431    pub(crate) parent: Handle<Node>,
432
433    #[reflect(hidden)]
434    pub(crate) children: Vec<Handle<Node>>,
435
436    #[reflect(read_only)]
437    pub(crate) global_transform: Cell<Matrix4<f32>>,
438
439    // Bone-specific matrix. Non-serializable.
440    #[reflect(hidden)]
441    pub(crate) inv_bind_pose_transform: Matrix4<f32>,
442
443    // A resource from which this node was instantiated from, can work in pair
444    // with `original` handle to get corresponding node from resource.
445    #[reflect(read_only)]
446    pub(crate) resource: Option<ModelResource>,
447
448    // Handle to node in scene of model resource from which this node
449    // was instantiated from.
450    #[reflect(read_only)]
451    #[reflect(hidden)]
452    pub(crate) original_handle_in_resource: Handle<Node>,
453
454    /// Unique id of a node, that could be used as a reliable "index" of the node. This id is mostly
455    /// useful for network games. Keep in mind, that this id **will** be randomized in case if you're
456    /// instantiating a prefab. In other words, all instances of a prefab will have unique instance
457    /// id.
458    pub(crate) instance_id: SceneNodeId,
459
460    // Scripts of the scene node.
461    //
462    // # Important notes
463    //
464    // WARNING: Setting a new script via reflection will break normal script destruction process!
465    // Use it at your own risk only when you're completely sure what you are doing.
466    pub(crate) scripts: Vec<ScriptRecord>,
467
468    #[reflect(read_only)]
469    pub(crate) global_enabled: Cell<bool>,
470}
471
472impl Drop for Base {
473    fn drop(&mut self) {
474        self.remove_all_scripts();
475    }
476}
477
478impl Base {
479    /// Returns handle of the node. A node has valid handle only after it was inserted in a graph!
480    #[inline]
481    pub fn handle(&self) -> Handle<Node> {
482        self.self_handle
483    }
484
485    /// Sets name of node. Can be useful to mark a node to be able to find it later on.
486    #[inline]
487    pub fn set_name<N: AsRef<str>>(&mut self, name: N) {
488        self.set_name_internal(ImmutableString::new(name));
489    }
490
491    fn set_name_internal(&mut self, name: ImmutableString) -> ImmutableString {
492        std::mem::replace(&mut self.name, name)
493    }
494
495    /// Returns name of node.
496    #[inline]
497    pub fn name(&self) -> &str {
498        self.name.as_str()
499    }
500
501    /// Returns owned name of node.
502    #[inline]
503    pub fn name_owned(&self) -> String {
504        self.name.to_mutable()
505    }
506
507    pub(crate) fn on_connected_to_graph(
508        &mut self,
509        self_handle: Handle<Node>,
510        message_sender: Sender<NodeMessage>,
511        script_message_sender: Sender<NodeScriptMessage>,
512    ) {
513        self.self_handle = self_handle;
514        self.message_sender = Some(message_sender.clone());
515        self.script_message_sender = Some(script_message_sender);
516        self.local_transform
517            .set_message_data(message_sender.clone(), self_handle);
518        self.visibility
519            .set_message_data(message_sender.clone(), self_handle);
520        self.enabled.set_message_data(message_sender, self_handle);
521        // Kick off initial hierarchical property propagation.
522        self.notify(self.self_handle, NodeMessageKind::TransformChanged);
523        self.notify(self.self_handle, NodeMessageKind::VisibilityChanged);
524        self.notify(self.self_handle, NodeMessageKind::EnabledFlagChanged);
525    }
526
527    fn notify(&self, node: Handle<Node>, kind: NodeMessageKind) {
528        let Some(sender) = self.message_sender.as_ref() else {
529            return;
530        };
531        Log::verify(sender.send(NodeMessage::new(node, kind)));
532    }
533
534    /// Returns shared reference to local transform of a node, can be used to fetch
535    /// some local spatial properties, such as position, rotation, scale, etc.
536    #[inline]
537    pub fn local_transform(&self) -> &Transform {
538        &self.local_transform
539    }
540
541    /// Returns mutable reference to local transform of a node, can be used to set some local spatial
542    /// properties, such as position, rotation, scale, etc. To set global position and rotation, use
543    /// [`super::Graph::set_global_position`] and [`super::Graph::set_global_rotation`] methods respectively.
544    #[inline]
545    pub fn local_transform_mut(&mut self) -> &mut Transform {
546        &mut self.local_transform
547    }
548
549    /// Sets new local transform of a node. If you need to modify existing local transformation,
550    /// use [`Self::local_transform_mut`].
551    #[inline]
552    pub fn set_local_transform(&mut self, transform: Transform) {
553        self.local_transform.property = transform;
554        self.notify(self.self_handle, NodeMessageKind::TransformChanged);
555    }
556
557    /// Sets the new position of the node in the parent's node coordinate system.
558    #[inline]
559    pub fn set_position(&mut self, position: Vector3<f32>) {
560        self.local_transform_mut().set_position(position);
561    }
562
563    /// Sets the new position of the node in the parent's node coordinate system.
564    #[inline]
565    pub fn set_position_xyz(&mut self, x: f32, y: f32, z: f32) {
566        self.set_position(Vector3::new(x, y, z))
567    }
568
569    /// Sets the new rotation of the node in the parent's node coordinate system.
570    #[inline]
571    pub fn set_rotation(&mut self, rotation: UnitQuaternion<f32>) {
572        self.local_transform_mut().set_rotation(rotation);
573    }
574
575    /// Sets the new rotation of the node in the parent's node coordinate system.
576    #[inline]
577    pub fn set_rotation_angles(&mut self, roll: f32, pitch: f32, yaw: f32) {
578        self.set_rotation(UnitQuaternion::from_euler_angles(roll, pitch, yaw))
579    }
580
581    /// Sets the new rotation of the node around X axis in the parent's node coordinate system.
582    #[inline]
583    pub fn set_rotation_x(&mut self, angle: f32) {
584        self.set_rotation(UnitQuaternion::from_axis_angle(&Vector3::x_axis(), angle))
585    }
586
587    /// Sets the new rotation of the node around Y axis in the parent's node coordinate system.
588    #[inline]
589    pub fn set_rotation_y(&mut self, angle: f32) {
590        self.set_rotation(UnitQuaternion::from_axis_angle(&Vector3::y_axis(), angle))
591    }
592
593    /// Sets the new rotation of the node around Z axis in the parent's node coordinate system.
594    #[inline]
595    pub fn set_rotation_z(&mut self, angle: f32) {
596        self.set_rotation(UnitQuaternion::from_axis_angle(&Vector3::z_axis(), angle))
597    }
598
599    /// Sets the new scale of the node in the parent's node coordinate system.
600    #[inline]
601    pub fn set_scale(&mut self, scale: Vector3<f32>) {
602        self.local_transform_mut().set_scale(scale);
603    }
604
605    /// Sets the new scale of the node in the parent's node coordinate system.
606    #[inline]
607    pub fn set_scale_xyz(&mut self, x: f32, y: f32, z: f32) {
608        self.set_scale(Vector3::new(x, y, z));
609    }
610
611    /// Sets the new scale of the node for all axes at once in the parent's node coordinate system.
612    #[inline]
613    pub fn set_uniform_scale(&mut self, scale: f32) {
614        self.set_scale(Vector3::repeat(scale))
615    }
616
617    /// Tries to find properties by the name. The method returns an iterator because it possible
618    /// to have multiple properties with the same name.
619    #[inline]
620    pub fn find_properties_ref<'a>(&'a self, name: &'a str) -> impl Iterator<Item = &'a Property> {
621        self.properties.iter().filter(move |p| p.name == name)
622    }
623
624    /// Tries to find a first property with the given name.
625    #[inline]
626    pub fn find_first_property_ref(&self, name: &str) -> Option<&Property> {
627        self.properties.iter().find(|p| p.name == name)
628    }
629
630    /// Sets a new set of properties of the node.
631    #[inline]
632    pub fn set_properties(&mut self, properties: Vec<Property>) -> Vec<Property> {
633        std::mem::replace(
634            self.properties.get_value_mut_and_mark_modified(),
635            properties,
636        )
637    }
638
639    /// Sets lifetime of node in seconds, lifetime is useful for temporary objects.
640    /// Example - you firing a gun, it produces two particle systems for each shot:
641    /// one for gunpowder fumes and one when bullet hits some surface. These particle
642    /// systems won't last very long - usually they will disappear in 1-2 seconds
643    /// but nodes will still be in scene consuming precious CPU clocks. This is where
644    /// lifetimes become handy - you just set appropriate lifetime for a particle
645    /// system node and it will be removed from scene when time will end. This is
646    /// efficient algorithm because scene holds every object in pool and allocation
647    /// or deallocation of node takes very little amount of time.
648    #[inline]
649    pub fn set_lifetime(&mut self, time_seconds: Option<f32>) -> &mut Self {
650        self.lifetime.set_value_and_mark_modified(time_seconds);
651        self
652    }
653
654    /// Returns current lifetime of a node. Will be None if node has undefined lifetime.
655    /// For more info about lifetimes see [`set_lifetime`](Self::set_lifetime).
656    #[inline]
657    pub fn lifetime(&self) -> Option<f32> {
658        *self.lifetime
659    }
660
661    /// Returns handle of parent node.
662    #[inline]
663    pub fn parent(&self) -> Handle<Node> {
664        self.parent
665    }
666
667    /// Returns slice of handles to children nodes. This can be used, for example, to
668    /// traverse tree starting from some node.
669    #[inline]
670    pub fn children(&self) -> &[Handle<Node>] {
671        self.children.as_slice()
672    }
673
674    /// Returns global transform matrix, such matrix contains combined transformation
675    /// of transforms of parent nodes. This is the final matrix that describes real
676    /// location of object in the world.
677    #[inline]
678    pub fn global_transform(&self) -> Matrix4<f32> {
679        self.global_transform.get()
680    }
681
682    /// Calculates global transform of the node, but discards scaling part of it.
683    #[inline]
684    pub fn global_transform_without_scaling(&self) -> Matrix4<f32> {
685        const EPSILON: f32 = 10.0 * f32::EPSILON;
686        let basis = self.global_transform().basis();
687        let rotation = UnitQuaternion::from_matrix_eps(&basis, EPSILON, 16, Default::default());
688        Matrix4::new_translation(&self.global_position()) * rotation.to_homogeneous()
689    }
690
691    /// Returns inverse of bind pose matrix. Bind pose matrix - is special matrix
692    /// for bone nodes, it stores initial transform of bone node at the moment
693    /// of "binding" vertices to bones.
694    #[inline]
695    pub fn inv_bind_pose_transform(&self) -> Matrix4<f32> {
696        self.inv_bind_pose_transform
697    }
698
699    /// Returns true if this node is model resource instance root node.
700    #[inline]
701    pub fn is_resource_instance_root(&self) -> bool {
702        self.is_resource_instance_root
703    }
704
705    /// Returns resource from which this node was instantiated from.
706    #[inline]
707    pub fn resource(&self) -> Option<ModelResource> {
708        self.resource.clone()
709    }
710
711    /// Sets local visibility of a node.
712    #[inline]
713    pub fn set_visibility(&mut self, visibility: bool) -> bool {
714        self.visibility.set_value_and_mark_modified(visibility)
715    }
716
717    /// Returns local visibility of a node.
718    #[inline]
719    pub fn visibility(&self) -> bool {
720        *self.visibility.property
721    }
722
723    /// Returns current **local-space** bounding box. Keep in mind that this value is just
724    /// a placeholder, because there is not information to calculate actual bounding box.
725    #[inline]
726    pub fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
727        AxisAlignedBoundingBox::unit()
728    }
729
730    /// Returns current **world-space** bounding box.
731    #[inline]
732    pub fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
733        self.local_bounding_box()
734            .transform(&self.global_transform())
735    }
736
737    /// Returns combined visibility of an node. This is the final visibility of a node. Global visibility calculated
738    /// using visibility of all parent nodes until root one, so if some parent node upper on tree is invisible then
739    /// all its children will be invisible. It defines if object will be rendered. It is *not* the same as real
740    /// visibility from point of view of a camera. Use frustum-box intersection test instead.
741    #[inline]
742    pub fn global_visibility(&self) -> bool {
743        self.global_visibility.get()
744    }
745
746    /// Handle to node in scene of model resource from which this node was instantiated from.
747    ///
748    /// # Notes
749    ///
750    /// This handle is extensively used to fetch information about the state of node in the resource
751    /// to sync properties of instance with its original in the resource.
752    #[inline]
753    pub fn original_handle_in_resource(&self) -> Handle<Node> {
754        self.original_handle_in_resource
755    }
756
757    /// Returns `true` if the node has a parent object in a resource from which it may restore
758    /// values of its inheritable properties.
759    #[inline]
760    pub fn has_inheritance_parent(&self) -> bool {
761        self.original_handle_in_resource.is_some() && self.resource.is_some()
762    }
763
764    /// Returns position of the node in absolute coordinates.
765    #[inline]
766    pub fn global_position(&self) -> Vector3<f32> {
767        self.global_transform.get().position()
768    }
769
770    /// Returns "look" vector of global transform basis, in most cases return vector will be non-normalized.
771    #[inline]
772    pub fn look_vector(&self) -> Vector3<f32> {
773        self.global_transform.get().look()
774    }
775
776    /// Returns "side" vector of global transform basis, in most cases return vector will be non-normalized.
777    #[inline]
778    pub fn side_vector(&self) -> Vector3<f32> {
779        self.global_transform.get().side()
780    }
781
782    /// Returns "up" vector of global transform basis, in most cases return vector will be non-normalized.
783    #[inline]
784    pub fn up_vector(&self) -> Vector3<f32> {
785        self.global_transform.get().up()
786    }
787
788    /// Sets new lod group.
789    #[inline]
790    pub fn set_lod_group(&mut self, lod_group: Option<LodGroup>) -> Option<LodGroup> {
791        std::mem::replace(self.lod_group.get_value_mut_and_mark_modified(), lod_group)
792    }
793
794    /// Extracts lod group, leaving None in the node.
795    #[inline]
796    pub fn take_lod_group(&mut self) -> Option<LodGroup> {
797        std::mem::take(self.lod_group.get_value_mut_and_mark_modified())
798    }
799
800    /// Returns shared reference to current lod group.
801    #[inline]
802    pub fn lod_group(&self) -> Option<&LodGroup> {
803        self.lod_group.as_ref()
804    }
805
806    /// Returns mutable reference to current lod group.
807    #[inline]
808    pub fn lod_group_mut(&mut self) -> Option<&mut LodGroup> {
809        self.lod_group.get_value_mut_and_mark_modified().as_mut()
810    }
811
812    /// Returns node tag.
813    #[inline]
814    pub fn tag(&self) -> &str {
815        &self.tag
816    }
817
818    /// Returns a copy of node tag.
819    #[inline]
820    pub fn tag_owned(&self) -> String {
821        (*self.tag).clone()
822    }
823
824    /// Sets new tag.
825    #[inline]
826    pub fn set_tag(&mut self, tag: String) -> String {
827        self.tag.set_value_and_mark_modified(tag)
828    }
829
830    /// Return the frustum_culling flag
831    #[inline]
832    pub fn frustum_culling(&self) -> bool {
833        *self.frustum_culling
834    }
835
836    /// Sets whether to use frustum culling or not
837    #[inline]
838    pub fn set_frustum_culling(&mut self, frustum_culling: bool) -> bool {
839        self.frustum_culling
840            .set_value_and_mark_modified(frustum_culling)
841    }
842
843    /// Returns true if the node should cast shadows, false - otherwise.
844    #[inline]
845    pub fn cast_shadows(&self) -> bool {
846        *self.cast_shadows
847    }
848
849    /// Sets whether the mesh should cast shadows or not.
850    #[inline]
851    pub fn set_cast_shadows(&mut self, cast_shadows: bool) -> bool {
852        self.cast_shadows.set_value_and_mark_modified(cast_shadows)
853    }
854
855    /// Returns current instance id.
856    pub fn instance_id(&self) -> SceneNodeId {
857        self.instance_id
858    }
859
860    /// Removes a script with the given `index` from the scene node. The script will be destroyed
861    /// in either the current update tick (if it was removed from some other script) or in the next
862    /// update tick of the parent graph.
863    pub fn remove_script(&mut self, index: usize) {
864        // Send script to the graph to destroy script instances correctly.
865        if let Some(entry) = self.scripts.get_mut(index) {
866            entry.should_be_deleted = true;
867
868            // We might be in a middle of a script method execution, where script is temporarily
869            // extracted from the array.
870            if let Some(script) = entry.take() {
871                if let Some(sender) = self.script_message_sender.as_ref() {
872                    Log::verify(sender.send(NodeScriptMessage::DestroyScript {
873                        script,
874                        handle: self.self_handle,
875                        script_index: index,
876                    }));
877                } else {
878                    Log::warn(format!(
879                        "There is a script instance on a node {}, but no message sender. \
880                    The script won't be correctly destroyed!",
881                        self.name(),
882                    ));
883                }
884            }
885        }
886    }
887
888    /// Removes all assigned scripts from the scene node. The scripts will be removed from
889    /// first-to-last order an their actual destruction will happen either on the current update tick
890    /// of the parent graph (if it was removed from some other script) or in the next update tick.
891    pub fn remove_all_scripts(&mut self) {
892        let script_count = self.scripts.len();
893        for i in 0..script_count {
894            self.remove_script(i);
895        }
896    }
897
898    /// Sets a new script for the scene node by index. Previous script will be removed (see
899    /// [`Self::remove_script`] docs for more info).
900    #[inline]
901    pub fn replace_script(&mut self, index: usize, script: Option<Script>) {
902        self.remove_script(index);
903
904        if let Some(entry) = self.scripts.get_mut(index) {
905            entry.script = script;
906            if let Some(sender) = self.script_message_sender.as_ref() {
907                if entry.script.is_some() {
908                    Log::verify(sender.send(NodeScriptMessage::InitializeScript {
909                        handle: self.self_handle,
910                        script_index: index,
911                    }));
912                }
913            }
914        }
915    }
916
917    /// Adds a new script to the scene node. The new script will be initialized either in the current
918    /// update tick (if the script was added in one of the [`ScriptTrait`] methods) or on the next
919    /// update tick.
920    #[inline]
921    pub fn add_script<T>(&mut self, script: T)
922    where
923        T: ScriptTrait,
924    {
925        let script_index = self.scripts.len();
926        self.scripts.push(ScriptRecord::new(Script::new(script)));
927        if let Some(sender) = self.script_message_sender.as_ref() {
928            Log::verify(sender.send(NodeScriptMessage::InitializeScript {
929                handle: self.self_handle,
930                script_index,
931            }));
932        }
933    }
934
935    /// Checks if the node has a script of a particular type. Returns `false` if there is no such
936    /// script.
937    #[inline]
938    pub fn has_script<T>(&self) -> bool
939    where
940        T: ScriptTrait,
941    {
942        self.try_get_script::<T>().is_some()
943    }
944
945    /// Checks if the node has any scripts assigned.
946    #[inline]
947    pub fn has_scripts_assigned(&self) -> bool {
948        self.scripts.iter().any(|script| script.is_some())
949    }
950
951    /// Tries to find a **first** script of the given type `T`, returns `None` if there's no such
952    /// script.
953    #[inline]
954    pub fn try_get_script<T>(&self) -> Option<&T>
955    where
956        T: ScriptTrait,
957    {
958        self.scripts
959            .iter()
960            .find_map(|s| s.as_ref().and_then(|s| s.cast::<T>()))
961    }
962
963    /// Returns an iterator that yields references to the scripts of the given type `T`.
964    #[inline]
965    pub fn try_get_scripts<T>(&self) -> impl Iterator<Item = &T>
966    where
967        T: ScriptTrait,
968    {
969        self.scripts
970            .iter()
971            .filter_map(|e| e.script.as_ref().and_then(|s| s.cast::<T>()))
972    }
973
974    /// Tries to find a **first** script of the given type `T`, returns `None` if there's no such
975    /// script.
976    #[inline]
977    pub fn try_get_script_mut<T>(&mut self) -> Option<&mut T>
978    where
979        T: ScriptTrait,
980    {
981        self.scripts
982            .iter_mut()
983            .find_map(|s| s.as_mut().and_then(|s| s.cast_mut::<T>()))
984    }
985
986    /// Returns an iterator that yields references to the scripts of the given type `T`.
987    #[inline]
988    pub fn try_get_scripts_mut<T>(&mut self) -> impl Iterator<Item = &mut T>
989    where
990        T: ScriptTrait,
991    {
992        self.scripts
993            .iter_mut()
994            .filter_map(|e| e.script.as_mut().and_then(|s| s.cast_mut::<T>()))
995    }
996
997    /// Tries find a component of the given type `C` across **all** available scripts of the node.
998    /// If you want to search a component `C` in a particular script, then use [`Self::try_get_script`]
999    /// and then search for component in it.
1000    #[inline]
1001    pub fn try_get_script_component<C>(&self) -> Option<&C>
1002    where
1003        C: Any,
1004    {
1005        self.scripts
1006            .iter()
1007            .find_map(|s| s.as_ref().and_then(|s| s.query_component_ref::<C>()))
1008    }
1009
1010    /// Tries find a component of the given type `C` across **all** available scripts of the node.
1011    /// If you want to search a component `C` in a particular script, then use [`Self::try_get_script`]
1012    /// and then search for component in it.
1013    #[inline]
1014    pub fn try_get_script_component_mut<C>(&mut self) -> Option<&mut C>
1015    where
1016        C: Any,
1017    {
1018        self.scripts
1019            .iter_mut()
1020            .find_map(|s| s.as_mut().and_then(|s| s.query_component_mut::<C>()))
1021    }
1022
1023    /// Returns total count of scripts assigned to the node.
1024    #[inline]
1025    pub fn script_count(&self) -> usize {
1026        self.scripts.len()
1027    }
1028
1029    /// Returns a shared reference to a script instance with the given `index`. This method will
1030    /// return [`None`] if the `index` is out of bounds or the script is temporarily not available.
1031    /// This could happen if this method was called from some method of a [`ScriptTrait`]. It
1032    /// happens because of borrowing rules - you cannot take another reference to a script that is
1033    /// already mutably borrowed.
1034    #[inline]
1035    pub fn script(&self, index: usize) -> Option<&Script> {
1036        self.scripts.get(index).and_then(|s| s.as_ref())
1037    }
1038
1039    /// Returns an iterator that yields all assigned scripts.
1040    #[inline]
1041    pub fn scripts(&self) -> impl Iterator<Item = &Script> {
1042        self.scripts.iter().filter_map(|s| s.as_ref())
1043    }
1044
1045    /// Returns a mutable reference to a script instance with the given `index`. This method will
1046    /// return [`None`] if the `index` is out of bounds or the script is temporarily not available.
1047    /// This could happen if this method was called from some method of a [`ScriptTrait`]. It
1048    /// happens because of borrowing rules - you cannot take another reference to a script that is
1049    /// already mutably borrowed.
1050    ///
1051    /// # Important notes
1052    ///
1053    /// Do **not** replace script instance using mutable reference given to you by this method.
1054    /// This will prevent correct script de-initialization! Use [`Self::replace_script`] if you need
1055    /// to replace the script.
1056    #[inline]
1057    pub fn script_mut(&mut self, index: usize) -> Option<&mut Script> {
1058        self.scripts.get_mut(index).and_then(|s| s.as_mut())
1059    }
1060
1061    /// Returns an iterator that yields all assigned scripts.
1062    #[inline]
1063    pub fn scripts_mut(&mut self) -> impl Iterator<Item = &mut Script> {
1064        self.scripts.iter_mut().filter_map(|s| s.as_mut())
1065    }
1066
1067    /// Enables or disables scene node. Disabled scene nodes won't be updated (including scripts) or rendered.
1068    ///
1069    /// # Important notes
1070    ///
1071    /// Enabled/disabled state will affect children nodes. It means that if you have a node with children nodes,
1072    /// and you disable the node, all children nodes will be disabled too even if their [`Self::is_enabled`] method
1073    /// returns `true`.
1074    #[inline]
1075    pub fn set_enabled(&mut self, enabled: bool) -> bool {
1076        self.enabled.set_value_and_mark_modified(enabled)
1077    }
1078
1079    /// Returns `true` if the node is enabled, `false` - otherwise. The return value does **not** include the state
1080    /// of parent nodes. It should be considered as "local" enabled flag. To get actual enabled state, that includes
1081    /// the state of parent nodes, use [`Self::is_globally_enabled`] method.
1082    #[inline]
1083    pub fn is_enabled(&self) -> bool {
1084        *self.enabled.property
1085    }
1086
1087    /// Returns `true` if the node and every parent up in hierarchy is enabled, `false` - otherwise. This method
1088    /// returns "true" `enabled` flag. Its value could be different from the value returned by [`Self::is_enabled`].
1089    #[inline]
1090    pub fn is_globally_enabled(&self) -> bool {
1091        self.global_enabled.get()
1092    }
1093
1094    /// Returns a root resource of the scene node. This method crawls up on dependency tree until it finds that
1095    /// the ancestor node does not have any dependencies and returns this resource as the root resource. For
1096    /// example, in case of simple scene node instance, this method will return the resource from which the node
1097    /// was instantiated from. In case of 2 or more levels of dependency, it will always return the "top"
1098    /// dependency in the dependency graph.
1099    #[inline]
1100    pub fn root_resource(&self) -> Option<ModelResource> {
1101        if let Some(resource) = self.resource.as_ref() {
1102            let mut state = resource.state();
1103            if let Some(model) = state.data() {
1104                if let Ok(ancestor_node) = model
1105                    .get_scene()
1106                    .graph
1107                    .try_get_node(self.original_handle_in_resource)
1108                {
1109                    return if ancestor_node.resource.is_none() {
1110                        Some(resource.clone())
1111                    } else {
1112                        ancestor_node.root_resource()
1113                    };
1114                }
1115            }
1116        }
1117        None
1118    }
1119}
1120
1121impl Default for Base {
1122    fn default() -> Self {
1123        BaseBuilder::new().build_base()
1124    }
1125}
1126
1127// Serializes Option<Script> using given serializer.
1128pub(crate) fn visit_opt_script(
1129    name: &str,
1130    script: &mut Option<Script>,
1131    visitor: &mut Visitor,
1132) -> VisitResult {
1133    let mut region = visitor.enter_region(name)?;
1134
1135    let mut script_type_uuid = script.as_ref().map(|s| s.id()).unwrap_or_default();
1136    script_type_uuid.visit("TypeUuid", &mut region)?;
1137
1138    if region.is_reading() {
1139        *script = if script_type_uuid.is_nil() {
1140            None
1141        } else {
1142            let serialization_context = region
1143                .blackboard
1144                .get::<SerializationContext>()
1145                .expect("Visitor blackboard must contain serialization context!");
1146
1147            Some(
1148                serialization_context
1149                    .script_constructors
1150                    .try_create(&script_type_uuid)
1151                    .ok_or_else(|| {
1152                        VisitError::User(format!(
1153                            "There is no corresponding script constructor for {script_type_uuid} type!"
1154                        ))
1155                    })?,
1156            )
1157        };
1158    }
1159
1160    if let Some(script) = script {
1161        script.visit("ScriptData", &mut region)?;
1162    }
1163
1164    Ok(())
1165}
1166
1167impl Visit for Base {
1168    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1169        let mut region = visitor.enter_region(name)?;
1170
1171        self.name.visit("Name", &mut region)?;
1172        self.local_transform.visit("Transform", &mut region)?;
1173        self.visibility.visit("Visibility", &mut region)?;
1174        self.parent.visit("Parent", &mut region)?;
1175        self.children.visit("Children", &mut region)?;
1176        self.resource.visit("Resource", &mut region)?;
1177        self.is_resource_instance_root
1178            .visit("IsResourceInstance", &mut region)?;
1179        self.lifetime.visit("Lifetime", &mut region)?;
1180        self.lod_group.visit("LodGroup", &mut region)?;
1181        self.original_handle_in_resource
1182            .visit("Original", &mut region)?;
1183        self.tag.visit("Tag", &mut region)?;
1184        self.properties.visit("Properties", &mut region)?;
1185        self.frustum_culling.visit("FrustumCulling", &mut region)?;
1186        self.cast_shadows.visit("CastShadows", &mut region)?;
1187        self.instance_id.visit("InstanceId", &mut region)?;
1188        self.enabled.visit("Enabled", &mut region)?;
1189        self.render_mask.visit("RenderMask", &mut region)?;
1190
1191        // Script visiting may fail for various reasons:
1192        //
1193        // 1) Data inside a script is not compatible with latest code (there is no backward
1194        //    compatibility for the data)
1195        // 2) Script was removed in the game.
1196        //
1197        // None of the reasons are fatal and we should still give an ability to load such node
1198        // to edit or remove it.
1199
1200        let _ = self.scripts.visit("Scripts", &mut region);
1201
1202        Ok(())
1203    }
1204}
1205
1206/// Base node builder allows you to create nodes in declarative manner.
1207pub struct BaseBuilder {
1208    name: String,
1209    visibility: bool,
1210    local_transform: Transform,
1211    children: Vec<Handle<Node>>,
1212    lifetime: Option<f32>,
1213    lod_group: Option<LodGroup>,
1214    inv_bind_pose_transform: Matrix4<f32>,
1215    tag: String,
1216    frustum_culling: bool,
1217    cast_shadows: bool,
1218    scripts: Vec<ScriptRecord>,
1219    instance_id: SceneNodeId,
1220    enabled: bool,
1221}
1222
1223impl Default for BaseBuilder {
1224    fn default() -> Self {
1225        Self::new()
1226    }
1227}
1228
1229impl BaseBuilder {
1230    /// Creates new builder instance.
1231    #[inline]
1232    pub fn new() -> Self {
1233        Self {
1234            name: Default::default(),
1235            visibility: true,
1236            local_transform: Default::default(),
1237            children: Default::default(),
1238            lifetime: None,
1239            lod_group: None,
1240            inv_bind_pose_transform: Matrix4::identity(),
1241            tag: Default::default(),
1242            frustum_culling: true,
1243            cast_shadows: true,
1244            scripts: vec![],
1245            instance_id: SceneNodeId(Uuid::new_v4()),
1246            enabled: true,
1247        }
1248    }
1249
1250    /// Sets desired name.
1251    #[inline]
1252    pub fn with_name<P: AsRef<str>>(mut self, name: P) -> Self {
1253        name.as_ref().clone_into(&mut self.name);
1254        self
1255    }
1256
1257    /// Sets desired visibility.
1258    #[inline]
1259    pub fn with_visibility(mut self, visibility: bool) -> Self {
1260        self.visibility = visibility;
1261        self
1262    }
1263
1264    /// Sets desired local transform.
1265    #[inline]
1266    pub fn with_local_transform(mut self, transform: Transform) -> Self {
1267        self.local_transform = transform;
1268        self
1269    }
1270
1271    /// Sets desired inverse bind pose transform.
1272    #[inline]
1273    pub fn with_inv_bind_pose_transform(mut self, inv_bind_pose: Matrix4<f32>) -> Self {
1274        self.inv_bind_pose_transform = inv_bind_pose;
1275        self
1276    }
1277
1278    /// Enables or disables the scene node.
1279    pub fn with_enabled(mut self, enabled: bool) -> Self {
1280        self.enabled = enabled;
1281        self
1282    }
1283
1284    /// Adds a new child to the node. If the given handle is [`Handle::NONE`], then the handle will
1285    /// be ignored.
1286    pub fn with_child(mut self, handle: Handle<impl ObjectOrVariant<Node>>) -> Self {
1287        if handle.is_some() {
1288            self.children.push(handle.to_base())
1289        }
1290        self
1291    }
1292
1293    /// Sets desired lifetime.
1294    #[inline]
1295    pub fn with_lifetime(mut self, time_seconds: f32) -> Self {
1296        self.lifetime = Some(time_seconds);
1297        self
1298    }
1299
1300    /// Sets desired lod group.
1301    #[inline]
1302    pub fn with_lod_group(mut self, lod_group: LodGroup) -> Self {
1303        self.lod_group = Some(lod_group);
1304        self
1305    }
1306
1307    /// Sets desired tag.
1308    #[inline]
1309    pub fn with_tag(mut self, tag: String) -> Self {
1310        self.tag = tag;
1311        self
1312    }
1313
1314    /// Sets desired frustum_culling flag.
1315    #[inline]
1316    pub fn with_frustum_culling(mut self, frustum_culling: bool) -> Self {
1317        self.frustum_culling = frustum_culling;
1318        self
1319    }
1320
1321    /// Sets whether mesh should cast shadows or not.
1322    #[inline]
1323    pub fn with_cast_shadows(mut self, cast_shadows: bool) -> Self {
1324        self.cast_shadows = cast_shadows;
1325        self
1326    }
1327
1328    /// Sets script of the node.
1329    #[inline]
1330    pub fn with_script<T>(mut self, script: T) -> Self
1331    where
1332        T: ScriptTrait,
1333    {
1334        self.scripts.push(ScriptRecord::new(Script::new(script)));
1335        self
1336    }
1337
1338    /// Sets new instance id.
1339    pub fn with_instance_id(mut self, id: SceneNodeId) -> Self {
1340        self.instance_id = id;
1341        self
1342    }
1343
1344    /// Creates an instance of [`Base`].
1345    #[inline]
1346    pub fn build_base(self) -> Base {
1347        Base {
1348            self_handle: Default::default(),
1349            script_message_sender: None,
1350            message_sender: None,
1351            name: self.name.into(),
1352            children: self.children,
1353            local_transform: TrackedProperty::unbound(
1354                self.local_transform,
1355                NodeMessageKind::TransformChanged,
1356            ),
1357            lifetime: self.lifetime.into(),
1358            visibility: TrackedProperty::unbound(
1359                self.visibility.into(),
1360                NodeMessageKind::VisibilityChanged,
1361            ),
1362            enabled: TrackedProperty::unbound(
1363                self.enabled.into(),
1364                NodeMessageKind::EnabledFlagChanged,
1365            ),
1366            render_mask: BitMask::all().into(),
1367            global_visibility: Cell::new(true),
1368            parent: Handle::NONE,
1369            global_transform: Cell::new(Matrix4::identity()),
1370            inv_bind_pose_transform: self.inv_bind_pose_transform,
1371            resource: None,
1372            original_handle_in_resource: Handle::NONE,
1373            is_resource_instance_root: false,
1374            lod_group: self.lod_group.into(),
1375            tag: self.tag.into(),
1376            properties: Default::default(),
1377            frustum_culling: self.frustum_culling.into(),
1378            cast_shadows: self.cast_shadows.into(),
1379            scripts: self.scripts,
1380            instance_id: SceneNodeId(Uuid::new_v4()),
1381
1382            global_enabled: Cell::new(true),
1383        }
1384    }
1385}