import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils'; import * as THREE from 'three'; import modelLoaderInstance from './pony-loader'; import { FullStatePacket } from '../../common/types/packet'; import { NameTag } from './nametag'; import { CanvasUtils } from './canvas-utils'; const nameTagBuilder = new CanvasUtils(); export class PonyEntity { public velocity = new THREE.Vector3(0, 0, 0); public angularVelocity = new THREE.Vector3(0, 0, 0); public mixer!: THREE.AnimationMixer; public container!: THREE.Object3D; public model!: THREE.Object3D; public walkAnimationState = 0; public idleAction: THREE.AnimationAction; public walkAction: THREE.AnimationAction; public nameTag?: NameTag; public changes: FullStatePacket = {}; initialize() { this.model = (SkeletonUtils as any).clone(modelLoaderInstance.ponyModel); this.mixer = new THREE.AnimationMixer(this.model); this.idleAction = this.mixer.clipAction(modelLoaderInstance.animations[0]); this.walkAction = this.mixer.clipAction(modelLoaderInstance.animations[2]); this.idleAction.play(); this.container = new THREE.Object3D(); this.container.add(this.model); } update(dt: number) { this.container.position.add(this.velocity.clone().multiplyScalar(dt)); this.container.rotation.setFromVector3( new THREE.Vector3( this.container.rotation.x, this.container.rotation.y, this.container.rotation.z, ).add(this.angularVelocity.clone().multiplyScalar(dt)), ); this.mixer.update(dt); } public addNameTag(name: string) { this.nameTag = new NameTag(nameTagBuilder, name); this.nameTag.tag.position.set(0, 1.8, 0.5); this.container.add(this.nameTag.tag); } public setWalkAnimationState(index: number) { const previousState = this.walkAnimationState; this.walkAnimationState = index; if (previousState === this.walkAnimationState) { return; } this.changes.animState = index; if (index === 1) { this.walkAction.reset().crossFadeFrom(this.idleAction, 0.5, false).play(); } else { this.walkAction.crossFadeTo(this.idleAction.reset(), 0.5, false).play(); } } }