icy3dw/src/client/object/pony.ts

102 lines
2.9 KiB
TypeScript
Raw Normal View History

2022-04-09 11:29:54 +00:00
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
import modelLoaderInstance from './pony-loader';
2022-04-10 06:52:50 +00:00
import { CharacterPacket, FullStatePacket } from '../../common/types/packet';
2022-04-09 11:29:54 +00:00
import { NameTag } from './nametag';
import { CanvasUtils } from './canvas-utils';
2022-04-10 08:33:52 +00:00
import {
Mesh,
MeshStandardMaterial,
Color,
AnimationAction,
AnimationMixer,
Object3D,
Vector3,
} from 'three';
2022-04-09 11:29:54 +00:00
2022-04-09 16:06:53 +00:00
const nameTagBuilder = new CanvasUtils({
fill: false,
textBorderColor: '#000',
foregroundColor: '#fff',
textShadowBlur: 2,
textBorderSize: 1,
});
2022-04-09 11:29:54 +00:00
export class PonyEntity {
2022-04-10 08:33:52 +00:00
public velocity = new Vector3(0, 0, 0);
public angularVelocity = new Vector3(0, 0, 0);
public mixer!: AnimationMixer;
public container!: Object3D;
public model!: Object3D;
public material!: MeshStandardMaterial;
2022-04-09 11:29:54 +00:00
public walkAnimationState = 0;
2022-04-10 08:33:52 +00:00
public idleAction: AnimationAction;
public walkAction: AnimationAction;
2022-04-09 11:29:54 +00:00
public nameTag?: NameTag;
2022-04-09 14:49:30 +00:00
public changes: FullStatePacket = {};
2022-04-09 11:29:54 +00:00
initialize() {
this.model = (SkeletonUtils as any).clone(modelLoaderInstance.ponyModel);
2022-04-10 06:52:50 +00:00
this.material = (
(this.model.children[0].children[1] as Mesh)
.material as MeshStandardMaterial
).clone();
(this.model.children[0].children[1] as Mesh).material = this.material;
2022-04-10 08:33:52 +00:00
this.mixer = new AnimationMixer(this.model);
2022-04-09 11:29:54 +00:00
this.idleAction = this.mixer.clipAction(modelLoaderInstance.animations[0]);
this.walkAction = this.mixer.clipAction(modelLoaderInstance.animations[2]);
this.idleAction.play();
2022-04-10 08:33:52 +00:00
this.container = new Object3D();
2022-04-09 11:29:54 +00:00
this.container.add(this.model);
}
update(dt: number) {
2022-04-09 12:57:20 +00:00
this.container.position.add(this.velocity.clone().multiplyScalar(dt));
2022-04-09 11:29:54 +00:00
this.container.rotation.setFromVector3(
2022-04-10 08:33:52 +00:00
new Vector3(
2022-04-09 11:29:54 +00:00
this.container.rotation.x,
this.container.rotation.y,
this.container.rotation.z,
2022-04-09 12:57:20 +00:00
).add(this.angularVelocity.clone().multiplyScalar(dt)),
2022-04-09 11:29:54 +00:00
);
this.mixer.update(dt);
}
2022-04-10 06:52:50 +00:00
dispose() {
this.model = null;
this.material.dispose();
this.nameTag?.dispose();
}
2022-04-09 11:29:54 +00:00
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();
}
}
2022-04-10 06:52:50 +00:00
public setColor(color: number | string) {
this.material.color = new Color(color);
}
public setCharacter(packet: CharacterPacket) {
if (packet.color) {
this.setColor(packet.color);
}
}
2022-04-09 11:29:54 +00:00
}