@wonderlandengine/api
Version:
Wonderland Engine's JavaScript API.
466 lines (465 loc) • 15.7 kB
TypeScript
import { ComponentManagers, NativeComponents } from './component.js';
import { WonderlandEngine } from './engine.js';
import { ResourceManager, SceneResource } from './resources/resource.js';
import { ProgressCallback } from './types.js';
import { Animation, CollisionCallback, Component, ComponentConstructor, Object3D, Skin } from './wonderland.js';
/** Scene loading options. */
export interface SceneLoadOptions {
/** An in-memory buffer, containing the bytes of a `.bin` file. */
buffer: ArrayBuffer;
/** Path from which resources are resolved (images, languages, etc...). */
baseURL: string;
/** If `true`, dispatches a ready event in the document. */
dispatchReadyEvent?: boolean;
}
/** Loading options for in-memory data. */
export interface InMemoryLoadOptions {
/** An in-memory buffer, containing the bytes of a `.bin` file. */
buffer: ArrayBuffer;
/** Path from which resources are resolved (images, languages, etc...). */
baseURL: string;
/** Name of the file. This is the same that will be retrieved via {@link Scene#filename} */
filename?: string;
/**
* Force to re-download the components bundle, and not use the version from cache.
*
* If not set, defaults to `false`.
*
* @note For now, this setting only affects the main scene loading.
*/
nocache?: boolean;
}
/**
* Loading options for streamed data.
*
* @hidden
*/
export interface StreamLoadOptions {
/** Stream that transfers the bytes of a `.bin` file. */
stream: ReadableStream<Uint8Array>;
/** Path from which resources are resolved (images, languages, etc...). */
baseURL: string;
/** Name of the file. This is the same that will be retrieved via {@link Scene#filename} */
filename?: string;
}
/** Options for loading files from a URL. */
export interface UrlLoadOptions {
/** URL to load. */
url: string;
/** Signal to abort the file fetch request. */
signal?: AbortSignal;
/**
* Whether to load the file as parts of it are fetched. If `false`,
* fetches the entire file first before loading. Streamed loading reduces
* memory usage. If not set, defaults to `true`.
*/
streamed?: boolean;
/**
* Force to re-download the components bundle, and not use the version from cache.
*
* If not set, defaults to `false`.
*
* @note For now, this setting only affects the main scene loading.
*/
nocache?: boolean;
}
/** Options used during loading. */
export type LoadOptions<Extra = {}> = string | (UrlLoadOptions & Partial<Extra>);
/**
* Base class for prefabs, scenes, and glTF.
*
* For more information have a look at the derived types:
* - {@link Scene} for Wonderland Engine activatable scenes (.bin)
* - {@link PrefabGLTF} for glTF scenes
*
* #### Resources
*
* While **meshes**, **textures**, and **materials** are shared
* on the {@link WonderlandEngine} instance, a scene comes with:
* - Animations: Managed using {@link Prefab.animations}
* - Skins: Managed using {@link Prefab.skins}
*
* Those resources are bound to the object hierarchy and are thus required to be
* per-scene.
*
* #### Destruction
*
* For now, destroying a scene doesn't automatically remove the resources it
* references in the engine. For more information, have a look at the
* {@link Scene.destroy} method.
*
* #### Isolation
*
* It's forbidden to mix objects and components from different scenes, e.g.,
*
* ```js
* const objA = sceneA.addChild();
* const objB = sceneB.addChild();
* objA.parent = objB; // Throws
* ```
*
* @category scene
*
* @since 1.2.0
*/
export declare class Prefab {
/**
* Create an object with shape `{url: string}`.
*
* - If the parameter is a string, a new object is returned
* - If the parameter is an object, the same reference is returned
*
* @param options The url or options object.
* @returns An object of the form `{url: string, ...}`.
*
* @hidden
*/
static makeUrlLoadOptions<E>(options: LoadOptions<E>): UrlLoadOptions & Partial<E>;
/**
* Load an `ArrayBuffer` using fetch.
*
* @param opts The url or options.
* @param progress Progress callback
* @returns An {@link InMemoryLoadOptions} object.
*
* @hidden
*/
static loadBuffer(options: LoadOptions, progress?: ProgressCallback): Promise<InMemoryLoadOptions>;
/**
* Load a `ReadableStream` using fetch.
*
* @param opts The url or options.
* @param progress Progress callback
* @returns A {@link StreamLoadOptions} object.
*
* @hidden
*/
static loadStream(options: LoadOptions, progress?: ProgressCallback): Promise<StreamLoadOptions>;
/**
* Validate the in-memory load options.
*
* @param options Options to validate.
* @returns Validated options object.
*
* @hidden
*/
static validateBufferOptions(options: InMemoryLoadOptions): {
buffer: ArrayBuffer;
baseURL: string;
url: string;
};
/**
* Validate the stream load options.
*
* @param options Options to validate.
* @returns Validated options object.
*
* @hidden
*/
static validateStreamOptions(options: StreamLoadOptions): {
stream: ReadableStream<Uint8Array>;
baseURL: string;
url: string;
};
/** Index in the scene manager. @hidden */
readonly _index: number;
/** @hidden */
protected _engine: WonderlandEngine;
/**
* Component manager caching to avoid GC.
*
* @hidden
*/
readonly _components: ComponentManagers;
/**
* JavaScript components for this scene.
*
* This array is moved into the WASM instance upon activation.
*
* @hidden
*/
readonly _jsComponents: Component[];
/**
* The map is indexed using the physx component id.
*
* @hidden
*/
readonly _pxCallbacks: Map<number, CollisionCallback[]>;
/** @hidden */
private readonly _animations;
/** @hidden */
private readonly _skins;
/**
* Object class instances to avoid GC.
*
* @hidden
*/
private readonly _objectCache;
/**
* `onDestroy()` depth.
*
* Multiple components can stack `onDestroy()` calls.
*/
private _pendingDestroy;
/**
* @note This api is meant to be used internally.
*
* @hidden
*/
constructor(engine: WonderlandEngine, index: number);
/**
* Add a new {@link Object3D} to the root object.
*
* See {@link Object3D.addChild} for more information.
*
* @returns A new {@link Object3D}.
*/
addChild(): Object3D;
/**
* Add an object to the scene.
*
* Alternatively, you can use {@link Prefab.addChild} to add the object
* to the root, or {@link Object3D.addChild} to add the object to a given parent:
*
* ```js
* const parent = scene.addChild();
* const child = parent.addChild();
* // Equivalent using scene.addObject
* const sibling = scene.addObject(parent);
* ```
*
* @param parent Parent object or `null`.
* @returns A newly created object.
*/
addObject(parent?: Object3D | null): Object3D;
/**
* Batch-add objects to the scene.
*
* Will provide better performance for adding multiple objects (e.g. > 16)
* than calling {@link Scene#addObject} repeatedly in a loop.
*
* By providing upfront information of how many objects will be required,
* the engine is able to batch-allocate the required memory rather than
* convervatively grow the memory in small steps.
*
* @experimental This API might change in upcoming versions.
*
* @param count Number of objects to add.
* @param parent Parent object or `null`, default `null`.
* @param componentCountHint Hint for how many components in total will
* be added to the created objects afterwards, default `0`.
* @returns Newly created objects
*/
addObjects(count: number, parent?: Object3D | null, componentCountHint?: number): Object3D[];
/**
* Pre-allocate memory for a given amount of objects and components.
*
* Will provide better performance for adding objects later with {@link Scene#addObject}
* and {@link Scene#addObjects}.
*
* By providing upfront information of how many objects will be required,
* the engine is able to batch-allocate the required memory rather than
* conservatively grow the memory in small steps.
*
* **Experimental:** This API might change in upcoming versions.
*
* @param objectCount Number of objects to add.
* @param componentCountPerType Amount of components to
* allocate for {@link Object3D.addComponent}, e.g. `{mesh: 100, collision: 200, "my-comp": 100}`.
* @since 0.8.10
*/
reserveObjects(objectCount: number, componentCountPerType: Record<string, number>): void;
/**
* Root object's children.
*
* See {@link Object3D.getChildren} for more information.
*
* @param out Destination array, expected to have at least `this.childrenCount` elements.
* @returns The `out` parameter.
*/
getChildren(out?: Object3D[]): Object3D[];
/** @overload */
getComponents<K extends keyof NativeComponents>(typeOrClass: K): NativeComponents[K][];
/** @overload */
getComponents(typeOrClass: string): Component[];
/**
* Get all the components of a given type.
*
* #### Usage
*
* ```js
* const meshes = scene.getComponents('mesh');
* const zombies = scene.getComponents(ZombieComponent);
* ```
*
* @param typeOrClass Typename to create a component of. Can be native or
* custom JavaScript component type. It's also possible to give a class definition.
* In this case, the method will use the `class.TypeName` field.
* @returns An array containing all components in this scene.
* Returns an empty array if the component isn't registered.
*/
getComponents<T extends Component>(typeOrClass: ComponentConstructor<T>): T[];
/** @overload */
getActiveComponents<K extends keyof NativeComponents>(typeOrClass: K): NativeComponents[K][];
/** @overload */
getActiveComponents(typeOrClass: string): Component[];
/**
* Get all the **active** components of a given type.
*
* ```js
* const zombies = scene.getActiveComponents(ZombieComponent);
* for(const zombie of zombies) zombie.active = false;
*
* const list = scene.getActiveComponents(ZombieComponent);
* console.log(list.length); // Prints `0`
* ```
*
* @param typeOrClass Typename to create a component of. Can be native or
* custom JavaScript component type. It's also possible to give a class definition.
* In this case, the method will use the `class.TypeName` field.
* @returns An array containing all components in this scene.
* Returns an empty array if the component isn't registered.
*/
getActiveComponents<T extends Component>(typeOrClass: ComponentConstructor<T>): T[];
/**
* Top-level objects of this scene.
*
* See {@link Object3D.children} for more information.
*
* @since 1.2.0
*/
get children(): Object3D[];
/** The number of children of the root object. */
get childrenCount(): number;
/**
* Search for objects matching the name.
*
* See {@link Object3D.findByName} for more information.
*
* @param name The name to search for.
* @param recursive If `true`, the method will look at all the objects of
* this scene. If `false`, this method will only perform the search in
* root objects.
* @returns An array of {@link Object3D} matching the name.
*
* @since 1.2.0
*/
findByName(name: string, recursive?: boolean): Object3D[];
/**
* Search for all **top-level** objects matching the name.
*
* See {@link Object3D.findByNameDirect} for more information.
*
* @param name The name to search for.
* @returns An array of {@link Object3D} matching the name.
*
* @since 1.2.0
*/
findByNameDirect(name: string): Object3D[];
/**
* Search for **all objects** matching the name.
*
* See {@link Object3D.findByNameRecursive} for more information.
*
* @param name The name to search for.
* @returns An array of {@link Object3D} matching the name.
*
* @since 1.2.0
*/
findByNameRecursive(name: string): Object3D[];
/**
* Wrap an object ID using {@link Object}.
*
* @note This method performs caching and will return the same
* instance on subsequent calls.
*
* @param objectId ID of the object to create.
*
* @returns The object
*/
wrap(objectId: number): Object3D;
/**
* Destroy the scene.
*
* For now, destroying a scene doesn't remove the resources it references. Thus,
* you will need to reload a main scene to free the memory.
*
* For more information about destruction, have a look at the {@link Scene.destroy} method.
*/
destroy(): void;
/**
* `true` if the scene is active, `false` otherwise.
*
* Always false for {@link Prefab} and {@link PrefabGLTF}.
*/
get isActive(): boolean;
/**
* Relative directory of the scene that was loaded.
*
* This is used for loading any files relative to the scene.
*/
get baseURL(): string;
/**
* Filename used when loading the file.
*
* If the scenes was loaded from memory and no filename was provided,
* this accessor will return an empty string.
*/
get filename(): string;
/** Animation resources */
get animations(): ResourceManager<Animation>;
/** Skin resources */
get skins(): ResourceManager<Skin>;
/** Hosting engine instance. */
get engine(): WonderlandEngine;
/**
* `true` if the object is destroyed, `false` otherwise.
*
* If {@link WonderlandEngine.erasePrototypeOnDestroy} is `true`,
* reading a class attribute / method will throw.
*/
get isDestroyed(): boolean;
toString(): string;
/**
* Checks that the input's scene is the same as this instance.
*
* It is forbidden to mix objects and components from different scenes, e.g.,
*
* ```js
* const objA = sceneA.addObject();
* const objB = sceneA.addObject();
* objA.parent = objB; // Throws
* ```
*
* @param other Object / component to check.
*
* @throws If other's scene isn't the same reference as this.
*/
assertOrigin(other: Object3D | Component | SceneResource | undefined | null): void;
/**
* Download components and initialize the scene.
*
* @hidden
*/
_initialize(): void;
/**
* Perform cleanup upon object destruction.
*
* @param localId The id to destroy.
*
* @hidden
*/
_destroyObject(localId: number): void;
/**
* Performs JavaScript only destrution of a component.
*
* @note Prefer to use this method to manually calling the destruction code,
* to protect the user from illegal method calls in {@link Component.onDestroy}.
*
* @param manager The component manager index.
* @param id The component id.
*
* @hidden
*/
_destroyComponent(manager: number, id: number): void;
}