HelixToolkit.Nex.Scene 1.2.0

dotnet add package HelixToolkit.Nex.Scene --version 1.2.0
                    
NuGet\Install-Package HelixToolkit.Nex.Scene -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HelixToolkit.Nex.Scene" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HelixToolkit.Nex.Scene" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="HelixToolkit.Nex.Scene" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add HelixToolkit.Nex.Scene --version 1.2.0
                    
#r "nuget: HelixToolkit.Nex.Scene, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package HelixToolkit.Nex.Scene@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=HelixToolkit.Nex.Scene&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=HelixToolkit.Nex.Scene&version=1.2.0
                    
Install as a Cake Tool
# HelixToolkit.Nex.Scene

The `HelixToolkit.Nex.Scene` package manages and manipulates scene-graph nodes within a 3D environment. It builds on the `HelixToolkit.Nex.ECS` framework to provide hierarchical transformations, node management, and scene sorting in a data-oriented, performant way.

## Overview

`HelixToolkit.Nex.Scene` is responsible for:
- Managing scene-graph nodes backed by ECS entities and components.
- Handling hierarchical transformations and parent-child relationships.
- Flattening and sorting nodes and updating world transforms.
- Deferred scene construction off the world thread via `SceneCommandBuffer`.

A `Node` wraps an ECS `Entity` and attaches the components needed for scene management (`NodeInfo`,
`Transform`, `WorldTransform`, `Parent`, and optionally `NodeName`, `Children`, `Renderable`). The
package depends on `HelixToolkit.Nex.ECS` for entity/component storage and `HelixToolkit.Nex.Maths`
for matrix math.

## Key Types

| Type                   | Description                                                                                                                    |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `Node`                 | A scene-graph node wrapping an `Entity`; manages transform and parent/child relationships.                                     |
| `NodeInfo`             | Component storing a node's hierarchy level, entity id, and enabled state. Implements `ISortable<NodeInfo>` (sorts by level).   |
| `NodeName`             | Optional component storing a node's display name.                                                                              |
| `Transform`            | Component holding local scale/rotation/translation plus a change `Timestamp`.                                                  |
| `WorldTransform`       | Component holding a node's computed world matrix (`Matrix4x4`).                                                                |
| `Parent`               | Component referencing a node's parent entity.                                                                                  |
| `Children`             | Component holding the list of child nodes.                                                                                     |
| `Renderable`           | Component marking a node for rendering, with a render mask and internal GPU indexing fields.                                   |
| `SceneSorting`         | Static/extension methods for flattening node trees and updating transforms (`Flatten`, `UpdateTransforms`, `SortSceneNodes`).  |
| `SceneCommandBuffer`   | Records deferred node creation, hierarchy, and properties off the world thread, then materializes real `Node`s during `Flush`. |
| `DeferredNode`         | Handle returned by `SceneCommandBuffer.RecordCreateNode()` that resolves to a real `Node` during flush.                        |
| `TypedDeferredNode<T>` | Typed handle for recording creation of a custom `Node` subtype `T`.                                                            |
| `SceneFlushResult`     | Result of `SceneCommandBuffer.Flush`, reporting success or the failing command index and description.                          |

## New Features

### Deferred Action Command

The `SceneCommandBuffer` now supports recording arbitrary actions to be executed during the flush on the world's owning thread. This is achieved through the `RecordDeferredAction` method.

#### `SceneCommandBuffer.RecordDeferredAction`

Records a deferred action to run on the world's owning thread during flush, in recorded order.

```csharp
public ResultCode RecordDeferredAction(Action<World> action, string description);
  • Parameters:

    • action: The delegate to invoke against the target World during flush. All required data must be captured inside the delegate.
    • description: A human-readable description surfaced in flush failure messages.
  • Returns: ResultCode.Ok on success; ResultCode.InvalidState if action is null or a concurrent recording operation is in progress.

Usage Examples

Creating and Managing Nodes

using HelixToolkit.Nex.Scene;
using HelixToolkit.Nex.ECS;

// Worlds are created through the ECS factory, not 'new'.
using var world = World.CreateWorld();

// Create a root node and a child.
var rootNode = new Node(world, "Root");
var childNode = new Node(world, "Child");
rootNode.AddChild(childNode);

// Sort by hierarchy level, then update world transforms.
world.SortSceneNodes();
world.UpdateTransforms();

Accessing and Modifying Node Properties

Console.WriteLine($"Root Node Name: {rootNode.Name}");
Console.WriteLine($"Child Node Level: {childNode.Level}");

childNode.Name = "Updated Child";

// Transform is exposed by ref, so it can be mutated in place.
childNode.Transform.Translation = new Vector3(1, 0, 0);
childNode.NotifyTransformChanged();

Flattening and Updating Transforms

// Flatten the tree (depth-first) into a sorted list, optionally filtered.
var sortedNodes = new List<Node>();
rootNode.Flatten(condition: null, sortedNodes);

// Update world transforms across the flattened, level-ordered list.
sortedNodes.UpdateTransforms();

Controlling Renderable State

childNode.IsRenderable = true;          // adds the Renderable component
bool isRenderable = childNode.IsRenderable;

Recording Deferred Actions

using HelixToolkit.Nex.Scene;
using HelixToolkit.Nex.ECS;

// 1. Record off the world thread — no World is referenced here.
var buffer = new SceneCommandBuffer();

buffer.RecordDeferredAction(world => {
    // Custom action to be executed during flush
    Console.WriteLine("Deferred action executed.");
}, "Custom deferred action");

// 2. Flush on the world's owning thread to materialize real Nodes and execute actions.
SceneFlushResult result = buffer.Flush(world);
if (result.Success)
{
    Console.WriteLine("Flush succeeded.");
}
else
{
    Console.WriteLine(
        $"Flush failed at command {result.FailedCommandIndex}: {result.Message} ({result.Code})");
}

Scene Command Buffer

SceneCommandBuffer lets you build a scene graph without touching any World during recording, so the work can run on a background thread. Recorded commands are materialized into real Node objects during Flush, which must run on the world's owning thread. Recording is single-writer: concurrent recording calls are rejected, leaving the buffer's state unchanged.

using HelixToolkit.Nex.Scene;
using HelixToolkit.Nex.ECS;

// 1. Record off the world thread — no World is referenced here.
var buffer = new SceneCommandBuffer();

var root = buffer.RecordCreateNode("Root");
var child = buffer.RecordCreateNode("Child");
buffer.RecordAddChild(root, child);
buffer.RecordLocalTransform(child, new Transform { Translation = new Vector3(1, 0, 0) });
buffer.RecordRenderable(child);

// 2. Flush on the world's owning thread to materialize real Nodes.
SceneFlushResult result = buffer.Flush(world);
if (result.Success)
{
    // Resolve a deferred handle to the materialized Node.
    if (buffer.MaterializedNodes.TryGetValue(child, out var childNode))
    {
        Console.WriteLine($"Materialized: {childNode.Name}");
    }
}
else
{
    Console.WriteLine(
        $"Flush failed at command {result.FailedCommandIndex}: {result.Message} ({result.Code})");
}

To create a custom Node subtype, record it with a factory:

var handle = buffer.RecordCreateNode(world => new MyCustomNode(world));
buffer.Flush(world);
if (buffer.TryGetMaterializedNode(handle, out MyCustomNode? node) == ResultCode.Ok)
{
    // use node
}

Architecture Notes

  • ECS-backed: Each Node is an Entity with scene components; transforms and hierarchy live in ECS component storage.
  • Per-world node registry: Nodes are tracked in a per-world ConcurrentDictionary keyed by entity id; the registry is dropped wholesale when the world is disposed.
  • Single-threaded per world: A world is accessed by one thread at a time. Use SceneCommandBuffer to build nodes off-thread and apply them back on the world thread.
  • Level-ordered transform updates: NodeInfo sorts by hierarchy level so parents are processed before children when world transforms are recomputed.
  • Dependencies: HelixToolkit.Nex.ECS (entities/components) and HelixToolkit.Nex.Maths (matrix math).
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on HelixToolkit.Nex.Scene:

Package Downloads
HelixToolkit.Nex.Rendering

Package Description

HelixToolkit.Nex.Engine

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 240 7/17/2026