.. _stdlib_scene_core: ===== Scene ===== This module provides functions for interacting with scene nodes and components. It allows you to create, read, delete, and modify nodes and components within the scene. **Nodes** serve as the fundamental building blocks of the scene, organizing its hierarchy and storing the position, rotation, and scale of objects. **Components**, on the other hand, are attached to nodes and define their behavior. For instance, a mesh component defines the geometry of a node, a camera component specifies camera properties, and a light component defines light properties. The node hierarchy forms a tree structure where each node can have one parent and multiple children. The root node is the top-level node in the hierarchy and has no parent. .. note:: Child nodes inherit their parent node's transformation, meaning that moving the parent node will also move its child nodes. The scene consists of nodes and components that collectively define the 3D environment. It accommodates multiple nodes and components, with nodes capable of hosting multiple attached components. The scene is used for rendering, physics simulation updates, and input event handling. To work with the scene, you must create a new scene, add nodes and components to it, and update the scene continuously. .. note:: The scene *will not* be rendered until a camera node is added to it. Let's build a simple scene with a cube rotating around the origin:: require engine.core var parentNode : NodeId [export] def on_initialize() { // add render settings with shadows and tonemapping let renderSettings = create_render_settings() get_component(renderSettings) $(var tonemap : Tonemap?) { tonemap.active = true } // create fixed camera add_component(create_node(NodeData(name="camera", position=float3(0, 0, -7))), new Camera()) // create light add_component(create_node(NodeData(name="sun")), new DirectionLight()) // create the parent node for the cube at the origin parentNode = create_node(NodeData(name="parent", position=float3(0))) // create the cube let cubeNode = create_node(NodeData(name="child", position=float3(-1, 0, 0), parent=parentNode)) add_component(cubeNode, new Mesh(meshId=CUBE_MESH_ID)) } [export] def on_update() { // rotate the parent node. The cube is a child of the parent node, // so it will rotate around the parent node let dt = get_delta_time() parentNode.localRotation *= quat4(0, 0.5 * dt, 0) } You can find more examples in the sample projects. To use this module, include the following line in your project file:: require engine.scene_core // or require engine.core ++++++++++++ Enumerations ++++++++++++ .. _enum-scene_core-ChildrenPolicy: .. das:attribute:: ChildrenPolicy The policy to include children nodes in the bounding box calculation. :Values: * **Exclude** = 0 - Exclude children nodes from the bounding box calculation. * **IncludeActive** = 1 - Include only active children nodes in the bounding box calculation. * **IncludeAll** = 2 - Include all children nodes in the bounding box calculation. .. _enum-public_scene-AddChildStrategy: .. das:attribute:: AddChildStrategy Enumeration for strategies to add a child node. :Values: * **KeepWorldTransform** = 0 - Keeps the world transform unchanged. Suitable for 3D objects. Default strategy if not specified. * **KeepLocalTransform** = 1 - Keeps the local transform unchanged. Suitable for 2D/UI objects. .. _enum-public_scene-BlendingMethod: .. das:attribute:: BlendingMethod Blending Methods for Animation Layers used in :ref:`sample_animation_and_overlay() ` Animation layers can be combined in two ways, depending on the blending method: * Overlay – The layer replaces subsequent layers (order matters). * BlendSublayer – Multiple sublayers are combined into a single layer by normalizing and scaling their weights (order within a layer does not matter). * The last sublayer should be with Overlay method, and its weight should be the weight of the whole layer, not the sublayer (for technical reasons). See overlay methods descriptions for further details. For example, consider this layer stack: * Top Layer (weight 50%) * Middle Layer (weight 80%) * Sublayer 1 (weight 20%) * Sublayer 2 (weight 30%) * Sublayer 3 (weight 50%) * Bottom Layer (weight 100%) This is represented as:: BlendingMethod.Overlay, weight 0.5 // Top Layer BlendingMethod.BlendSublayer, weight 0.2 // Middle Layer, Sublayer 1 BlendingMethod.BlendSublayer, weight 0.3 // Middle Layer, Sublayer 2 BlendingMethod.Overlay, weight 0.8 // Middle Layer, Sublayer 3, Last Sublayer BlendingMethod.Overlay, weight 1.0 // Bottom Layer which in the end will result in that weights:: Top Layer = 50% Middle Layer, Sublayer 1 = 20% * 80% * (100 - 50%) = 8% Middle Layer, Sublayer 2 = 30% * 80% * (100 - 50%) = 12% Middle Layer, Sublayer 3 = 50% * 80% * (100 - 50%) = 20% Bottom Layer = (100 - 50%) * (100 - 80%) = 10% Total = 100% (always normalized). :Values: * **Overlay** = 0 - ``result = layerA * weight + layerB * (1 - weight)`` . With 100% weight, the layer completely replaces all subsequent layers. * **BlendSublayer** = 1 - ``result = (Σ sublayer_i * weight_i) * layer_weight`` . Sublayers are combined into one layer. The last sublayer must be with Overlay method, with its weight set to the weight of the whole group (not just that sublayer). This ensures the total weight is preserved. .. _enum-transform3d_component-AttachmentMode: .. das:attribute:: AttachmentMode The attachment mode of a scene node. :Values: * **Parent** = 0x0u8 - The scene node is attached to the parent node as a child. * **World** = 0x1u8 - The scene node is still a child of the parent node, but is attached to the world. The local transformation of the parent node is ignored. ++++++++++ Structures ++++++++++ .. _struct-scene_core-NodeData: .. das:attribute:: NodeData A structure for initialization of a scene instance (single scene node or prefab). :Fields: * **name** : string - The name of the node .. _function-scene_core_NodeData_rq_has_position_NodeData: .. das:function:: NodeData.has_position() : bool Checks if the position component has been explicitly set .. _function-scene_core_NodeData_rq_has_rotation_NodeData: .. das:function:: NodeData.has_rotation() : bool Checks if the rotation component has been explicitly set .. _function-scene_core_NodeData_rq_has_scale_NodeData: .. das:function:: NodeData.has_scale() : bool Checks if the scale component has been explicitly set .. _function-scene_core_NodeData_rq_has_parent_NodeData: .. das:function:: NodeData.has_parent() : bool Checks if the parent component has been explicitly set .. _function-scene_core_NodeData_rq_has_name_NodeData: .. das:function:: NodeData.has_name() : bool Checks if the name component has been explicitly set (empty string counts as an invalid name) :Properties: .. _function-scene_core__dot__rq_position_NodeData: .. das:operator:: NodeData.position() : float3 .. _function-scene_core__dot__rq_position_rq_clone_NodeData_float3: .. das:operator:: NodeData.position =(position: float3) Local position, relative to its parent :Arguments: * **position** : float3 .. _function-scene_core__dot__rq_rotation_NodeData: .. das:operator:: NodeData.rotation() : quat4 Returns the current local rotation as a quaternion (quat4) .. _function-scene_core__dot__rq_rotation_rq_clone_NodeData_quat4: .. das:operator:: NodeData.rotation =(rotation: quat4) Local rotation, relative to its parent :Arguments: * **rotation** : :ref:`quat4 ` .. _function-scene_core__dot__rq_scale_NodeData: .. das:operator:: NodeData.scale() : float3 Returns the current local scale vector (float3) .. _function-scene_core__dot__rq_scale_rq_clone_NodeData_float3: .. das:operator:: NodeData.scale =(scale: float3) Local scale, relative to its parent :Arguments: * **scale** : float3 .. _function-scene_core__dot__rq_parent_NodeData: .. das:operator:: NodeData.parent() : NodeId .. _function-scene_core__dot__rq_parent_rq_clone_NodeData_NodeId: .. das:operator:: NodeData.parent =(parent: NodeId) The parent node, can be invalid NodeId if the node does not have a parent :Arguments: * **parent** : :ref:`NodeId ` +++++++++++++ Handled types +++++++++++++ .. _handle-public_scene-NodeId: .. das:attribute:: NodeId A reference (``uint64``) to the real scene node. It is used to uniquely identify a specific node in the scene. ``NodeId`` is considered **invalid** if its initialized with ``NodeId()``. Consider these examples:: // invalid let node2 = NodeId() // valid, constructed via create_node() let node2 = create_node(NodeData(name="node2")) So, if you want to check NodeId for validity, you can do it like this:: if (node == NodeId()) { print("Node is invalid!") } +++++++++ Functions +++++++++ * :ref:`clear_scene () ` * :ref:`create_node (req: NodeData = NodeData()) : NodeId ` * :ref:`get_children (nodeId: NodeId; var children: array\) : int ` * :ref:`get_children (nodeId: NodeId) : array\ ` * :ref:`NodeId.childCount (nodeId: NodeId) : int ` * :ref:`get_child (nodeId: NodeId; idx: int) : NodeId ` * :ref:`remove_node (nodeId: NodeId) : bool ` * :ref:`add_child (nodeId: NodeId; child: NodeId) : bool ` * :ref:`add_child (nodeId: NodeId; child: NodeId; strategy: AddChildStrategy) : bool ` * :ref:`add_child (nodeId: NodeId; child: NodeId; at: int) : bool ` * :ref:`add_child (nodeId: NodeId; child: NodeId; at: int; strategy: AddChildStrategy) : bool ` * :ref:`get_child_index (nodeId: NodeId; child: NodeId) : int ` * :ref:`get_sibling_index (nodeId: NodeId) : int ` * :ref:`find_child (nodeId: NodeId; child_name: string) : NodeId ` * :ref:`find_child_recursive (nodeId: NodeId; child_name: string) : NodeId ` * :ref:`find_children (nodeId: NodeId; child_name: string) : array\ ` * :ref:`find_children (nodeId: NodeId; child_name: string; var res: array\) : int ` * :ref:`find_children_recursive (nodeId: NodeId; child_name: string) : array\ ` * :ref:`find_children_recursive (nodeId: NodeId; child_name: string; var res: array\) : int ` * :ref:`look_at (nodeId: NodeId; pos: float3; up: float3 = UP) ` * :ref:`look_at (nodeId: NodeId; target: NodeId; up: float3 = UP) ` * :ref:`get_scene_root () : NodeId ` * :ref:`get_scene_roots () : array\ ` * :ref:`get_scene_roots (var out_nodes: array\) ` * :ref:`find_child (child_name: string) : NodeId ` * :ref:`find_child_recursive (child_name: string) : NodeId ` * :ref:`find_children_recursive (child_name: string) : array\ ` * :ref:`find_children_recursive (child_name: string; var res: array\) : int ` * :ref:`duplicate_node (nodeId: NodeId; data: NodeData = NodeData()) : NodeId ` * :ref:`NodeId.isAlive (nodeId: NodeId) : bool ` * :ref:`NodeId.isActive (nodeId: NodeId) : bool ` * :ref:`NodeId.isActive = (nodeId: NodeId; is_active: bool) ` * :ref:`NodeId.isActiveInHierarchy (nodeId: NodeId) : bool ` * :ref:`NodeId.attachmentMode (nodeId: NodeId) : AttachmentMode ` * :ref:`NodeId.attachmentMode = (nodeId: NodeId; attachment_type: AttachmentMode) ` * :ref:`NodeId.parent (nodeId: NodeId) : NodeId ` * :ref:`NodeId.parent = (nodeId: NodeId; parent: NodeId) ` * :ref:`set_parent (nodeId: NodeId; parent: NodeId; strategy: AddChildStrategy) ` * :ref:`set_parent (nodeId: NodeId; parent: NodeId) ` * :ref:`NodeId.name (nodeId: NodeId) : string ` * :ref:`NodeId.name = (nodeId: NodeId; name: string) ` * :ref:`NodeId.hierarchyName (nodeId: NodeId) : string ` * :ref:`NodeId.localPosition (nodeId: NodeId) : float3 ` * :ref:`NodeId.localPosition = (nodeId: NodeId; local_position: float3) ` * :ref:`NodeId.localPosition += (nodeId: NodeId; delta: float3) ` * :ref:`NodeId.localPosition -= (nodeId: NodeId; delta: float3) ` * :ref:`NodeId.localRotation (nodeId: NodeId) : quat4 ` * :ref:`NodeId.localRotation = (nodeId: NodeId; local_rotation: quat4) ` * :ref:`NodeId.localRotation *= (nodeId: NodeId; delta: quat4) ` * :ref:`NodeId.localScale (nodeId: NodeId) : float3 ` * :ref:`NodeId.localScale = (nodeId: NodeId; local_scale: float3) ` * :ref:`NodeId.worldTransform (nodeId: NodeId) : float3x4 ` * :ref:`NodeId.invWorldTransform (nodeId: NodeId) : float3x4 ` * :ref:`NodeId.localTransform (nodeId: NodeId) : float3x4 ` * :ref:`NodeId.worldPosition (nodeId: NodeId) : float3 ` * :ref:`NodeId.worldPosition = (nodeId: NodeId; world_position: float3) ` * :ref:`NodeId.worldPosition += (nodeId: NodeId; delta: float3) ` * :ref:`NodeId.worldPosition -= (nodeId: NodeId; delta: float3) ` * :ref:`NodeId.worldRotation (nodeId: NodeId) : quat4 ` * :ref:`NodeId.worldRotation = (nodeId: NodeId; world_rotation: quat4) ` * :ref:`NodeId.worldRotation *= (nodeId: NodeId; delta: quat4) ` * :ref:`NodeId.worldScale (nodeId: NodeId) : float3 ` * :ref:`NodeId.worldScale = (nodeId: NodeId; world_scale: float3) ` * :ref:`NodeId.localRight (nodeId: NodeId) : float3 ` * :ref:`NodeId.localUp (nodeId: NodeId) : float3 ` * :ref:`NodeId.localForward (nodeId: NodeId) : float3 ` * :ref:`NodeId.worldRight (nodeId: NodeId) : float3 ` * :ref:`NodeId.worldUp (nodeId: NodeId) : float3 ` * :ref:`NodeId.worldForward (nodeId: NodeId) : float3 ` * :ref:`sample_animation_and_blend (nodeId: NodeId; animations: array\; ratios: array\; weights: array\) ` * :ref:`sample_animation_and_blend (nodeId: NodeId; animations: array\; ratios: array\; weights: array\; masks: array\) ` * :ref:`sample_animation_and_overlay (nodeId: NodeId; animations: array\; ratios: array\; weights: array\; masks: array\; blendingMethod: array\) ` * :ref:`apply_aim_ik_to_animation (nodeId: NodeId; names: array\; target: float3; offset: float3; chain_weight: float; joint_weight: float) ` * :ref:`get_node_bounding_box (nodeId: NodeId; policy: ChildrenPolicy = scene_core::ChildrenPolicy.Exclude) : BBox3D ` * :ref:`NodeId () : NodeId ` * :ref:`NodeId (id: uint64) : NodeId ` * :ref:`NodeId (id: NodeId) : NodeId ` * :ref:`uint64 (id: NodeId) : uint64 ` * :ref:`NodeId\! (a: NodeId) : bool ` * :ref:`NodeId== (a: NodeId; b: NodeId) : bool ` * :ref:`NodeId\!= (a: NodeId; b: NodeId) : bool ` * :ref:`valid (id: NodeId) : bool ` .. _function-scene_core_clear_scene: .. das:function:: clear_scene() clear all scene nodes and components .. _function-scene_core_create_node_NodeData: .. das:function:: create_node(req: NodeData = NodeData()) : NodeId creates a scene node with specified parameters Usage example:: let node = create_node(NodeData( name="MyNode", parent=parent_node, position=float3(0, 4, 0), rotation=quat4(), scale=float3(0.5) )) :Arguments: * **req** : :ref:`NodeData ` .. _function-scene_core_get_children_NodeId_array_ls_NodeId_gr_: .. das:function:: get_children(nodeId: NodeId; children: array) : int Gets all children of the node, and appends them to the `children` array :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node * **children** : array< :ref:`NodeId ` > - the output array :Returns: * int - the amount of children of the node Usage example:: var inscope children : array get_children(nodeId, children) print("{children}") .. _function-scene_core_get_children_NodeId: .. das:function:: get_children(nodeId: NodeId) : array Gets all children of the node, that is, nodes for which `nodeId` is a parent. If `nodeId` is zero, gets all root nodes of the scene (i.e. nodes with no parent). :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node :Returns: * array< :ref:`NodeId ` > - all children of the node Usage example:: for (child in get_children(nodeId)) { print("{child}") } .. _function-scene_core__dot__rq_childCount_NodeId: .. das:function:: NodeId.childCount(nodeId: NodeId) : int :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * int - the number of children of the node. Usage example:: print("{nodeId.childCount}") .. _function-scene_core_get_child_NodeId_int: .. das:function:: get_child(nodeId: NodeId; idx: int) : NodeId :Returns: * :ref:`NodeId ` - `idx`'th child of the node. :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node * **idx** : int - the index of the child in the parent's children list. Values < 0 are treated as an offset from the end of the children list Usage example:: for (i in 0..nodeId.childCount) { print("{get_child(nodeId, i)}") } .. _function-scene_core_remove_node_NodeId: .. das:function:: remove_node(nodeId: NodeId) : bool removes the scene node with all components :Arguments: * **nodeId** : :ref:`NodeId ` - the node to remove :Returns: * bool - true if the node was removed, false if the node was not found .. _function-scene_core_add_child_NodeId_NodeId: .. das:function:: add_child(nodeId: NodeId; child: NodeId) : bool adds a child node in the end of the children list :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node * **child** : :ref:`NodeId ` - the node to add as a new child :Returns: * bool - true if the child was added, false if the child wasn't added .. _function-scene_core_add_child_NodeId_NodeId_AddChildStrategy: .. das:function:: add_child(nodeId: NodeId; child: NodeId; strategy: AddChildStrategy) : bool adds a child node in the end of the children list :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node * **child** : :ref:`NodeId ` - the node to add as a new child * **strategy** : :ref:`AddChildStrategy ` - the strategy to apply when adding the child :Returns: * bool - true if the child was added, false if the child wasn't added .. _function-scene_core_add_child_NodeId_NodeId_int: .. das:function:: add_child(nodeId: NodeId; child: NodeId; at: int) : bool adds a child node to the position with a specified index. If node is already a child of `nodeId`, it will be moved to the ``at`` position. :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node * **child** : :ref:`NodeId ` - the node to add as a new child * **at** : int - the index in the children list to where the `child` should be inserted. Values < 0 are treated as an offset from the end of the children list :Returns: * bool - true if the child was added, false if the child wasn't added .. _function-scene_core_add_child_NodeId_NodeId_int_AddChildStrategy: .. das:function:: add_child(nodeId: NodeId; child: NodeId; at: int; strategy: AddChildStrategy) : bool adds a child node to the position with a specified index :Arguments: * **nodeId** : :ref:`NodeId ` - the parent node * **child** : :ref:`NodeId ` - the node to add as a new child * **at** : int - the index in the children list to where the `child` should be inserted. Values < 0 are treated as an offset from the end of the children list * **strategy** : :ref:`AddChildStrategy ` - the strategy to apply when adding the child :Returns: * bool - true if the child was added, false if the child wasn't added .. _function-scene_core_get_child_index_NodeId_NodeId: .. das:function:: get_child_index(nodeId: NodeId; child: NodeId) : int :Arguments: * **nodeId** : :ref:`NodeId ` * **child** : :ref:`NodeId ` :Returns: * int - the index of the child in the parent's children list. If the `child` is not actually a child of `nodeId`, returns -1 .. _function-scene_core_get_sibling_index_NodeId: .. das:function:: get_sibling_index(nodeId: NodeId) : int :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * int - the index of the node in its parent's children list. Equivalent to `get_child_index(node.parent, node)` .. _function-scene_core_find_child_NodeId_string: .. das:function:: find_child(nodeId: NodeId; child_name: string) : NodeId finds the child node by name, looking only in the list of direct children of `nodeId`. If name contains a path separator '/', the function will search for the child recursively Usage example:: let child = find_child(nodeId, "MyChild") :Arguments: * **nodeId** : :ref:`NodeId ` * **child_name** : string .. _function-scene_core_find_child_recursive_NodeId_string: .. das:function:: find_child_recursive(nodeId: NodeId; child_name: string) : NodeId finds the child node by name, looking through all children of `nodeId` (including grandchildren etc.) recursively. If name contains a path separator '/', the function will search for the child recursively Usage example:: // finds the "Hand" node on any level of the hierarchy let child = find_child_recursive(nodeId, "Hand") // finds the "Hand" node that is a child of the "LeftArm" node let child = find_child_recursive(nodeId, "LeftArm/Hand") :Arguments: * **nodeId** : :ref:`NodeId ` * **child_name** : string .. _function-scene_core_find_children_NodeId_string: .. das:function:: find_children(nodeId: NodeId; child_name: string) : array Finds all child nodes by name, looking only in the list of direct children of `nodeId`. If name contains a path separator '/', the function will search for the child recursively Usage example:: let children = find_children(nodeId, "MyChild") :Arguments: * **nodeId** : :ref:`NodeId ` * **child_name** : string .. _function-scene_core_find_children_NodeId_string_array_ls_NodeId_gr_: .. das:function:: find_children(nodeId: NodeId; child_name: string; res: array) : int Finds all child nodes by name, looking only in the list of direct children of `nodeId`. If name contains a path separator '/', the function will search for the child recursively Usage example:: var children : array find_children(nodeId, "MyChild", children) :Arguments: * **nodeId** : :ref:`NodeId ` * **child_name** : string * **res** : array< :ref:`NodeId ` > .. _function-scene_core_find_children_recursive_NodeId_string: .. das:function:: find_children_recursive(nodeId: NodeId; child_name: string) : array Finds all child nodes by name, looking through all children of `nodeId` (including grandchildren etc.) recursively. If name contains a path separator '/', the function will search for the child recursively Usage example:: let children = find_children_recursive(nodeId, "MyChild") :Arguments: * **nodeId** : :ref:`NodeId ` * **child_name** : string .. _function-scene_core_find_children_recursive_NodeId_string_array_ls_NodeId_gr_: .. das:function:: find_children_recursive(nodeId: NodeId; child_name: string; res: array) : int Finds all child nodes by name, looking through all children of `nodeId` (including grandchildren etc.) recursively. If name contains a path separator '/', the function will search for the child recursively Usage example:: var children : array find_children_recursive(nodeId, "MyChild", children) :Arguments: * **nodeId** : :ref:`NodeId ` * **child_name** : string * **res** : array< :ref:`NodeId ` > .. _function-scene_core_look_at_NodeId_float3_float3: .. das:function:: look_at(nodeId: NodeId; pos: float3; up: float3 = UP) rotates the node to look at the position :Arguments: * **nodeId** : :ref:`NodeId ` - the node to rotate * **pos** : float3 - the position to look at * **up** : float3 - the upward direction for the new rotation .. _function-scene_core_look_at_NodeId_NodeId_float3: .. das:function:: look_at(nodeId: NodeId; target: NodeId; up: float3 = UP) rotates the node to look at the target node :Arguments: * **nodeId** : :ref:`NodeId ` - the node to rotate * **target** : :ref:`NodeId ` - the target node to look at * **up** : float3 - the upward direction for the new rotation .. _function-scene_core_get_scene_root: .. das:function:: get_scene_root() : NodeId :Returns: * :ref:`NodeId ` - the root node of the scene, returns invalid NodeId if the scene is empty .. _function-scene_core_get_scene_roots: .. das:function:: get_scene_roots() : array :Returns: * array< :ref:`NodeId ` > - all root nodes of the scene. Same as `get_children(NodeId())` .. _function-scene_core_get_scene_roots_array_ls_NodeId_gr_: .. das:function:: get_scene_roots(out_nodes: array) writes all root nodes of the scene to the `out_nodes` array. Same as `get_children(NodeId(), out_nodes)` :Arguments: * **out_nodes** : array< :ref:`NodeId ` > - content of the array will be replaced with the root nodes .. _function-scene_core_find_child_string: .. das:function:: find_child(child_name: string) : NodeId finds the child node by name, looking through all scene nodes If name contains a path separator '/', the function will search for the child recursively Usage example:: let child = find_child("MyChild") :Arguments: * **child_name** : string .. _function-scene_core_find_child_recursive_string: .. das:function:: find_child_recursive(child_name: string) : NodeId finds the child node by name, looking through all scene nodes If name contains a path separator '/', the function will search for the child recursively Usage example:: // finds the "Hand" node on any level of the hierarchy let child = find_child_recursive("Hand") :Arguments: * **child_name** : string .. _function-scene_core_find_children_recursive_string: .. das:function:: find_children_recursive(child_name: string) : array Finds all child nodes by name, looking through all children of `nodeId` (including grandchildren etc.) recursively. If name contains a path separator '/', the function will search for the child recursively Usage example:: let children = find_children_recursive("MyChild") :Arguments: * **child_name** : string .. _function-scene_core_find_children_recursive_string_array_ls_NodeId_gr_: .. das:function:: find_children_recursive(child_name: string; res: array) : int Finds all child nodes by name, looking through all children of `nodeId` (including grandchildren etc.) recursively. If name contains a path separator '/', the function will search for the child recursively Usage example:: var children : array find_children_recursive("MyChild", children) :Arguments: * **child_name** : string * **res** : array< :ref:`NodeId ` > .. _function-scene_core_duplicate_node_NodeId_NodeData: .. das:function:: duplicate_node(nodeId: NodeId; data: NodeData = NodeData()) : NodeId Creates a copy of the node, including all of its children and components. Note that duplication will be performed as if the target node was a prefab root, so all `on_initialize` functions of components will be called. You can pass NodeData to additionaly parameterize the copy, just like in `create_node` or `instantiate_prefab` functions. :Arguments: * **nodeId** : :ref:`NodeId ` - the node to duplicate * **data** : :ref:`NodeData ` - parameters for the new node :Returns: * :ref:`NodeId ` - the resulting copy of of the input node Usage example:: let copy = duplicate_node(duplicateMe, NodeData(name = "{duplicateMe}_copy")) .. _function-scene_core__dot__rq_isAlive_NodeId: .. das:function:: NodeId.isAlive(nodeId: NodeId) : bool :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * bool - true if `nodeId` is valid and is not removed from the scene. Otherwise, false Usage example:: if (node.isAlive) { print("Node {node.name} is alive") } .. _function-scene_core__dot__rq_isActive_NodeId: .. das:function:: NodeId.isActive(nodeId: NodeId) : bool :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * bool - an active state of `nodeId`, not taking into account parent's active state When the node is not active, all components attached to the node are also disabled (e.g. meshes do not rendering, physics for the node is not calculated, etc.) and it does not receive on_update events. .. _function-scene_core__dot__rq_isActive_rq_clone_NodeId_bool: .. das:function:: NodeId.isActive =(nodeId: NodeId; is_active: bool) sets the node active state. It will also change the enabled state of all components attached to the node. Note that the render related components will be affected only in the next frame :Arguments: * **nodeId** : :ref:`NodeId ` * **is_active** : bool .. _function-scene_core__dot__rq_isActiveInHierarchy_NodeId: .. das:function:: NodeId.isActiveInHierarchy(nodeId: NodeId) : bool :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * bool - true if `nodeId` and all its parents are active .. _function-scene_core__dot__rq_attachmentMode_NodeId: .. das:function:: NodeId.attachmentMode(nodeId: NodeId) : AttachmentMode :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`AttachmentMode ` - the attachment mode of the node .. _function-scene_core__dot__rq_attachmentMode_rq_clone_NodeId_AttachmentMode: .. das:function:: NodeId.attachmentMode =(nodeId: NodeId; attachment_type: AttachmentMode) sets the attachment mode of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **attachment_type** : :ref:`AttachmentMode ` .. _function-scene_core__dot__rq_parent_NodeId: .. das:function:: NodeId.parent(nodeId: NodeId) : NodeId :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`NodeId ` - the parent of this node .. _function-scene_core__dot__rq_parent_rq_clone_NodeId_NodeId: .. das:function:: NodeId.parent =(nodeId: NodeId; parent: NodeId) sets the parent for this node :Arguments: * **nodeId** : :ref:`NodeId ` * **parent** : :ref:`NodeId ` .. _function-scene_core_set_parent_NodeId_NodeId_AddChildStrategy: .. das:function:: set_parent(nodeId: NodeId; parent: NodeId; strategy: AddChildStrategy) sets the parent for this node :Arguments: * **nodeId** : :ref:`NodeId ` - the node to set the parent for * **parent** : :ref:`NodeId ` - the new parent node * **strategy** : :ref:`AddChildStrategy ` - the strategy to apply when adding the child .. _function-scene_core_set_parent_NodeId_NodeId: .. das:function:: set_parent(nodeId: NodeId; parent: NodeId) sets the parent for this node, using `AddChildStrategy.KeepWorldTransform` :Arguments: * **nodeId** : :ref:`NodeId ` - the node to set the parent for * **parent** : :ref:`NodeId ` - the new parent node .. _function-scene_core__dot__rq_name_NodeId: .. das:function:: NodeId.name(nodeId: NodeId) : string :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * string - the node name .. _function-scene_core__dot__rq_name_rq_clone_NodeId_string: .. das:function:: NodeId.name =(nodeId: NodeId; name: string) sets the node name :Arguments: * **nodeId** : :ref:`NodeId ` * **name** : string .. _function-scene_core__dot__rq_hierarchyName_NodeId: .. das:function:: NodeId.hierarchyName(nodeId: NodeId) : string :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * string - the node full hierarchy name, e.g. "root/parent/current" .. _function-scene_core__dot__rq_localPosition_NodeId: .. das:function:: NodeId.localPosition(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the local position of the node .. _function-scene_core__dot__rq_localPosition_rq_clone_NodeId_float3: .. das:function:: NodeId.localPosition =(nodeId: NodeId; local_position: float3) sets the local position of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **local_position** : float3 .. _function-scene_core__dot__rq_localPosition_rq_+_eq__NodeId_float3: .. das:function:: NodeId.localPosition +=(nodeId: NodeId; delta: float3) increments the local position of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **delta** : float3 .. _function-scene_core__dot__rq_localPosition_rq_-_eq__NodeId_float3: .. das:function:: NodeId.localPosition -=(nodeId: NodeId; delta: float3) decrements the local position of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **delta** : float3 .. _function-scene_core__dot__rq_localRotation_NodeId: .. das:function:: NodeId.localRotation(nodeId: NodeId) : quat4 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`quat4 ` - the local rotation of the node .. _function-scene_core__dot__rq_localRotation_rq_clone_NodeId_quat4: .. das:function:: NodeId.localRotation =(nodeId: NodeId; local_rotation: quat4) sets the local rotation of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **local_rotation** : :ref:`quat4 ` .. _function-scene_core__dot__rq_localRotation_rq__st__eq__NodeId_quat4: .. das:function:: NodeId.localRotation *=(nodeId: NodeId; delta: quat4) multiplies the local rotation of the node by the delta quaternion :Arguments: * **nodeId** : :ref:`NodeId ` * **delta** : :ref:`quat4 ` .. _function-scene_core__dot__rq_localScale_NodeId: .. das:function:: NodeId.localScale(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the local scale of the node .. _function-scene_core__dot__rq_localScale_rq_clone_NodeId_float3: .. das:function:: NodeId.localScale =(nodeId: NodeId; local_scale: float3) sets the local scale of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **local_scale** : float3 .. _function-scene_core__dot__rq_worldTransform_NodeId: .. das:function:: NodeId.worldTransform(nodeId: NodeId) : float3x4 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`float3x4 ` - the world transform of the node (local to world) Usage example:: var particleWorldPos = node.worldTransform * particle.localPosition .. _function-scene_core__dot__rq_invWorldTransform_NodeId: .. das:function:: NodeId.invWorldTransform(nodeId: NodeId) : float3x4 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`float3x4 ` - the inverse world transform of the node (world to local) Usage example:: var bulletLocalPos = node.invWorldTransform * bullet.worldPosition .. _function-scene_core__dot__rq_localTransform_NodeId: .. das:function:: NodeId.localTransform(nodeId: NodeId) : float3x4 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`float3x4 ` - the local transform of the node .. _function-scene_core__dot__rq_worldPosition_NodeId: .. das:function:: NodeId.worldPosition(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the world position of the node .. _function-scene_core__dot__rq_worldPosition_rq_clone_NodeId_float3: .. das:function:: NodeId.worldPosition =(nodeId: NodeId; world_position: float3) sets the world position of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **world_position** : float3 .. _function-scene_core__dot__rq_worldPosition_rq_+_eq__NodeId_float3: .. das:function:: NodeId.worldPosition +=(nodeId: NodeId; delta: float3) increments the world position of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **delta** : float3 .. _function-scene_core__dot__rq_worldPosition_rq_-_eq__NodeId_float3: .. das:function:: NodeId.worldPosition -=(nodeId: NodeId; delta: float3) decrements the world position of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **delta** : float3 .. _function-scene_core__dot__rq_worldRotation_NodeId: .. das:function:: NodeId.worldRotation(nodeId: NodeId) : quat4 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * :ref:`quat4 ` - the world rotation of the node .. _function-scene_core__dot__rq_worldRotation_rq_clone_NodeId_quat4: .. das:function:: NodeId.worldRotation =(nodeId: NodeId; world_rotation: quat4) sets the world rotation of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **world_rotation** : :ref:`quat4 ` .. _function-scene_core__dot__rq_worldRotation_rq__st__eq__NodeId_quat4: .. das:function:: NodeId.worldRotation *=(nodeId: NodeId; delta: quat4) multiplies the world rotation of the node by the delta quaternion :Arguments: * **nodeId** : :ref:`NodeId ` * **delta** : :ref:`quat4 ` .. _function-scene_core__dot__rq_worldScale_NodeId: .. das:function:: NodeId.worldScale(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the world scale of the node .. _function-scene_core__dot__rq_worldScale_rq_clone_NodeId_float3: .. das:function:: NodeId.worldScale =(nodeId: NodeId; world_scale: float3) sets the world scale of the node :Arguments: * **nodeId** : :ref:`NodeId ` * **world_scale** : float3 .. _function-scene_core__dot__rq_localRight_NodeId: .. das:function:: NodeId.localRight(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the local right vector of the node .. _function-scene_core__dot__rq_localUp_NodeId: .. das:function:: NodeId.localUp(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the local up vector of the node .. _function-scene_core__dot__rq_localForward_NodeId: .. das:function:: NodeId.localForward(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the local forward vector of the node .. _function-scene_core__dot__rq_worldRight_NodeId: .. das:function:: NodeId.worldRight(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the world right vector of the node .. _function-scene_core__dot__rq_worldUp_NodeId: .. das:function:: NodeId.worldUp(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the world up vector of the node .. _function-scene_core__dot__rq_worldForward_NodeId: .. das:function:: NodeId.worldForward(nodeId: NodeId) : float3 :Arguments: * **nodeId** : :ref:`NodeId ` :Returns: * float3 - the world forward vector of the node .. _function-scene_core_sample_animation_and_blend_NodeId_array_ls_AnimationId_gr__array_ls_float_gr__array_ls_float_gr_: .. das:function:: sample_animation_and_blend(nodeId: NodeId; animations: array; ratios: array; weights: array) samples given animations and blends them into the node's animator :Arguments: * **nodeId** : :ref:`NodeId ` * **animations** : array< :ref:`AnimationId ` > * **ratios** : array * **weights** : array .. _function-scene_core_sample_animation_and_blend_NodeId_array_ls_AnimationId_gr__array_ls_float_gr__array_ls_float_gr__array_ls_AnimationMaskId_gr_: .. das:function:: sample_animation_and_blend(nodeId: NodeId; animations: array; ratios: array; weights: array; masks: array) samples given animations and blends them into the node's animator :Arguments: * **nodeId** : :ref:`NodeId ` * **animations** : array< :ref:`AnimationId ` > * **ratios** : array * **weights** : array * **masks** : array< :ref:`AnimationMaskId ` > .. _function-scene_core_sample_animation_and_overlay_NodeId_array_ls_AnimationId_gr__array_ls_float_gr__array_ls_float_gr__array_ls_AnimationMaskId_gr__array_ls_BlendingMethod_gr_: .. das:function:: sample_animation_and_overlay(nodeId: NodeId; animations: array; ratios: array; weights: array; masks: array; blendingMethod: array) samples given animations and overlays them into the node's animator :Arguments: * **nodeId** : :ref:`NodeId ` * **animations** : array< :ref:`AnimationId ` > * **ratios** : array * **weights** : array * **masks** : array< :ref:`AnimationMaskId ` > * **blendingMethod** : array< :ref:`BlendingMethod ` > .. _function-scene_core_apply_aim_ik_to_animation_NodeId_array_ls_string_gr__float3_float3_float_float: .. das:function:: apply_aim_ik_to_animation(nodeId: NodeId; names: array; target: float3; offset: float3; chain_weight: float; joint_weight: float) samples given animations and blends them into the node's animator :Arguments: * **nodeId** : :ref:`NodeId ` * **names** : array * **target** : float3 * **offset** : float3 * **chain_weight** : float * **joint_weight** : float .. _function-scene_core_get_node_bounding_box_NodeId_ChildrenPolicy: .. das:function:: get_node_bounding_box(nodeId: NodeId; policy: ChildrenPolicy = scene_core::ChildrenPolicy.Exclude) : BBox3D Calculate the bounding box of a scene node including mesh bounding boxes and optionally the bounding boxes of the children. :Arguments: * **nodeId** : :ref:`NodeId ` - the id of the scene node * **policy** : :ref:`ChildrenPolicy ` - the policy to include children nodes in the bounding box calculation :Returns: * :ref:`BBox3D ` - the bounding box of the node Usage example:: let bbox = get_node_bounding_box(node, /*with children*/true) .. _function-public_scene_NodeId: .. das:function:: NodeId() : NodeId :Returns: * :ref:`NodeId ` - an empty `NodeId` object .. _function-public_scene_NodeId_uint64: .. das:function:: NodeId(id: uint64) : NodeId :Arguments: * **id** : uint64 :Returns: * :ref:`NodeId ` - a constructed `NodeId` object from id .. _function-public_scene_NodeId_NodeId: .. das:function:: NodeId(id: NodeId) : NodeId :Arguments: * **id** : :ref:`NodeId ` :Returns: * :ref:`NodeId ` - a copy of a `NodeId` object (used as a copy constructor) .. _function-public_scene_uint64_NodeId: .. das:function:: uint64(id: NodeId) : uint64 :Arguments: * **id** : :ref:`NodeId ` :Returns: * uint64 - the id of a scene node as `uint64` .. _function-public_scene__ex__NodeId: .. das:function:: NodeId!(a: NodeId) : bool :Arguments: * **a** : :ref:`NodeId ` :Returns: * bool - whether the `NodeId` is invalid .. _function-public_scene__eq__eq__NodeId_NodeId: .. das:function:: NodeId==(a: NodeId; b: NodeId) : bool :Arguments: * **a** : :ref:`NodeId ` * **b** : :ref:`NodeId ` :Returns: * bool - whether two scene nodes are equal (or both invalid) .. _function-public_scene__ex__eq__NodeId_NodeId: .. das:function:: NodeId!=(a: NodeId; b: NodeId) : bool :Arguments: * **a** : :ref:`NodeId ` * **b** : :ref:`NodeId ` :Returns: * bool - whether two scene nodes are not equal .. _function-public_scene_valid_NodeId: .. das:function:: valid(id: NodeId) : bool :Arguments: * **id** : :ref:`NodeId ` :Returns: * bool - whether the `NodeId` is valid