import Clip from './Clip'; import quat from '../glmatrix/quat'; import vec3 from '../glmatrix/vec3'; /** * * Animation clip that manage a collection of {@link clay.animation.SamplerTrack} * @constructor * @alias clay.animation.TrackClip * * @extends clay.animation.Clip * @param {Object} [opts] * @param {string} [opts.name] * @param {Object} [opts.target] * @param {number} [opts.life] * @param {number} [opts.delay] * @param {number} [opts.gap] * @param {number} [opts.playbackRatio] * @param {boolean|number} [opts.loop] If loop is a number, it indicate the loop count of animation * @param {string|Function} [opts.easing] * @param {Function} [opts.onframe] * @param {Function} [opts.onfinish] * @param {Function} [opts.onrestart] * @param {Array.} [opts.tracks] */ var TrackClip = function (opts) { opts = opts || {}; Clip.call(this, opts); /** * * @type {clay.animation.SamplerTrack[]} */ this.tracks = opts.tracks || []; this.calcLifeFromTracks(); }; TrackClip.prototype = Object.create(Clip.prototype); TrackClip.prototype.constructor = TrackClip; TrackClip.prototype.step = function (time, dTime, silent) { var ret = Clip.prototype.step.call(this, time, dTime, true); if (ret !== 'finish') { var time = this.getElapsedTime(); // TODO life may be changed. if (this._range) { time = this._range[0] + time; } this.setTime(time); } // PENDING Schedule if (!silent && ret !== 'paused') { this.fire('frame'); } return ret; }; /** * @param {Array.} range */ TrackClip.prototype.setRange = function (range) { this.calcLifeFromTracks(); this._range = range; if (range) { range[1] = Math.min(range[1], this.life); range[0] = Math.min(range[0], this.life); this.life = (range[1] - range[0]); } }; TrackClip.prototype.setTime = function (time) { for (var i = 0; i < this.tracks.length; i++) { this.tracks[i].setTime(time); } }; TrackClip.prototype.calcLifeFromTracks = function () { this.life = 0; for (var i = 0; i < this.tracks.length; i++) { this.life = Math.max(this.life, this.tracks[i].getMaxTime()); } }; /** * @param {clay.animation.SamplerTrack} track */ TrackClip.prototype.addTrack = function (track) { this.tracks.push(track); this.calcLifeFromTracks(); }; /** * @param {clay.animation.SamplerTrack} track */ TrackClip.prototype.removeTarck = function (track) { var idx = this.tracks.indexOf(track); if (idx >= 0) { this.tracks.splice(idx, 1); } }; /** * @param {number} startTime * @param {number} endTime * @param {boolean} isLoop * @return {clay.animation.TrackClip} */ TrackClip.prototype.getSubClip = function (startTime, endTime, isLoop) { var subClip = new TrackClip({ name: this.name }); for (var i = 0; i < this.tracks.length; i++) { var subTrack = this.tracks[i].getSubTrack(startTime, endTime); subClip.addTrack(subTrack); } if (isLoop !== undefined) { subClip.setLoop(isLoop); } subClip.life = endTime - startTime; return subClip; }; /** * 1d blending from two skinning clips * @param {clay.animation.TrackClip} clip1 * @param {clay.animation.TrackClip} clip2 * @param {number} w */ TrackClip.prototype.blend1D = function (clip1, clip2, w) { for (var i = 0; i < this.tracks.length; i++) { var c1 = clip1.tracks[i]; var c2 = clip2.tracks[i]; var tClip = this.tracks[i]; tClip.blend1D(c1, c2, w); } }; /** * Additive blending from two skinning clips * @param {clay.animation.TrackClip} clip1 * @param {clay.animation.TrackClip} clip2 */ TrackClip.prototype.additiveBlend = function (clip1, clip2) { for (var i = 0; i < this.tracks.length; i++) { var c1 = clip1.tracks[i]; var c2 = clip2.tracks[i]; var tClip = this.tracks[i]; tClip.additiveBlend(c1, c2); } }; /** * Subtractive blending from two skinning clips * @param {clay.animation.TrackClip} clip1 * @param {clay.animation.TrackClip} clip2 */ TrackClip.prototype.subtractiveBlend = function (clip1, clip2) { for (var i = 0; i < this.tracks.length; i++) { var c1 = clip1.tracks[i]; var c2 = clip2.tracks[i]; var tClip = this.tracks[i]; tClip.subtractiveBlend(c1, c2); } }; /** * 2D blending from three skinning clips * @param {clay.animation.TrackClip} clip1 * @param {clay.animation.TrackClip} clip2 * @param {clay.animation.TrackClip} clip3 * @param {number} f * @param {number} g */ TrackClip.prototype.blend2D = function (clip1, clip2, clip3, f, g) { for (var i = 0; i < this.tracks.length; i++) { var c1 = clip1.tracks[i]; var c2 = clip2.tracks[i]; var c3 = clip3.tracks[i]; var tClip = this.tracks[i]; tClip.blend2D(c1, c2, c3, f, g); } }; /** * Copy SRT of all joints clips from another TrackClip * @param {clay.animation.TrackClip} clip */ TrackClip.prototype.copy = function (clip) { for (var i = 0; i < this.tracks.length; i++) { var sTrack = clip.tracks[i]; var tTrack = this.tracks[i]; vec3.copy(tTrack.position, sTrack.position); vec3.copy(tTrack.scale, sTrack.scale); quat.copy(tTrack.rotation, sTrack.rotation); } }; TrackClip.prototype.clone = function () { var clip = Clip.prototype.clone.call(this); for (var i = 0; i < this.tracks.length; i++) { clip.addTrack(this.tracks[i].clone()); } clip.life = this.life; return clip; }; export default TrackClip;