@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
154 lines • 5.63 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Layers } from "three";
import { serializable } from "../engine/engine_serialization_decorator.js";
import { getParam } from "../engine/engine_utils.js";
import { BoxHelperComponent } from "./BoxHelperComponent.js";
import { Behaviour, GameObject } from "./Component.js";
import { EventList } from "./EventList.js";
const debug = getParam("debugspatialtrigger");
const layer1 = new Layers();
const layer2 = new Layers();
function testMask(mask1, mask2) {
layer1.mask = mask1;
layer2.mask = mask2;
return layer1.test(layer2);
}
/**
* @category Interactivity
* @group Components
*/
export class SpatialTriggerReceiver extends Behaviour {
// currently Layers in unity but maybe this should be a string or plane number? Or should it be a bitmask to allow receivers use multiple triggers?
triggerMask = 0;
onEnter;
onStay;
onExit;
start() {
if (debug)
console.log(this.name, this.triggerMask, this);
}
update() {
this.currentIntersected.length = 0;
for (const trigger of SpatialTrigger.triggers) {
if (testMask(trigger.triggerMask, this.triggerMask)) {
if (trigger.test(this.gameObject)) {
this.currentIntersected.push(trigger);
}
}
}
for (let i = this.lastIntersected.length - 1; i >= 0; i--) {
const last = this.lastIntersected[i];
if (this.currentIntersected.indexOf(last) < 0) {
this.onExitTrigger(last);
this.lastIntersected.splice(i, 1);
}
}
for (const cur of this.currentIntersected) {
if (this.lastIntersected.indexOf(cur) < 0)
this.onEnterTrigger(cur);
this.onStayTrigger(cur);
}
this.lastIntersected.length = 0;
this.lastIntersected.push(...this.currentIntersected);
}
currentIntersected = [];
lastIntersected = [];
onEnterTrigger(trigger) {
if (debug)
console.log("ENTER TRIGGER", this.name, trigger.name, this, trigger);
trigger.raiseOnEnterEvent(this);
this.onEnter?.invoke(this, trigger);
}
onExitTrigger(trigger) {
if (debug)
console.log("EXIT TRIGGER", this.name, trigger.name, this, trigger);
trigger.raiseOnExitEvent(this);
this.onExit?.invoke(this, trigger);
}
onStayTrigger(trigger) {
trigger.raiseOnStayEvent(this);
this.onStay?.invoke(this, trigger);
}
}
__decorate([
serializable()
], SpatialTriggerReceiver.prototype, "triggerMask", void 0);
__decorate([
serializable(EventList)
], SpatialTriggerReceiver.prototype, "onEnter", void 0);
__decorate([
serializable(EventList)
], SpatialTriggerReceiver.prototype, "onStay", void 0);
__decorate([
serializable(EventList)
], SpatialTriggerReceiver.prototype, "onExit", void 0);
/**
* A trigger that can be used to detect if an object is inside a box.
* @category Interactivity
* @group Components
*/
export class SpatialTrigger extends Behaviour {
static triggers = [];
triggerMask;
boxHelper;
start() {
if (debug)
console.log(this.name, this.triggerMask, this);
}
onEnable() {
SpatialTrigger.triggers.push(this);
if (!this.boxHelper) {
this.boxHelper = GameObject.addComponent(this.gameObject, BoxHelperComponent);
this.boxHelper?.showHelper(null, debug);
}
}
onDisable() {
SpatialTrigger.triggers.splice(SpatialTrigger.triggers.indexOf(this), 1);
}
test(obj) {
if (!this.boxHelper)
return false;
return this.boxHelper.isInBox(obj) ?? false;
}
// private args: SpatialTriggerEventArgs = new SpatialTriggerEventArgs();
raiseOnEnterEvent(rec) {
// this.args.trigger = this;
// this.args.source = rec;
GameObject.foreachComponent(this.gameObject, c => {
if (c === rec)
return;
if (c instanceof SpatialTriggerReceiver) {
c.onEnterTrigger(this);
}
}, false);
}
raiseOnStayEvent(rec) {
// this.args.trigger = this;
// this.args.source = rec;
GameObject.foreachComponent(this.gameObject, c => {
if (c === rec)
return;
if (c instanceof SpatialTriggerReceiver) {
c.onStayTrigger(this);
}
}, false);
}
raiseOnExitEvent(rec) {
GameObject.foreachComponent(this.gameObject, c => {
if (c === rec)
return;
if (c instanceof SpatialTriggerReceiver) {
c.onExitTrigger(this);
}
}, false);
}
}
__decorate([
serializable()
], SpatialTrigger.prototype, "triggerMask", void 0);
//# sourceMappingURL=SpatialTrigger.js.map