whs
Version:
Super-fast 3D framework for Web Applications & Games. Based on Three.js
99 lines (86 loc) • 2.56 kB
JavaScript
import {
AnimationMixer,
AnimationClip,
Clock
} from 'three';
import {Loop} from '../../core/Loop';
/**
* @class AnimationModule
* @category modules/mesh
* @description Convenience module that wraps the <a href='https://threejs.org/docs/#manual/introduction/Animation-system'>three.js animation system</a>
* @param {App} app - the app
* @param {Boolean} [isDeferred=false] - set to true if animation should not start automatically
* @param {Object} [params={speed: 1}] - the params
* @memberof module:modules/mesh
* @example <caption>Create animation module and play a given clip of an imported model</caption>
* const animationModule = new AnimationModule(app, false, {
* speed: 1.2 // speed up animation by 20%
* });
*
* new Importer({
* parser(geometry, materials) {
* // Override parse to generate a skinnedMesh, needed for skinned models
* return new THREE.SkinnedMesh(geometry, materials);
* },
*
* url: `path/to/model.json`,
* useCustomMaterial: true,
*
* material: new THREE.MeshStandardMaterial({
* skinning: true
* }),
*
* modules: [animationModule]
* }).addTo(app).then(() => {
* // adding model to app returns a promise, so pipe the function to kick off the animation clip
* animationModule.play('clipName');
* });
*/
export class AnimationModule {
constructor(app, isDeferred, params = {}) {
this.params = Object.assign({
speed: 1
}, params);
this.clock = new Clock();
this.app = app;
this.isDeferred = isDeferred;
}
/**
* @method play
* @instance
* @description Plays the given clip name
* @param {String} clipName - the clip to play
* @memberof module:modules/mesh.AnimationModule
*/
play(clipName) {
const clip = AnimationClip.findByName(this.clips, clipName);
const action = this.mixer.clipAction(clip);
action.play();
}
/**
* @method update
* @instance
* @description Update the mixer (being called on frame animation loop)
* @memberof module:modules/mesh.AnimationModule
*/
update() {
if (this.mixer) this.mixer.update(this.clock.getDelta() * this.params.speed);
}
integrate(self) {
self.loop = new Loop(() => {
self.update();
});
if (!self.isDeferred) self.loop.start(self.app);
}
manager(manager) {
manager.define('animation');
}
bridge = {
mesh(mesh, self) {
mesh.geometry.skeleton = mesh.skeleton;
self.mixer = new AnimationMixer(mesh.geometry);
self.clips = mesh.geometry.animations;
return mesh;
}
}
}