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.

80 lines 3.24 kB
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 { Object3D } from "three"; import { serializable } from "../../engine/engine_serialization_decorator.js"; import * as utils from "../../engine/engine_utils.js"; import { Behaviour, GameObject } from "../Component.js"; import { Voip } from "../Voip.js"; import { AvatarMarker } from "../webxr/WebXRAvatar.js"; const debug = utils.getParam("debugmouth"); /** @internal */ export class Avatar_MouthShapes extends Behaviour { idle = []; talking = []; marker = null; voip = null; lastMouthChangeTime = 0; mouthChangeLength = 0; awake() { setTimeout(() => { this.voip = GameObject.findObjectOfType(Voip, this.context); if (!this.marker) this.marker = GameObject.getComponentInParent(this.gameObject, AvatarMarker); }, 3000); } update() { if (!this.voip) return; if (this.context.time.frameCount % 10 !== 0) return; let id = this.marker?.connectionId ?? null; if (!id) { if (debug) id = null; return; } const freq = this.voip.getFrequency(id) ?? 0; this.updateLips(freq); } updateLips(frequency) { if (this.context.time.time - this.lastMouthChangeTime > this.mouthChangeLength) { this.mouthChangeLength = .05 + Math.random() * .1; if (this.talking && this.talking.length > 0 && frequency > 30) { this.lastMouthChangeTime = this.context.time.time; const index = Math.floor(Math.random() * this.talking.length); this.setMouthShapeActive(this.talking, index); } else if (this.idle.length > 0 && this.context.time.time - this.lastMouthChangeTime > .5) { this.lastMouthChangeTime = this.context.time.time; const index = Math.floor(Math.random() * this.idle.length); this.setMouthShapeActive(this.idle, index); } } } setMouthShapeActive(arr, index) { if (!arr) return; // hide other if (arr != this.idle) this.idle.map(i => i.visible = false); else this.talking.map(i => i.visible = false); for (let i = 0; i < arr.length; i++) { const shape = arr[i]; if (shape) { shape.visible = i === index; } } } } __decorate([ serializable(Object3D) ], Avatar_MouthShapes.prototype, "idle", void 0); __decorate([ serializable(Object3D) ], Avatar_MouthShapes.prototype, "talking", void 0); //# sourceMappingURL=Avatar_MouthShapes.js.map