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.

106 lines (99 loc) 4.11 kB
import { Mesh } from "three"; import { Gizmos } from "../engine/engine_gizmos.js"; import { syncDestroy } from "../engine/engine_networking_instantiate.js"; import { getParam } from "../engine/engine_utils.js"; import { BoxHelperComponent } from "./BoxHelperComponent.js"; import { Behaviour, GameObject } from "./Component.js"; import { UsageMarker } from "./Interactable.js"; const debug = getParam("debugdeletable"); /** * The [DeleteBox](https://engine.needle.tools/docs/api/DeleteBox) component creates an invisible deletion zone that destroys objects entering it. * Works with objects that have a {@link Deletable} component attached. * * ![](https://cloud.needle.tools/-/media/J-Gmdhl214kfdjkfYViG8g.gif) * * **Use cases:** * - Trash bins in sandbox builders * - Kill zones in physics simulations * - Cleanup areas for multiplayer scenes * * **Setup:** * 1. Add DeleteBox to a GameObject with a BoxCollider-like shape * 2. Add {@link Deletable} component to objects that should be destroyable * 3. Objects entering the box will be destroyed (synced across network) * * **Debug:** Use `?debugdeletable` URL parameter to visualize deletion areas. * * - Example: https://engine.needle.tools/samples/collaborative-sandbox * * @example Create a deletion zone * ```ts * const trashBin = trashBinModel.addComponent(DeleteBox); * // Objects with Deletable component will be destroyed when entering * ``` * * @summary Box area that deletes objects entering it * @category Interactivity * @group Components * @see {@link Deletable} - Add to objects that can be destroyed * @see {@link Duplicatable} for spawning objects * @see {@link DragControls} for moving objects */ export class DeleteBox extends BoxHelperComponent { static _instances: DeleteBox[] = []; onEnable(): void { DeleteBox._instances.push(this); } onDisable(): void { const idx = DeleteBox._instances.indexOf(this); if (idx >= 0) DeleteBox._instances.splice(idx, 1); } } /** * Marks a GameObject as deletable by {@link DeleteBox} zones. * Objects with this component will be destroyed (and synced across network) * when they enter a DeleteBox area. * * **Note:** Objects currently being used (with {@link UsageMarker}) are protected from deletion. * * @example Make an object deletable * ```ts * const deletable = spawnedObject.addComponent(Deletable); * // Object can now be destroyed by entering a DeleteBox * ``` * * @summary Marks object as destroyable by DeleteBox * @category Interactivity * @group Components * @see {@link DeleteBox} for the deletion trigger * @see {@link UsageMarker} for protecting objects in use */ export class Deletable extends Behaviour { update(): void { for (const box of DeleteBox._instances) { const obj = this.gameObject as unknown as Mesh; const res = box.isInBox(obj); if (res === true) { const marker = GameObject.getComponentInParent(this.gameObject, UsageMarker); if (!marker) { if (debug) { try { if (box["box"]) { const deleteBoxArea = box["box"]; const deletedObjectArea = BoxHelperComponent["testBox"]; Gizmos.DrawWireBox3(deleteBoxArea, 0xff0000, 5); Gizmos.DrawWireBox3(deletedObjectArea, 0x0000ff, 5); console.log("DeleteBox: Destroying", this.gameObject, { deleteBoxArea, deletedObjectArea }); } else { console.log("DeleteBox: Destroying", this.gameObject); } } catch (_e) {} } syncDestroy(this.gameObject, this.context.connection); } else if (debug) console.warn("DeleteBox: Not deleting object with usage marker", this.guid, marker) } } } }