UNPKG

@wonderlandengine/api

Version:

Wonderland Engine's JavaScript API.

483 lines (482 loc) 16.5 kB
import { WonderlandEngine } from './engine.js'; import { Emitter } from './utils/event.js'; import { Object3D, RayHit, Environment, ViewComponent, InputType, ProbeVolumeScenario, Component, SSAO } from './wonderland.js'; import { NumberArray } from './types.js'; import { Material } from './resources/material-manager.js'; import { Prefab, SceneLoadOptions } from './prefab.js'; import { GLTFExtensionsInstance, PrefabGLTF } from './scene-gltf.js'; export interface InstantiateResult { root: Object3D; } export interface InstantiateGltfResult extends InstantiateResult { extensions: GLTFExtensionsInstance | null; } /** Options for scene activation. */ export interface ActivateOptions { /** If `true`, dispatches a ready event in the document. */ dispatchReadyEvent?: boolean; /** * If `true`, the promise will resolve only once all dependencies are downloaded. * * If `false`, resolves as soon as possible, e.g., when the lowest * resolution textures are available. */ waitForDependencies?: boolean; /** @hidden */ legacyLoaded?: boolean; } /** * Legacy gltf extension type. * * @deprecated Use the new {@link WonderlandEngine.loadGLTF} API. */ export interface GLTFExtensionsLegacy { /** glTF root extensions object. JSON data indexed by extension name. */ root: Record<string, Record<string, any>>; /** * Mesh extension objects. Key is {@link Object3D.objectId}, value is JSON * data indexed by extension name. */ mesh: Record<number, Record<string, Record<string, any>>>; /** * Node extension objects. Key is {@link Object3D.objectId}, value is JSON * data indexed by extension name. */ node: Record<number, Record<string, Record<string, any>>>; /** Remapping from glTF node index to {@link Object3D.objectId}. */ idMapping: number[]; } /** Options for {@link Scene.append}. */ export interface SceneAppendParameters { /** Whether to load glTF extension data */ loadGltfExtensions: boolean; baseURL: string | undefined; } /** * Result obtained when appending a scene with {@link Scene.append} with gltf extensions. */ export type SceneAppendResultWithExtensions = { root: Object3D | null; extensions: GLTFExtensionsLegacy; }; /** * Result obtained when appending a scene with {@link Scene.append}. */ export type SceneAppendResult = (Object3D | null) | SceneAppendResultWithExtensions; /** * Scene type to load with {@link ChunkedSceneLoadSink}. * * @since 1.2.1 * @hidden */ export declare enum SceneType { Prefab = 0, Main = 1, Dependency = 2 } /** * Sink for `WritableStream` that loads the data as a .bin file. * * Data is loaded chunk by chunk to minimize the total WASM allocation size. * * @since 1.2.1 * @hidden */ export declare class ChunkedSceneLoadSink implements UnderlyingSink<Uint8Array> { #private; _loadIndex: number; sceneIndex: number; /** * Constructor * @param engine Engine instance * @param type Type of scene to load * @param url URL for the scene creation. Can be empty. * @param closeParameters Parameters for the final function to be called * during a successful {@link ChunkedSceneLoadSink.close}. */ constructor(engine: WonderlandEngine, type: SceneType, url: string); private _resizeBuffer; private _throwError; /** * Write a single blob of data. * * @param blob Data to parse */ write(blob: Uint8Array): void; /** Called when all blobs of data have been written */ close(): void; /** Called when the stream is aborted */ abort(): void; /** Staging buffer size */ get size(): number; } /** * Wonderland Engine (.bin) scene. * * Wonderland Engine packages two types of scene: * - Activatable scene: Contains objects, components, views, resources, and rendering data * - Streamable scene: Contains objects, components, and resources * * #### Activation * * Some scenes are **activatable**, they can thus be attached to the renderer * to be updated and rendered on the canvas. * * For more information, have a look at the {@link WonderlandEngine.switchTo} method. * * #### Instantiation * * Besides activation, a scene can instantiate the content of another scene. * * For more information, have a look at the {@link Scene#instantiate} method. * * @category scene */ export declare class Scene extends Prefab { /** Called before rendering the scene */ readonly onPreRender: Emitter<void[]>; /** Called after the scene has been rendered */ readonly onPostRender: Emitter<void[]>; /** Ray hit pointer in WASM heap. @hidden */ private _rayHit; /** Ray hit. @hidden */ private _hit; /** @hidden */ private _environment; /** @hidden */ private _ssao; /** Components to tick, one array per type. @hidden */ private readonly _jsSystems; /** Mapping from component type index to system index. @hidden */ private readonly _componentTypeToSystem; /** Synced with the engine's version upon sorting. @hidden */ private _registrationVersion; constructor(engine: WonderlandEngine, index: number); /** @overload */ instantiate(scene: PrefabGLTF): InstantiateGltfResult; /** * Instantiate `scene` into this instance. * * Any scene can be instantiated into one another. It's thus possible * to instantiate a {@link PrefabGLTF} into this instance, or another * {@link Scene} instance. * * #### Usage * * ```js * const prefabScene = await engine.loadScene('Prefab.bin'); * // Instantiate `prefabScene` into `scene` * engine.scene.instantiate(prefabScene); * ``` * * #### Shared Resources * * Instantiating **does not** duplicate resources. Each instance will * reference the same assets stored in the {@link Scene}, e.g., * * ```js * // `zombie` has one mesh and one material * const zombie = await engine.loadScene('Zombie.bin'); * * for (let i = 0; i < 100; ++i) { * engine.scene.instantiate(zombie); * } * * console.log(engine.meshes.count) // Prints '1' * console.log(engine.materials.count) // Prints '1' * ``` * * #### glTF extensions * * Instantiating a prefab loaded from a .glb automatically retargets the extensions * to the created hierarchy: * * ```js * const gltf = await engine.loadGLTF({url: 'Model.glb', extensions: true}); * const {root, extensions} = engine.scene.instantiate(gltf); * * // Retrieve Object3D instance from extension nodes list * for (const key in extensions.node) { * const object3d = engine.scene.wrap(extensions.node[key]); * } * ``` * * @param scene The scene to instantiate. * @returns An object containing the instantiated root {@link Object3D}. * When a glTF is instantiated, the result can contain extra metadata. * For more information, have a look at the {@link InstantiateResult} type. * * @since 1.2.0 */ instantiate(prefab: Prefab): InstantiateResult; /** @todo: Add `instantiateBatch` to instantiate multiple chunks in a row. */ /** * @todo Provide an API to delete all resources linked to a scene. * * Example: * * ```ts * const scene = await engine.loadScene('Scene.bin'); * ... * scene.destroy({removeResources: true}); * ``` */ /** * Destroy this scene and remove it from the engine. * * @note Destroying a scene **doesn't** remove the materials, meshes, * and textures it references in the engine. Those should be cleaned up either by loading * another main scene via {@link WonderlandEngine.loadMainScene}, or manually using {@link Mesh.destroy}. * * @throws If the scene is currently active. * */ destroy(): void; /** * View components. */ get views(): ViewComponent[]; /** * Active view components. */ get activeViews(): ViewComponent[]; /** Main view. */ get mainView(): ViewComponent | null; /** Set the current non-VR view. */ set mainView(view: ViewComponent | null); /** * Left eye view. */ get leftEyeView(): ViewComponent | null; /** * Right eye view. */ get rightEyeView(): ViewComponent | null; set probeVolumeScenario(scenario: ProbeVolumeScenario | null); get probeVolumeScenario(): ProbeVolumeScenario | null; /** * Set input transformation. * * @hidden */ _setInputTransformation(type: InputType, position: Readonly<NumberArray>, orientation: Readonly<NumberArray>): void; /** * Cast a ray through the scene and find intersecting collision components. * * The resulting ray hit will contain **up to 4** closest ray hits, * sorted by increasing distance. * * Example: * * ```js * const hit = engine.scene.rayCast( * [0, 0, 0], * [0, 0, 1], * 1 << 0 | 1 << 4, // Only check against components in groups 0 and 4 * 25 * ); * if (hit.hitCount > 0) { * const locations = hit.getLocations(); * console.log(`Object hit at: ${locations[0][0]}, ${locations[0][1]}, ${locations[0][2]}`); * } * ``` * * @param o Ray origin. * @param d Ray direction. * @param groupMask Bitmask of collision groups to filter by: only objects * that are part of given groups are considered for the raycast. * @param maxDistance Maximum **inclusive** hit distance. Defaults to `100`. * * @returns The {@link RayHit} instance, cached by this class. * * @note The returned {@link RayHit} object is owned by the {@link Scene} * instance and will be reused with the next {@link Scene#rayCast} call. */ rayCast(o: Readonly<NumberArray>, d: Readonly<NumberArray>, groupMask: number, maxDistance?: number): RayHit; /** * Set the background clear color. * * @param color new clear color (RGBA). * @since 0.8.5 */ set clearColor(color: number[]); /** * Set whether to clear the color framebuffer before drawing. * * This function is useful if an external framework (e.g. an AR tracking * framework) is responsible for drawing a camera frame before Wonderland * Engine draws the scene on top of it. * * @param b Whether to enable color clear. * @since 0.9.4 */ set colorClearEnabled(b: boolean); /** * Load a scene file (.bin). * * Will replace the currently active scene with the one loaded * from given file. It is assumed that JavaScript components required by * the new scene were registered in advance. * * Once the scene is loaded successfully and initialized, * {@link WonderlandEngine.onSceneLoaded} is notified. * * #### ArrayBuffer * * The `load()` method accepts an in-memory buffer: * * ```js * scene.load({ * buffer: new ArrayBuffer(...), * baseURL: 'https://my-website/assets' * }) * ``` * * @note The `baseURL` is mandatory. It's used to fetch images and languages. * * Use {@link Scene.setLoadingProgress} to update the loading progress bar * when using an ArrayBuffer. * * @deprecated Use the new {@link WonderlandEngine.loadMainScene} API. * * @param options Path to the file to load, or an option object. * For more information about the options, see the {@link SceneLoadOptions} documentation. * @returns Promise that resolves when the scene was loaded. */ load(options: string | SceneLoadOptions): Promise<Scene>; /** * Append a scene file. * * Loads and parses the file and its images and appends the result * to the currently active scene. * * Supported formats are streamable Wonderland scene files (.bin) and glTF * 3D scenes (.gltf, .glb). * * ```js * WL.scene.append(filename).then(root => { * // root contains the loaded scene * }); * ``` * * In case the `loadGltfExtensions` option is set to true, the response * will be an object containing both the root of the loaded scene and * any glTF extensions found on nodes, meshes and the root of the file. * * ```js * WL.scene.append(filename, { loadGltfExtensions: true }).then(({root, extensions}) => { * // root contains the loaded scene * // extensions.root contains any extensions at the root of glTF document * const rootExtensions = extensions.root; * // extensions.mesh and extensions.node contain extensions indexed by Object id * const childObject = root.children[0]; * const meshExtensions = root.meshExtensions[childObject.objectId]; * const nodeExtensions = root.nodeExtensions[childObject.objectId]; * // extensions.idMapping contains a mapping from glTF node index to Object id * }); * ``` * * If the file to be loaded is located in a subfolder, it might be useful * to define the `baseURL` option. This will ensure any bin files * referenced by the loaded bin file are loaded at the correct path. * * ```js * WL.scene.append(filename, { baseURL: 'scenes' }).then(({root, extensions}) => { * // do stuff * }); * ``` * * @deprecated Use the new {@link Prefab} and {@link Scene} API. * * @param file The .bin, .gltf or .glb file to append. Should be a URL or * an `ArrayBuffer` with the file content. * @param options Additional options for loading. * @returns Promise that resolves when the scene was appended. */ append(file: string | ArrayBuffer, options?: Partial<SceneAppendParameters>): Promise<SceneAppendResult>; /** * Update the loading screen progress bar. * * @param value Current loading percentage, in the range [0; 1]. * * @deprecated Use {@link WonderlandEngine.setLoadingProgress}. */ setLoadingProgress(percentage: number): void; /** * Dispatch an event 'wle-scene-ready' in the document. * * @note This is used for automatic testing. */ dispatchReadyEvent(): void; /** * Set the current material to render the sky. * * @note The sky needs to be enabled in the editor when creating the scene. * For more information, please refer to the background [tutorial](https://wonderlandengine.com/tutorials/background-effect/). */ set skyMaterial(material: Material | null); /** Current sky material, or `null` if no sky is set. */ get skyMaterial(): Material | null; /** * Environment lighting properties. * * @since 1.2.3 */ get environment(): Environment; /** * SSAO properties. * * @since 1.6.0 */ get ssao(): SSAO; /** * Relative url to the js components bundle * * Returns `null` if the scene was built without a components bundle. */ get componentsBundle(): string | null; /** * Reset the scene. * * This method deletes all used and allocated objects, and components. * * @deprecated Load a new scene and activate it instead. */ reset(): void; /** * Trigger update for active js components. * * @param dt Delta time. * * @hidden */ _runUpdateJs(dt: number): void; /** * Make this scene active. * * @hidden */ _activate(): void; _postDeactivate(): void; /** * Download and apply queued dependency files (.bin). * * @hidden */ _downloadDependencies(): Promise<void | void[]>; /** @override @hidden */ protected _onComponentCreated(component: Component, type: number): void; /** @override @hidden */ protected _onComponentDestroyed(instance: Component): void; /** * Cache js systems on this instance. * * @note Must be called to be able to update js components. * * @param force If `true`, force re-assign components to system buckets. * * @hidden */ private _cacheJsSystems; /** Sort js component types topologically. @hidden */ private _sortComponentSystems; }