playcanvas
Version:
PlayCanvas WebGL game engine
118 lines (115 loc) • 3.96 kB
JavaScript
import { path } from '../../core/path.js';
import { Quat } from '../../core/math/quat.js';
import { Vec3 } from '../../core/math/vec3.js';
import { Http, http } from '../../platform/net/http.js';
import { Animation, AnimationNode, AnimationKey } from '../../scene/animation/animation.js';
import { AnimEvents } from '../anim/evaluator/anim-events.js';
import { GlbParser } from '../parsers/glb-parser.js';
import { ResourceHandler } from './handler.js';
class AnimationHandler extends ResourceHandler {
constructor(app){
super(app, 'animation');
this.device = app.graphicsDevice;
this.assets = app.assets;
}
load(url, callback, asset) {
if (typeof url === 'string') {
url = {
load: url,
original: url
};
}
const options = {
retry: this.maxRetries > 0,
maxRetries: this.maxRetries
};
if (url.load.startsWith('blob:') || url.load.startsWith('data:')) {
if (path.getExtension(url.original).toLowerCase() === '.glb') {
options.responseType = Http.ResponseType.ARRAY_BUFFER;
} else {
options.responseType = Http.ResponseType.JSON;
}
}
http.get(url.load, options, (err, response)=>{
if (err) {
callback(`Error loading animation resource: ${url.original} [${err}]`);
} else {
if (path.getExtension(url.original).toLowerCase() === '.glb') {
GlbParser.parse('filename.glb', '', response, this.device, this.assets, asset?.options ?? {}, (err, parseResult)=>{
if (err) {
callback(err);
} else {
const animations = parseResult.animations;
if (asset?.data?.events) {
for(let i = 0; i < animations.length; i++){
animations[i].events = new AnimEvents(Object.values(asset.data.events));
}
}
parseResult.destroy();
callback(null, animations);
}
});
} else {
callback(null, this[`_parseAnimationV${response.animation.version}`](response));
}
}
});
}
open(url, data, asset) {
return data;
}
_parseAnimationV3(data) {
const animData = data.animation;
const anim = new Animation();
anim.name = animData.name;
anim.duration = animData.duration;
for(let i = 0; i < animData.nodes.length; i++){
const node = new AnimationNode();
const n = animData.nodes[i];
node._name = n.name;
for(let j = 0; j < n.keys.length; j++){
const k = n.keys[j];
const t = k.time;
const p = k.pos;
const r = k.rot;
const s = k.scale;
const pos = new Vec3(p[0], p[1], p[2]);
const rot = new Quat().setFromEulerAngles(r[0], r[1], r[2]);
const scl = new Vec3(s[0], s[1], s[2]);
const key = new AnimationKey(t, pos, rot, scl);
node._keys.push(key);
}
anim.addNode(node);
}
return anim;
}
_parseAnimationV4(data) {
const animData = data.animation;
const anim = new Animation();
anim.name = animData.name;
anim.duration = animData.duration;
for(let i = 0; i < animData.nodes.length; i++){
const node = new AnimationNode();
const n = animData.nodes[i];
node._name = n.name;
const defPos = n.defaults.p;
const defRot = n.defaults.r;
const defScl = n.defaults.s;
for(let j = 0; j < n.keys.length; j++){
const k = n.keys[j];
const t = k.t;
const p = defPos ? defPos : k.p;
const r = defRot ? defRot : k.r;
const s = defScl ? defScl : k.s;
const pos = new Vec3(p[0], p[1], p[2]);
const rot = new Quat().setFromEulerAngles(r[0], r[1], r[2]);
const scl = new Vec3(s[0], s[1], s[2]);
const key = new AnimationKey(t, pos, rot, scl);
node._keys.push(key);
}
anim.addNode(node);
}
return anim;
}
}
export { AnimationHandler };