UNPKG

@gltf-transform/core

Version:

glTF 2.0 SDK for JavaScript and TypeScript, on Web and Node.js.

83 lines (73 loc) 3.05 kB
import { RefSet } from 'property-graph'; import { type Nullable, PropertyType } from '../constants.js'; import { ExtensibleProperty, type IExtensibleProperty } from './extensible-property.js'; import type { Node } from './node.js'; import { COPY_IDENTITY } from './property.js'; interface IScene extends IExtensibleProperty { children: RefSet<Node>; } /** * *Scenes represent a set of visual objects to render.* * * Typically a glTF file contains only a single Scene, although more are allowed and useful in some * cases. No particular meaning is associated with additional Scenes, except as defined by the * application. Scenes reference {@link Node}s, and a single Node cannot be a member of more than * one Scene. * * References: * - [glTF → Scenes](https://github.com/KhronosGroup/gltf/blob/main/specification/2.0/README.md#scenes) * - [glTF → Coordinate System and Units](https://github.com/KhronosGroup/gltf/blob/main/specification/2.0/README.md#coordinate-system-and-units) * * @category Properties */ export class Scene extends ExtensibleProperty<IScene> { public declare propertyType: PropertyType.SCENE; protected init(): void { this.propertyType = PropertyType.SCENE; } protected getDefaults(): Nullable<IScene> { return Object.assign(super.getDefaults() as IExtensibleProperty, { children: new RefSet<Node>() }); } public copy(other: this, resolve: typeof COPY_IDENTITY = COPY_IDENTITY): this { // Scene cannot be copied, only cloned. Copying is shallow, but nodes cannot have more than // one parent. Rather than leaving one of the two Scenes without children, throw an error here. if (resolve === COPY_IDENTITY) throw new Error('Scene cannot be copied.'); return super.copy(other, resolve); } /** * Adds a {@link Node} to the Scene. * * Requirements: * * 1. Nodes MAY be root children of multiple {@link Scene Scenes} * 2. Nodes MUST NOT be children of >1 Node * 3. Nodes MUST NOT be children of both Nodes and {@link Scene Scenes} * * The `addChild` method enforces these restrictions automatically, and will * remove the new child from previous parents where needed. This behavior * may change in future major releases of the library. */ public addChild(node: Node): this { // Remove existing parent. const parentNode = node.getParentNode(); if (parentNode) parentNode.removeChild(node); return this.addRef('children', node); } /** Removes a {@link Node} from the Scene. */ public removeChild(node: Node): this { return this.removeRef('children', node); } /** * Lists all direct child {@link Node Nodes} in the Scene. Indirect * descendants (children of children) are not returned, but may be * reached recursively or with {@link Scene.traverse} instead. */ public listChildren(): Node[] { return this.listRefs('children'); } /** Visits each {@link Node} in the Scene, including descendants, top-down. */ public traverse(fn: (node: Node) => void): this { for (const node of this.listChildren()) node.traverse(fn); return this; } }