@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
text/typescript
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.
*
* 
*
* **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)
}
}
}
}