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.

122 lines 4.69 kB
import { Vector3 } from "three"; import { OwnershipModel } from "../../engine/engine_networking.js"; import { Context } from "../../engine/engine_setup.js"; import * as utils from "../../engine/engine_three_utils.js"; import { TypeStore } from "../../engine/engine_typestore.js"; import { Behaviour, GameObject } from "../Component.js"; import { AvatarMarker } from "../webxr/WebXRAvatar.js"; /** @internal */ export class Avatar_POI { static Pois = []; static LastChangeTime = 0; static Add(context, obj, ignoredBy = null) { if (!obj) return; for (const e of this.Pois) { if (e.obj === obj) return; } this.Pois.push({ obj: obj, avatar: ignoredBy }); this.LastChangeTime = context.time.time; // console.log("Added", obj?.name); } static Remove(context, obj) { if (!obj) return; for (const e of this.Pois) { if (e.obj === obj) { this.Pois.splice(this.Pois.indexOf(e), 1); this.LastChangeTime = context?.time.time ?? Context.Current?.time.time; // console.log("Removed", obj?.name); return; } } } } var NetworkEvents; (function (NetworkEvents) { NetworkEvents["TargetChanged"] = "avatar-look-target-changed"; })(NetworkEvents || (NetworkEvents = {})); class TargetModel { guid; position = new Vector3(); } /** @internal */ export class Avatar_Brain_LookAt extends Behaviour { set controlledTarget(target) { this.target = target; // HACK const r = TypeStore.get("MoveRandom"); if (r && this.target) { const rm = GameObject.getComponent(this.target, r); if (rm) { rm.destroy(); } } // this.target.add(new AxesHelper(.1)); } // that target to copy positions into target = null; avatar = null; _model = null; _targetModel = new TargetModel(); _currentTargetObject = null; _lastUpdateTime = 0; _lookDuration = 0; _lastPoiChangedTime = 0; awake() { this.avatar = GameObject.getComponentInParent(this.gameObject, AvatarMarker); if (this.avatar) { const marker = GameObject.getComponentInParent(this.gameObject, AvatarMarker); this._model = new OwnershipModel(this.context.connection, this.guid); if (marker?.isLocalAvatar) { this._model.requestOwnership(); } } this.context.connection.beginListen(NetworkEvents.TargetChanged, (cb) => { if (this.target && cb && cb.guid === this.avatar?.guid) { utils.setWorldPosition(this.target, cb.position); } }); // console.log(this); } update() { const connected = this.context.connection.isConnected; if (!connected || this._model?.hasOwnership) { if (Avatar_POI.LastChangeTime !== this._lastPoiChangedTime) { this._lastPoiChangedTime = Avatar_POI.LastChangeTime; this._lookDuration = 0; } this.selectTarget(); // send target info if (this._currentTargetObject && this.context.time.frameCount % 10 === 0 && this.target) { const wp = utils.getWorldPosition(this._currentTargetObject); utils.setWorldPosition(this.target, wp); if (this.context.connection.isConnected && this.avatar) { this.context.connection.send(NetworkEvents.TargetChanged, this._targetModel); this._targetModel.guid = this.avatar.guid; this._targetModel.position.copy(wp); } } } } selectTarget() { // select random target const td = this.context.time.time - this._lastUpdateTime; if (td > this._lookDuration) { this._lastUpdateTime = this.context.time.time; this._lookDuration = Math.random() * .5 + .2; const pois = Avatar_POI.Pois; if (pois.length > 0) { const poi = pois[Math.floor(Math.random() * pois.length)]; if (poi && poi.obj) { if (poi.avatar && poi.avatar === this.avatar) return; this._currentTargetObject = poi.obj; // console.log(this._currentTargetObject); } } } } } //# sourceMappingURL=Avatar_Brain_LookAt.js.map