@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
TypeScript
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 {};