UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

188 lines (187 loc) 7.42 kB
import { Behaviour } from "./Component.js"; export declare function initSkyboxAttributes(): void; /** * The [RemoteSkybox](https://engine.needle.tools/docs/api/RemoteSkybox) component allows you to set the skybox or environment texture of a scene from a URL, a local file or a static skybox name. * It supports .hdr, .exr, .jpg, .png, and .ktx2 files. * * **HTML Attributes:** * You can control skybox and environment from HTML using `<needle-engine>` attributes: * - `background-image`: Sets the scene background/skybox image * - `environment-image`: Sets the scene environment map (for reflections and lighting) * * These attributes accept URLs or magic skybox names (see examples below). * * **Magic Skybox Names:** * Built-in optimized skyboxes hosted on Needle CDN: * - `"studio"` - Neutral studio lighting (default) * - `"blurred-skybox"` - Blurred environment * - `"quicklook"` - Apple QuickLook object mode style * - `"quicklook-ar"` - Apple QuickLook AR mode style * * ### Events * - `dropped-unknown-url`: Emitted when a file is dropped on the scene. The event detail contains the sender, the url and a function to apply the url. * * @example Using HTML attributes * ```html * <needle-engine * background-image="https://example.com/skybox.hdr" * environment-image="studio"> * </needle-engine> * ``` * * @example Using magic skybox names * ```html * <needle-engine background-image="studio"></needle-engine> * <needle-engine environment-image="quicklook"></needle-engine> * ``` * * @example Adding via code * ```ts * GameObject.addComponent(gameObject, RemoteSkybox, { * url: "https://example.com/skybox.hdr", * background: true, * environment: true * }); * ``` * * @example Handle custom dropped URL * ```ts * const skybox = GameObject.addComponent(gameObject, RemoteSkybox); * skybox.addEventListener("dropped-unknown-url", (evt) => { * let url = evt.detail.url; * console.log("User dropped file", url); * // change url or resolve it differently * url = "https://example.com/skybox.hdr"; * // apply the url * evt.detail.apply(url); * }); * ``` * * @example Update skybox at runtime * ```ts * skybox.setSkybox("https://example.com/skybox.hdr"); * // Or use a magic name: * skybox.setSkybox("studio"); * ``` * * @summary Sets the skybox or environment texture of a scene * @category Rendering * @group Components * @see {@link Camera} for clearFlags and background control * @link https://engine.needle.tools/docs/html.html#needle-engine-element */ export declare class RemoteSkybox extends Behaviour { /** * URL to a remote skybox. * To update the skybox/environment map use `setSkybox(url)`. * * The url can also be set to a magic skybox name. * Magic name options are: "quicklook", "quicklook-ar", "studio", "blurred-skybox". * These will resolve to built-in skyboxes hosted on the Needle CDN that are static, optimized for the web and will never change. * * @example * ```ts * skybox.url = "https://example.com/skybox.hdr"; * ``` */ url: MagicSkyboxName | AnyString; /** * When enabled a user can drop a link to a skybox image on the scene to set the skybox. * @default true */ allowDrop: boolean; /** * When enabled the skybox will be set as the background of the scene. * @default true */ background: boolean; /** * When enabled the skybox will be set as the environment of the scene (to be used as environment map for reflections and lighting) * @default true */ environment: boolean; /** * When enabled dropped skybox urls (or assigned skybox urls) will be networked to other users in the same networked room. * @default true */ allowNetworking: boolean; private _prevUrl?; private _prevLoadedEnvironment?; /** Promise returned by the most recent in-flight {@link setSkybox} load. * The URL it's loading is `_prevUrl` (set synchronously before the * awaited work begins). When a second `setSkybox(sameUrl)` comes in * while `_prevLoadedEnvironment` hasn't been populated yet, we return * this promise instead of kicking off a duplicate `loadPMREM` — same * URL, same texture, no reason to race two loads. * * Without this, the create path fetches the same URL twice: * `createRemoteSkyboxComponent` calls `setSkybox(url)` eagerly to get * a promise for the ContextCreationStart barrel, AND the component's * `onEnable()` lifecycle also calls `setSkybox(this.url)` — both * before `_prevLoadedEnvironment` is populated, so the fast-path cache * check doesn't fire and `loadPMREM` runs twice. */ private _inFlightLoad?; private _prevEnvironment; private _prevBackground; /** * If our texture is still installed in `scene.environment` / * `scene.background`, restore the snapshot {@link apply} took before it * wrote there. Slots owned by something else are left alone. * * @returns `true` if either slot was ours (and was reverted). */ private revertAppliedSceneState; /** * Discard the result of any in-flight {@link setSkybox} call AND revert * any already-applied skybox state from this RemoteSkybox so the scene * looks as if this component never ran. * * Automatically called when the `background-image` / `environment-image` * HTML attribute is cleared — callers normally don't need to invoke it * directly. * * Covers two races: * * 1. **In-flight load.** `setSkybox` re-checks `_prevUrl` after `await * loadPMREM(...)` and bails if it changed; resetting it here trips * that check on the in-flight call. * 2. **Already-applied load.** If `loadPMREM` resolved fast (HTTP cache * hit), `apply()` already ran. The in-flight check above doesn't * help — `revertAppliedSceneState` restores the prior snapshot. * * NOTE: this does NOT abort the underlying network fetch / PMREM * generation — `loadPMREM` has no cancellation. It only flips state so * `setSkybox` bails after the await and skips `apply()`. The texture * returned by `loadPMREM` in those bail-out branches (`_prevUrl !== url` * and disabled/destroyed) is still dropped without `dispose()` — a small * GPU leak that should be fixed at those sites. * @internal */ discardPendingLoad(): void; /** @internal */ onEnable(): void; /** @internal */ onDisable(): void; private urlChangedSyncField; /** * Set the skybox from a given url * @param url The url of the skybox image * @param name Define name of the file with extension if it isn't apart of the url * @returns Whether the skybox was successfully set */ setSkybox(url: MagicSkyboxName | AnyString | undefined | null, name?: string): Promise<boolean>; private apply; private readonly validProtocols; private readonly validTextureTypes; private isRemoteTexture; private isValidTextureType; private registerDropEvents; private unregisterDropEvents; private onDragOverEvent; private onDrop; } type MagicSkyboxName = "studio" | "blurred-skybox" | "quicklook-ar" | "quicklook"; type AnyString = string & { _brand?: never; }; export {};