|
@@ -1,12 +1,12 @@
|
|
-import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, ParticleSystem, Skeleton } from "babylonjs";
|
|
|
|
|
|
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, ParticleSystem, Skeleton, IDisposable, Nullable, Animation } from "babylonjs";
|
|
import { IModelConfiguration } from "../configuration/configuration";
|
|
import { IModelConfiguration } from "../configuration/configuration";
|
|
|
|
+import { IModelAnimation, GroupModelAnimation, AnimationPlayMode } from "./modelAnimation";
|
|
|
|
|
|
-export class ViewerModel {
|
|
|
|
|
|
+export class ViewerModel implements IDisposable {
|
|
|
|
|
|
public loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync;
|
|
public loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync;
|
|
|
|
|
|
- public animationGroups: Array<AnimationGroup>;
|
|
|
|
- public animatables: Array<Animatable>;
|
|
|
|
|
|
+ private _animations: Array<IModelAnimation>;
|
|
public meshes: Array<AbstractMesh>;
|
|
public meshes: Array<AbstractMesh>;
|
|
public particleSystems: Array<ParticleSystem>;
|
|
public particleSystems: Array<ParticleSystem>;
|
|
public skeletons: Array<Skeleton>;
|
|
public skeletons: Array<Skeleton>;
|
|
@@ -20,6 +20,8 @@ export class ViewerModel {
|
|
this.onLoadErrorObservable = new Observable();
|
|
this.onLoadErrorObservable = new Observable();
|
|
this.onLoadProgressObservable = new Observable();
|
|
this.onLoadProgressObservable = new Observable();
|
|
|
|
|
|
|
|
+ this._animations = [];
|
|
|
|
+
|
|
if (!disableAutoLoad) {
|
|
if (!disableAutoLoad) {
|
|
this._initLoad();
|
|
this._initLoad();
|
|
}
|
|
}
|
|
@@ -33,6 +35,25 @@ export class ViewerModel {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public getAnimations() {
|
|
|
|
+ return this._animations;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public getAnimationNames() {
|
|
|
|
+ return this._animations.map(a => a.name);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public getAnimationByName(name: string): Nullable<IModelAnimation> {
|
|
|
|
+ // can't use .find, noe available on IE
|
|
|
|
+ let filtered = this._animations.filter(a => a.name === name);
|
|
|
|
+ // what the next line means - if two animations have the same name, they will not be returned!
|
|
|
|
+ if (filtered.length === 1) {
|
|
|
|
+ return filtered[0];
|
|
|
|
+ } else {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private _initLoad() {
|
|
private _initLoad() {
|
|
if (!this._modelConfiguration || !this._modelConfiguration.url) {
|
|
if (!this._modelConfiguration || !this._modelConfiguration.url) {
|
|
return Tools.Error("No model URL to load.");
|
|
return Tools.Error("No model URL to load.");
|
|
@@ -50,21 +71,54 @@ export class ViewerModel {
|
|
this.meshes = meshes;
|
|
this.meshes = meshes;
|
|
this.particleSystems = particleSystems;
|
|
this.particleSystems = particleSystems;
|
|
this.skeletons = skeletons;
|
|
this.skeletons = skeletons;
|
|
|
|
+
|
|
|
|
+ // check if this is a gltf loader and load the animations
|
|
|
|
+ if (this.loader['_loader'] && this.loader['_loader']['_gltf'] && this.loader['_loader']['_gltf'].animations) {
|
|
|
|
+ this.loader['_loader']['_gltf'].animations.forEach(animation => {
|
|
|
|
+ this._animations.push(new GroupModelAnimation(animation._babylonAnimationGroup));
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ skeletons.forEach((skeleton, idx) => {
|
|
|
|
+ let ag = new BABYLON.AnimationGroup("animation-" + idx, this._scene);
|
|
|
|
+ skeleton.getAnimatables().forEach(a => {
|
|
|
|
+ if (a.animations[0]) {
|
|
|
|
+ ag.addTargetedAnimation(a.animations[0], a);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ this._animations.push(new GroupModelAnimation(ag));
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (this._modelConfiguration.animation) {
|
|
|
|
+ if (this._modelConfiguration.animation.playOnce) {
|
|
|
|
+ this._animations.forEach(a => {
|
|
|
|
+ a.playMode = AnimationPlayMode.ONCE;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if (this._modelConfiguration.animation.autoStart) {
|
|
|
|
+ let animation = this.getAnimationByName(this._modelConfiguration.animation.autoStart);
|
|
|
|
+ if (animation) {
|
|
|
|
+ animation.start();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.log(this.getAnimationNames());
|
|
|
|
+
|
|
this.onLoadedObservable.notifyObserversWithPromise(this);
|
|
this.onLoadedObservable.notifyObserversWithPromise(this);
|
|
}, (progressEvent) => {
|
|
}, (progressEvent) => {
|
|
this.onLoadProgressObservable.notifyObserversWithPromise(progressEvent);
|
|
this.onLoadProgressObservable.notifyObserversWithPromise(progressEvent);
|
|
}, (e, m, exception) => {
|
|
}, (e, m, exception) => {
|
|
this.onLoadErrorObservable.notifyObserversWithPromise({ message: m, exception: exception });
|
|
this.onLoadErrorObservable.notifyObserversWithPromise({ message: m, exception: exception });
|
|
}, plugin)!;
|
|
}, plugin)!;
|
|
|
|
+
|
|
|
|
+ this.loader['animationStartMode'] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
public dispose() {
|
|
public dispose() {
|
|
- this.animatables.forEach(a => {
|
|
|
|
- a.stop();
|
|
|
|
- });
|
|
|
|
this.particleSystems.forEach(ps => ps.dispose());
|
|
this.particleSystems.forEach(ps => ps.dispose());
|
|
this.skeletons.forEach(s => s.dispose());
|
|
this.skeletons.forEach(s => s.dispose());
|
|
- this.animationGroups.forEach(ag => ag.dispose());
|
|
|
|
|
|
+ this._animations.forEach(ag => ag.dispose());
|
|
this.meshes.forEach(m => m.dispose());
|
|
this.meshes.forEach(m => m.dispose());
|
|
}
|
|
}
|
|
}
|
|
}
|