@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.
239 lines (238 loc) • 9.58 kB
TypeScript
import { Object3D, Vector3 } from "three";
import { Model, Vec3 } from "../engine/engine_types.js";
import { Behaviour } from "./Component.js";
import { EventList } from "./EventList.js";
/**
* Events dispatched by the DropListener component
* @enum {string}
*/
export declare enum DropListenerEvents {
/**
* Dispatched when a file is dropped into the scene. The detail of the event is the {@link File} that was dropped.
* The event is called once for each dropped file.
*/
FileDropped = "file-dropped",
/**
* Dispatched when a new object is added to the scene. The detail of the event contains {@link DropListenerOnDropArguments} for the content that was added.
*/
ObjectAdded = "object-added"
}
/**
* Network event arguments passed between clients when using the DropListener with networking
*/
export declare type DropListenerNetworkEventArguments = {
/** Unique identifier of the sender */
guid: string;
/** Name of the dropped object */
name: string;
/** URL or array of URLs to the dropped content */
url: string | string[];
/** Worldspace point where the object was placed in the scene */
point: Vec3;
/** Bounding box size */
size: Vec3;
/** MD5 hash of the content for verification */
contentMD5: string;
};
/**
* Arguments provided to handlers when an object is dropped or added to the scene
*/
export declare type DropListenerOnDropArguments = {
/** The DropListener component that processed the drop event */
sender: DropListener;
/** The root object added to the scene */
object: Object3D;
/** The complete model with all associated data */
model: Model;
/** MD5 hash of the content for verification */
contentMD5: string;
/** The original dropped URL or File object */
dropped: URL | File | undefined;
};
/**
* DropListener enables drag-and-drop loading of 3D files directly into your scene.
* Users can drop glTF/GLB files onto the canvas to dynamically add new objects at runtime.
*
* [](https://engine.needle.tools/samples/droplistener)
*
* **Supported formats:** glTF, GLB, FBX, OBJ, USDZ, VRM
*
* **Key features:**
* - Drop files directly onto canvas or onto a specific {@link dropArea}
* - Paste URLs from clipboard (Ctrl/Cmd+V)
* - Auto-fit objects to a specific size with {@link fitIntoVolume}
* - Network sync to share dropped objects with other users
* - Special handling for GitHub and Polyhaven URLs
*
* **Events:**
* - `file-dropped` - Fired for each dropped file
* - `object-added` - Fired when object is loaded and added to scene
*
* **Debug:** Use `?debugdroplistener` URL parameter
*
* @example Listen for dropped objects
* ```ts
* const dropListener = myObject.addComponent(DropListener);
* dropListener.useNetworking = true;
* dropListener.fitIntoVolume = true;
*
* dropListener.on(DropListenerEvents.ObjectAdded, (evt) => {
* const { object, model } = evt.detail;
* console.log("Added:", object.name);
* });
* ```
*
* @example Load from URL programmatically
* ```ts
* const obj = await dropListener.loadFromURL("https://example.com/model.glb");
* ```
* Hint: We recommend to use {@link AssetReference} for preloading and referencing assets in code if you simply want to load a model.
*
* @summary Drag-and-drop file loading for 3D assets
* @category Asset Management
* @group Components
* @see {@link SceneSwitcher} for loading entire scenes
* @see {@link AssetReference} for preloading assets
* @see {@link SyncedTransform} for networking support
* @link https://engine.needle.tools/samples/droplistener for a live demo
*/
export declare class DropListener extends Behaviour {
/**
* When assigned, the DropListener will only accept files that are dropped on this specific object.
* This allows creating designated drop zones in your scene.
*/
dropArea?: Object3D;
/**
* When enabled, dropped objects will be automatically scaled to fit within the volume defined by fitVolumeSize.
* Useful for ensuring dropped models appear at an appropriate scale.
*
* **Tip**: Use the handy `fitObjectIntoVolume` function (`import { fitObjectIntoVolume } from "@needle-tools/engine"`) for custom fitting needs.
*
* @default false
*/
fitIntoVolume: boolean;
/**
* Defines the dimensions of the volume that dropped objects will be scaled to fit within.
* Only used when fitIntoVolume is enabled.
*/
fitVolumeSize: Vector3;
/**
* When enabled, dropped objects will be positioned at the point where the cursor hit the scene.
* When disabled, objects will be placed at the origin of the DropListener.
* @default true
*/
placeAtHitPosition: boolean;
/**
* When enabled, the DropListener will automatically synchronize dropped files to other connected clients.
* When a file is dropped locally, it will be uploaded to blob storage and the URL will be shared with other clients.
* @default false
*/
useNetworking: boolean;
/**
* Event list that gets invoked after a file has been successfully added to the scene.
* Receives {@link DropListenerOnDropArguments} containing the added object and related information.
* @event object-added
* @example
* ```typescript
* dropListener.onDropped.addEventListener((evt) => {
* console.log("Object added", evt.model);
* });
*/
onDropped: EventList<DropListenerOnDropArguments>;
/**
* Loads a file from the given URL and adds it to the scene.
* @returns A promise that resolves to the loaded object or null if loading failed.
*/
loadFromURL(url: string, data?: {
point?: Vec3;
size?: Vec3;
}): Promise<Object3D | null>;
/**
* Forgets all previously added objects.
* The droplistener will then not be able to remove previously added objects.
*/
forgetObjects(): void;
awake(): void;
/** @internal */
onEnable(): void;
/** @internal */
onDisable(): void;
/**
* Handles network events received from other clients containing information about dropped objects
* @param evt Network event data containing object information, position, and content URL
*/
private onNetworkEvent;
/**
* Handles clipboard paste events and processes them as potential URL drops
* Only URLs are processed by this handler, and only when editing is allowed
* @param evt The paste event
*/
private handlePaste;
/**
* Handles drag events over the renderer's canvas
* Prevents default behavior to enable drop events
* @param evt The drag event
*/
private onDrag;
/**
* Processes drop events to add files to the scene
* Handles both file drops and text/URL drops
* @param evt The drop event
*/
private onDrop;
/**
* Processes a dropped or pasted URL and tries to load it as a 3D model
* Handles special cases like GitHub URLs and Polyhaven asset URLs
* @param url The URL to process
* @param ctx Context information about where the drop occurred
* @param isRemote Whether this URL was shared from a remote client
* @returns The added object or null if loading failed
*/
private addFromUrl;
private _abort;
/**
* Processes dropped files and loads them as 3D models.
* When enabled, it also handles network drops (sending files between clients).
* Automatically handles cancelling previous uploads if new files are dropped.
* @param fileList Array of dropped files
* @param ctx Context information about where on the screen or in 3D space the drop occurred
*/
private addFromFiles;
/** Previously added objects */
private readonly _addedObjects;
private readonly _addedModels;
/**
* Removes all previously added objects from the scene
* @param doDestroy When true, destroys the objects; when false, just clears the references
*/
private removePreviouslyAddedObjects;
/**
* Adds a loaded model to the scene with proper positioning and scaling.
* Handles placement based on component settings and raycasting.
* If {@link fitIntoVolume} is enabled, the object will be scaled to fit within the volume defined by {@link fitVolumeSize}.
* @param data The loaded model data and content hash
* @param ctx Context information about where the drop occurred
* @param isRemote Whether this object was shared from a remote client
* @returns The added object or null if adding failed
*/
private onObjectLoaded;
/**
* Sends a network event to other clients about a dropped object
* Only triggered when networking is enabled and the connection is established
* @param url The URL to the content that was dropped
* @param obj The object that was added to the scene
* @param contentmd5 The content hash for verification
*/
private sendDropEvent;
/**
* Deletes remote state for this DropListener's objects
* Called when new files are dropped to clean up previous state
*/
private deleteDropEvent;
/**
* Tests if a drop event occurred within the designated drop area if one is specified
* @param ctx The drop context containing screen position information
* @returns True if the drop is valid (either no drop area is set or the drop occurred inside it)
*/
private testIfIsInDropArea;
}