import { PropertyBindingMixer } from './PropertyBindingMixer.js';
/**
* The AnimationMixer is a player for animations on a particular object in the scene.
* When multiple objects in the scene are animated independently, one AnimationMixer may be used for each object.
* @constructor
* @memberof zen3d
*/
function AnimationMixer() {
this._clips = {};
this._bindings = {};
this._activeClips = {};
}
Object.assign(AnimationMixer.prototype, /** @lends zen3d.AnimationMixer.prototype */{
add: function(clip) {
if (this._clips[clip.name] !== undefined) {
console.warn("AnimationMixer.add: already has clip: " + clip.name);
return;
}
var tracks = clip.tracks;
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
var trackName = track.name;
var binding;
if (!this._bindings[trackName]) {
binding = new PropertyBindingMixer(track.target, track.propertyPath, track.valueTypeName, track.valueSize);
this._bindings[trackName] = binding;
} else {
binding = this._bindings[trackName];
}
binding.referenceCount++;
}
this._clips[clip.name] = clip;
},
remove: function(clip) {
if (!this._clips[clip.name]) {
console.warn("AnimationMixer.remove: has no clip: " + clip.name);
return;
}
var tracks = clip.tracks;
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
var trackName = track.name;
var binding = this._bindings[trackName];
if (binding) {
binding.referenceCount--;
}
if (binding.referenceCount <= 0) {
delete this._bindings[trackName];
}
}
delete this._clips[clip.name];
},
play: function(name, weight) {
if (this._activeClips[name] !== undefined) {
console.warn("AnimationMixer.play: clip " + name + " is playing.");
return;
}
this._activeClips[name] = (weight === undefined) ? 1 : weight;
var clip = this._clips[name];
if (!clip) {
console.warn("AnimationMixer.stop: clip " + name + " is not found.");
return;
}
clip.frame = 0;
var tracks = clip.tracks;
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
var trackName = track.name;
var binding = this._bindings[trackName];
if (binding) {
if (binding.useCount++ === 0) {
binding.saveOriginalState();
}
}
}
},
stop: function(name) {
if (this._activeClips[name] === undefined) {
console.warn("AnimationMixer.stop: clip " + name + " is not playing.");
return;
}
delete this._activeClips[name];
var clip = this._clips[name];
if (!clip) {
console.warn("AnimationMixer.stop: clip " + name + " is not found.");
return;
}
var tracks = clip.tracks;
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
var trackName = track.name;
var binding = this._bindings[trackName];
if (binding && binding.useCount > 0) {
if (--binding.useCount === 0) {
binding.restoreOriginalState();
}
}
}
},
update: function(t) {
for (var name in this._activeClips) {
var clip = this._clips[name];
var weight = this._activeClips[name];
clip.update(t, this._bindings, weight);
}
for (var key in this._bindings) {
if (this._bindings[key].useCount > 0) {
this._bindings[key].apply();
}
}
},
// set clip weight
// this method can be used for cross fade
setClipWeight: function(name, weight) {
if (this._activeClips[name] === undefined) {
console.warn("AnimationMixer.stop: clip " + name + " is not playing.");
return;
}
this._activeClips[name] = weight;
},
// return all clip names of this animation
getAllClipNames: function() {
var array = [];
for (var key in this._clips) {
array.push(key);
}
return array;
}
});
export { AnimationMixer };