ソースを参照

Added support animation synchronization + nightly

David Catuhe 7 年 前
コミット
421789a653
37 ファイル変更39844 行追加39415 行削除
  1. 16912 16889
      Playground/babylon.d.txt
  2. 16213 16190
      dist/preview release/babylon.d.ts
  3. 43 43
      dist/preview release/babylon.js
  4. 65 5
      dist/preview release/babylon.max.js
  5. 44 44
      dist/preview release/babylon.worker.js
  6. 6103 6080
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  7. 45 45
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  8. 66 5
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  9. 66 5
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  10. 65 5
      dist/preview release/es6.js
  11. 4 4
      dist/preview release/gui/babylon.gui.min.js
  12. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  13. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  14. 1 0
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  15. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  16. 1 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  17. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  18. 1 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  19. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  20. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  21. 1 0
      dist/preview release/loaders/babylonjs.loaders.js
  22. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  24. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  26. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  27. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  28. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  29. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  30. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  31. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  32. 2 7
      dist/preview release/typedocValidationBaseline.json
  33. 52 52
      dist/preview release/viewer/babylon.viewer.js
  34. 65 5
      dist/preview release/viewer/babylon.viewer.max.js
  35. 1 1
      dist/preview release/what's new.md
  36. 42 1
      src/Animations/babylon.animatable.ts
  37. 23 5
      src/Animations/babylon.runtimeAnimation.ts

ファイルの差分が大きいため隠しています
+ 16912 - 16889
Playground/babylon.d.txt


ファイルの差分が大きいため隠しています
+ 16213 - 16190
dist/preview release/babylon.d.ts


ファイルの差分が大きいため隠しています
+ 43 - 43
dist/preview release/babylon.js


+ 65 - 5
dist/preview release/babylon.max.js

@@ -47993,9 +47993,10 @@ var BABYLON;
          * @param target defines the target of the animation
          * @param animation defines the source {BABYLON.Animation} object
          * @param scene defines the hosting scene
+         * @param host defines the initiating Animatable
          */
-        function RuntimeAnimation(target, animation, scene) {
-            this.currentFrame = 0;
+        function RuntimeAnimation(target, animation, scene, host) {
+            this._currentFrame = 0;
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._stopped = false;
@@ -48008,8 +48009,19 @@ var BABYLON;
             this._animation = animation;
             this._target = target;
             this._scene = scene;
+            this._host = host;
             animation._runtimeAnimations.push(this);
         }
+        Object.defineProperty(RuntimeAnimation.prototype, "currentFrame", {
+            /**
+             * Gets the current frame
+             */
+            get: function () {
+                return this._currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(RuntimeAnimation.prototype, "weight", {
             /**
              * Gets the weight of the runtime animation
@@ -48070,7 +48082,7 @@ var BABYLON;
         RuntimeAnimation.prototype.reset = function () {
             this._offsetsCache = {};
             this._highLimitsCache = {};
-            this.currentFrame = 0;
+            this._currentFrame = 0;
             this._blendingFactor = 0;
             this._originalValue = null;
         };
@@ -48093,7 +48105,7 @@ var BABYLON;
             if (loopMode === BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }
-            this.currentFrame = currentFrame;
+            this._currentFrame = currentFrame;
             var keys = this._animation.getKeys();
             // Try to get a hash to find the right key
             var startKeyIndex = Math.max(0, Math.min(keys.length - 1, Math.floor(keys.length * (currentFrame - keys[0].frame) / (keys[keys.length - 1].frame - keys[0].frame)) - 1));
@@ -48431,6 +48443,12 @@ var BABYLON;
             // Compute value
             var repeatCount = (ratio / range) >> 0;
             var currentFrame = returnValue ? from + ratio % range : to;
+            // Need to normalize?
+            if (this._host && this._host.syncRoot) {
+                var syncRoot = this._host.syncRoot;
+                var hostNormalizedFrame = (syncRoot.masterFrame - syncRoot.fromFrame) / (syncRoot.toFrame - syncRoot.fromFrame);
+                currentFrame = from + (to - from) * hostNormalizedFrame;
+            }
             var currentValue = this._interpolate(currentFrame, repeatCount, this._getCorrectLoopMode(), offsetValue, highLimitValue);
             // Set value
             this.setValue(currentValue, weight);
@@ -48497,6 +48515,30 @@ var BABYLON;
             this._scene = scene;
             scene._activeAnimatables.push(this);
         }
+        Object.defineProperty(Animatable.prototype, "syncRoot", {
+            /**
+             * Gets the root Animatable used to synchronize and normalize animations
+             */
+            get: function () {
+                return this._syncRoot;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Animatable.prototype, "masterFrame", {
+            /**
+             * Gets the current frame of the first RuntimeAnimation
+             * Used to synchronize Animatables
+             */
+            get: function () {
+                if (this._runtimeAnimations.length === 0) {
+                    return 0;
+                }
+                return this._runtimeAnimations[0].currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Animatable.prototype, "weight", {
             /**
              * Gets or sets the animatable weight (-1.0 by default meaning not weighted)
@@ -48533,13 +48575,31 @@ var BABYLON;
             configurable: true
         });
         // Methods
+        /**
+         * Synchronize and normalize current Animatable with a source Animatable.
+         * This is useful when using animation weights and when animations are not of the same length
+         * @param root defines the root Animatable to synchronize with
+         * @returns the current Animatable
+         */
+        Animatable.prototype.syncWith = function (root) {
+            this._syncRoot = root;
+            if (root) {
+                // Make sure this animatable will animate after the root
+                var index = this._scene._activeAnimatables.indexOf(this);
+                if (index > -1) {
+                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.push(this);
+                }
+            }
+            return this;
+        };
         Animatable.prototype.getAnimations = function () {
             return this._runtimeAnimations;
         };
         Animatable.prototype.appendAnimations = function (target, animations) {
             for (var index = 0; index < animations.length; index++) {
                 var animation = animations[index];
-                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene));
+                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene, this));
             }
         };
         Animatable.prototype.getAnimationByTargetProperty = function (property) {

ファイルの差分が大きいため隠しています
+ 44 - 44
dist/preview release/babylon.worker.js


ファイルの差分が大きいため隠しています
+ 6103 - 6080
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


ファイルの差分が大きいため隠しています
+ 45 - 45
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 66 - 5
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -47993,9 +47993,10 @@ var BABYLON;
          * @param target defines the target of the animation
          * @param animation defines the source {BABYLON.Animation} object
          * @param scene defines the hosting scene
+         * @param host defines the initiating Animatable
          */
-        function RuntimeAnimation(target, animation, scene) {
-            this.currentFrame = 0;
+        function RuntimeAnimation(target, animation, scene, host) {
+            this._currentFrame = 0;
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._stopped = false;
@@ -48008,8 +48009,19 @@ var BABYLON;
             this._animation = animation;
             this._target = target;
             this._scene = scene;
+            this._host = host;
             animation._runtimeAnimations.push(this);
         }
+        Object.defineProperty(RuntimeAnimation.prototype, "currentFrame", {
+            /**
+             * Gets the current frame
+             */
+            get: function () {
+                return this._currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(RuntimeAnimation.prototype, "weight", {
             /**
              * Gets the weight of the runtime animation
@@ -48070,7 +48082,7 @@ var BABYLON;
         RuntimeAnimation.prototype.reset = function () {
             this._offsetsCache = {};
             this._highLimitsCache = {};
-            this.currentFrame = 0;
+            this._currentFrame = 0;
             this._blendingFactor = 0;
             this._originalValue = null;
         };
@@ -48093,7 +48105,7 @@ var BABYLON;
             if (loopMode === BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }
-            this.currentFrame = currentFrame;
+            this._currentFrame = currentFrame;
             var keys = this._animation.getKeys();
             // Try to get a hash to find the right key
             var startKeyIndex = Math.max(0, Math.min(keys.length - 1, Math.floor(keys.length * (currentFrame - keys[0].frame) / (keys[keys.length - 1].frame - keys[0].frame)) - 1));
@@ -48431,6 +48443,12 @@ var BABYLON;
             // Compute value
             var repeatCount = (ratio / range) >> 0;
             var currentFrame = returnValue ? from + ratio % range : to;
+            // Need to normalize?
+            if (this._host && this._host.syncRoot) {
+                var syncRoot = this._host.syncRoot;
+                var hostNormalizedFrame = (syncRoot.masterFrame - syncRoot.fromFrame) / (syncRoot.toFrame - syncRoot.fromFrame);
+                currentFrame = from + (to - from) * hostNormalizedFrame;
+            }
             var currentValue = this._interpolate(currentFrame, repeatCount, this._getCorrectLoopMode(), offsetValue, highLimitValue);
             // Set value
             this.setValue(currentValue, weight);
@@ -48497,6 +48515,30 @@ var BABYLON;
             this._scene = scene;
             scene._activeAnimatables.push(this);
         }
+        Object.defineProperty(Animatable.prototype, "syncRoot", {
+            /**
+             * Gets the root Animatable used to synchronize and normalize animations
+             */
+            get: function () {
+                return this._syncRoot;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Animatable.prototype, "masterFrame", {
+            /**
+             * Gets the current frame of the first RuntimeAnimation
+             * Used to synchronize Animatables
+             */
+            get: function () {
+                if (this._runtimeAnimations.length === 0) {
+                    return 0;
+                }
+                return this._runtimeAnimations[0].currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Animatable.prototype, "weight", {
             /**
              * Gets or sets the animatable weight (-1.0 by default meaning not weighted)
@@ -48533,13 +48575,31 @@ var BABYLON;
             configurable: true
         });
         // Methods
+        /**
+         * Synchronize and normalize current Animatable with a source Animatable.
+         * This is useful when using animation weights and when animations are not of the same length
+         * @param root defines the root Animatable to synchronize with
+         * @returns the current Animatable
+         */
+        Animatable.prototype.syncWith = function (root) {
+            this._syncRoot = root;
+            if (root) {
+                // Make sure this animatable will animate after the root
+                var index = this._scene._activeAnimatables.indexOf(this);
+                if (index > -1) {
+                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.push(this);
+                }
+            }
+            return this;
+        };
         Animatable.prototype.getAnimations = function () {
             return this._runtimeAnimations;
         };
         Animatable.prototype.appendAnimations = function (target, animations) {
             for (var index = 0; index < animations.length; index++) {
                 var animation = animations[index];
-                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene));
+                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene, this));
             }
         };
         Animatable.prototype.getAnimationByTargetProperty = function (property) {
@@ -92444,6 +92504,7 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onAnimationGroupLoadedObservable.add(function (animationGroup) { return _this.onAnimationGroupLoadedObservable.notifyObservers(animationGroup); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();

+ 66 - 5
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js

@@ -47965,9 +47965,10 @@ var BABYLON;
          * @param target defines the target of the animation
          * @param animation defines the source {BABYLON.Animation} object
          * @param scene defines the hosting scene
+         * @param host defines the initiating Animatable
          */
-        function RuntimeAnimation(target, animation, scene) {
-            this.currentFrame = 0;
+        function RuntimeAnimation(target, animation, scene, host) {
+            this._currentFrame = 0;
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._stopped = false;
@@ -47980,8 +47981,19 @@ var BABYLON;
             this._animation = animation;
             this._target = target;
             this._scene = scene;
+            this._host = host;
             animation._runtimeAnimations.push(this);
         }
+        Object.defineProperty(RuntimeAnimation.prototype, "currentFrame", {
+            /**
+             * Gets the current frame
+             */
+            get: function () {
+                return this._currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(RuntimeAnimation.prototype, "weight", {
             /**
              * Gets the weight of the runtime animation
@@ -48042,7 +48054,7 @@ var BABYLON;
         RuntimeAnimation.prototype.reset = function () {
             this._offsetsCache = {};
             this._highLimitsCache = {};
-            this.currentFrame = 0;
+            this._currentFrame = 0;
             this._blendingFactor = 0;
             this._originalValue = null;
         };
@@ -48065,7 +48077,7 @@ var BABYLON;
             if (loopMode === BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }
-            this.currentFrame = currentFrame;
+            this._currentFrame = currentFrame;
             var keys = this._animation.getKeys();
             // Try to get a hash to find the right key
             var startKeyIndex = Math.max(0, Math.min(keys.length - 1, Math.floor(keys.length * (currentFrame - keys[0].frame) / (keys[keys.length - 1].frame - keys[0].frame)) - 1));
@@ -48403,6 +48415,12 @@ var BABYLON;
             // Compute value
             var repeatCount = (ratio / range) >> 0;
             var currentFrame = returnValue ? from + ratio % range : to;
+            // Need to normalize?
+            if (this._host && this._host.syncRoot) {
+                var syncRoot = this._host.syncRoot;
+                var hostNormalizedFrame = (syncRoot.masterFrame - syncRoot.fromFrame) / (syncRoot.toFrame - syncRoot.fromFrame);
+                currentFrame = from + (to - from) * hostNormalizedFrame;
+            }
             var currentValue = this._interpolate(currentFrame, repeatCount, this._getCorrectLoopMode(), offsetValue, highLimitValue);
             // Set value
             this.setValue(currentValue, weight);
@@ -48469,6 +48487,30 @@ var BABYLON;
             this._scene = scene;
             scene._activeAnimatables.push(this);
         }
+        Object.defineProperty(Animatable.prototype, "syncRoot", {
+            /**
+             * Gets the root Animatable used to synchronize and normalize animations
+             */
+            get: function () {
+                return this._syncRoot;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Animatable.prototype, "masterFrame", {
+            /**
+             * Gets the current frame of the first RuntimeAnimation
+             * Used to synchronize Animatables
+             */
+            get: function () {
+                if (this._runtimeAnimations.length === 0) {
+                    return 0;
+                }
+                return this._runtimeAnimations[0].currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Animatable.prototype, "weight", {
             /**
              * Gets or sets the animatable weight (-1.0 by default meaning not weighted)
@@ -48505,13 +48547,31 @@ var BABYLON;
             configurable: true
         });
         // Methods
+        /**
+         * Synchronize and normalize current Animatable with a source Animatable.
+         * This is useful when using animation weights and when animations are not of the same length
+         * @param root defines the root Animatable to synchronize with
+         * @returns the current Animatable
+         */
+        Animatable.prototype.syncWith = function (root) {
+            this._syncRoot = root;
+            if (root) {
+                // Make sure this animatable will animate after the root
+                var index = this._scene._activeAnimatables.indexOf(this);
+                if (index > -1) {
+                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.push(this);
+                }
+            }
+            return this;
+        };
         Animatable.prototype.getAnimations = function () {
             return this._runtimeAnimations;
         };
         Animatable.prototype.appendAnimations = function (target, animations) {
             for (var index = 0; index < animations.length; index++) {
                 var animation = animations[index];
-                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene));
+                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene, this));
             }
         };
         Animatable.prototype.getAnimationByTargetProperty = function (property) {
@@ -92416,6 +92476,7 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onAnimationGroupLoadedObservable.add(function (animationGroup) { return _this.onAnimationGroupLoadedObservable.notifyObservers(animationGroup); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();

+ 65 - 5
dist/preview release/es6.js

@@ -47965,9 +47965,10 @@ var BABYLON;
          * @param target defines the target of the animation
          * @param animation defines the source {BABYLON.Animation} object
          * @param scene defines the hosting scene
+         * @param host defines the initiating Animatable
          */
-        function RuntimeAnimation(target, animation, scene) {
-            this.currentFrame = 0;
+        function RuntimeAnimation(target, animation, scene, host) {
+            this._currentFrame = 0;
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._stopped = false;
@@ -47980,8 +47981,19 @@ var BABYLON;
             this._animation = animation;
             this._target = target;
             this._scene = scene;
+            this._host = host;
             animation._runtimeAnimations.push(this);
         }
+        Object.defineProperty(RuntimeAnimation.prototype, "currentFrame", {
+            /**
+             * Gets the current frame
+             */
+            get: function () {
+                return this._currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(RuntimeAnimation.prototype, "weight", {
             /**
              * Gets the weight of the runtime animation
@@ -48042,7 +48054,7 @@ var BABYLON;
         RuntimeAnimation.prototype.reset = function () {
             this._offsetsCache = {};
             this._highLimitsCache = {};
-            this.currentFrame = 0;
+            this._currentFrame = 0;
             this._blendingFactor = 0;
             this._originalValue = null;
         };
@@ -48065,7 +48077,7 @@ var BABYLON;
             if (loopMode === BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }
-            this.currentFrame = currentFrame;
+            this._currentFrame = currentFrame;
             var keys = this._animation.getKeys();
             // Try to get a hash to find the right key
             var startKeyIndex = Math.max(0, Math.min(keys.length - 1, Math.floor(keys.length * (currentFrame - keys[0].frame) / (keys[keys.length - 1].frame - keys[0].frame)) - 1));
@@ -48403,6 +48415,12 @@ var BABYLON;
             // Compute value
             var repeatCount = (ratio / range) >> 0;
             var currentFrame = returnValue ? from + ratio % range : to;
+            // Need to normalize?
+            if (this._host && this._host.syncRoot) {
+                var syncRoot = this._host.syncRoot;
+                var hostNormalizedFrame = (syncRoot.masterFrame - syncRoot.fromFrame) / (syncRoot.toFrame - syncRoot.fromFrame);
+                currentFrame = from + (to - from) * hostNormalizedFrame;
+            }
             var currentValue = this._interpolate(currentFrame, repeatCount, this._getCorrectLoopMode(), offsetValue, highLimitValue);
             // Set value
             this.setValue(currentValue, weight);
@@ -48469,6 +48487,30 @@ var BABYLON;
             this._scene = scene;
             scene._activeAnimatables.push(this);
         }
+        Object.defineProperty(Animatable.prototype, "syncRoot", {
+            /**
+             * Gets the root Animatable used to synchronize and normalize animations
+             */
+            get: function () {
+                return this._syncRoot;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Animatable.prototype, "masterFrame", {
+            /**
+             * Gets the current frame of the first RuntimeAnimation
+             * Used to synchronize Animatables
+             */
+            get: function () {
+                if (this._runtimeAnimations.length === 0) {
+                    return 0;
+                }
+                return this._runtimeAnimations[0].currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Animatable.prototype, "weight", {
             /**
              * Gets or sets the animatable weight (-1.0 by default meaning not weighted)
@@ -48505,13 +48547,31 @@ var BABYLON;
             configurable: true
         });
         // Methods
+        /**
+         * Synchronize and normalize current Animatable with a source Animatable.
+         * This is useful when using animation weights and when animations are not of the same length
+         * @param root defines the root Animatable to synchronize with
+         * @returns the current Animatable
+         */
+        Animatable.prototype.syncWith = function (root) {
+            this._syncRoot = root;
+            if (root) {
+                // Make sure this animatable will animate after the root
+                var index = this._scene._activeAnimatables.indexOf(this);
+                if (index > -1) {
+                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.push(this);
+                }
+            }
+            return this;
+        };
         Animatable.prototype.getAnimations = function () {
             return this._runtimeAnimations;
         };
         Animatable.prototype.appendAnimations = function (target, animations) {
             for (var index = 0; index < animations.length; index++) {
                 var animation = animations[index];
-                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene));
+                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene, this));
             }
         };
         Animatable.prototype.getAnimationByTargetProperty = function (property) {

ファイルの差分が大きいため隠しています
+ 4 - 4
dist/preview release/gui/babylon.gui.min.js


ファイルの差分が大きいため隠しています
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


ファイルの差分が大きいため隠しています
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


+ 1 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -307,6 +307,7 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onAnimationGroupLoadedObservable.add(function (animationGroup) { return _this.onAnimationGroupLoadedObservable.notifyObservers(animationGroup); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();

ファイルの差分が大きいため隠しています
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 1 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -307,6 +307,7 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onAnimationGroupLoadedObservable.add(function (animationGroup) { return _this.onAnimationGroupLoadedObservable.notifyObservers(animationGroup); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();

ファイルの差分が大きいため隠しています
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 1 - 0
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -307,6 +307,7 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onAnimationGroupLoadedObservable.add(function (animationGroup) { return _this.onAnimationGroupLoadedObservable.notifyObservers(animationGroup); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();

ファイルの差分が大きいため隠しています
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 1 - 0
dist/preview release/loaders/babylonjs.loaders.js

@@ -1304,6 +1304,7 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onAnimationGroupLoadedObservable.add(function (animationGroup) { return _this.onAnimationGroupLoadedObservable.notifyObservers(animationGroup); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();

ファイルの差分が大きいため隠しています
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


ファイルの差分が大きいため隠しています
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 2 - 7
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 7153,
+  "errors": 7152,
   "babylon.typedoc.json": {
-    "errors": 7153,
+    "errors": 7152,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -25726,11 +25726,6 @@
           "Comments": {
             "MissingText": true
           }
-        },
-        "currentFrame": {
-          "Comments": {
-            "MissingText": true
-          }
         }
       },
       "Method": {

ファイルの差分が大きいため隠しています
+ 52 - 52
dist/preview release/viewer/babylon.viewer.js


+ 65 - 5
dist/preview release/viewer/babylon.viewer.max.js

@@ -48081,9 +48081,10 @@ var BABYLON;
          * @param target defines the target of the animation
          * @param animation defines the source {BABYLON.Animation} object
          * @param scene defines the hosting scene
+         * @param host defines the initiating Animatable
          */
-        function RuntimeAnimation(target, animation, scene) {
-            this.currentFrame = 0;
+        function RuntimeAnimation(target, animation, scene, host) {
+            this._currentFrame = 0;
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._stopped = false;
@@ -48096,8 +48097,19 @@ var BABYLON;
             this._animation = animation;
             this._target = target;
             this._scene = scene;
+            this._host = host;
             animation._runtimeAnimations.push(this);
         }
+        Object.defineProperty(RuntimeAnimation.prototype, "currentFrame", {
+            /**
+             * Gets the current frame
+             */
+            get: function () {
+                return this._currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(RuntimeAnimation.prototype, "weight", {
             /**
              * Gets the weight of the runtime animation
@@ -48158,7 +48170,7 @@ var BABYLON;
         RuntimeAnimation.prototype.reset = function () {
             this._offsetsCache = {};
             this._highLimitsCache = {};
-            this.currentFrame = 0;
+            this._currentFrame = 0;
             this._blendingFactor = 0;
             this._originalValue = null;
         };
@@ -48181,7 +48193,7 @@ var BABYLON;
             if (loopMode === BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }
-            this.currentFrame = currentFrame;
+            this._currentFrame = currentFrame;
             var keys = this._animation.getKeys();
             // Try to get a hash to find the right key
             var startKeyIndex = Math.max(0, Math.min(keys.length - 1, Math.floor(keys.length * (currentFrame - keys[0].frame) / (keys[keys.length - 1].frame - keys[0].frame)) - 1));
@@ -48519,6 +48531,12 @@ var BABYLON;
             // Compute value
             var repeatCount = (ratio / range) >> 0;
             var currentFrame = returnValue ? from + ratio % range : to;
+            // Need to normalize?
+            if (this._host && this._host.syncRoot) {
+                var syncRoot = this._host.syncRoot;
+                var hostNormalizedFrame = (syncRoot.masterFrame - syncRoot.fromFrame) / (syncRoot.toFrame - syncRoot.fromFrame);
+                currentFrame = from + (to - from) * hostNormalizedFrame;
+            }
             var currentValue = this._interpolate(currentFrame, repeatCount, this._getCorrectLoopMode(), offsetValue, highLimitValue);
             // Set value
             this.setValue(currentValue, weight);
@@ -48585,6 +48603,30 @@ var BABYLON;
             this._scene = scene;
             scene._activeAnimatables.push(this);
         }
+        Object.defineProperty(Animatable.prototype, "syncRoot", {
+            /**
+             * Gets the root Animatable used to synchronize and normalize animations
+             */
+            get: function () {
+                return this._syncRoot;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Animatable.prototype, "masterFrame", {
+            /**
+             * Gets the current frame of the first RuntimeAnimation
+             * Used to synchronize Animatables
+             */
+            get: function () {
+                if (this._runtimeAnimations.length === 0) {
+                    return 0;
+                }
+                return this._runtimeAnimations[0].currentFrame;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Animatable.prototype, "weight", {
             /**
              * Gets or sets the animatable weight (-1.0 by default meaning not weighted)
@@ -48621,13 +48663,31 @@ var BABYLON;
             configurable: true
         });
         // Methods
+        /**
+         * Synchronize and normalize current Animatable with a source Animatable.
+         * This is useful when using animation weights and when animations are not of the same length
+         * @param root defines the root Animatable to synchronize with
+         * @returns the current Animatable
+         */
+        Animatable.prototype.syncWith = function (root) {
+            this._syncRoot = root;
+            if (root) {
+                // Make sure this animatable will animate after the root
+                var index = this._scene._activeAnimatables.indexOf(this);
+                if (index > -1) {
+                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.push(this);
+                }
+            }
+            return this;
+        };
         Animatable.prototype.getAnimations = function () {
             return this._runtimeAnimations;
         };
         Animatable.prototype.appendAnimations = function (target, animations) {
             for (var index = 0; index < animations.length; index++) {
                 var animation = animations[index];
-                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene));
+                this._runtimeAnimations.push(new BABYLON.RuntimeAnimation(target, animation, this._scene, this));
             }
         };
         Animatable.prototype.getAnimationByTargetProperty = function (property) {

+ 1 - 1
dist/preview release/what's new.md

@@ -14,7 +14,7 @@
 - Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials. Demo [here](http://www.babylonjs.com/demos/GlowLayer/) ([sebavan](https://github.com/sebavan))
 - New [AssetContainer](http://doc.babylonjs.com/how_to/how_to_use_assetcontainer) class and loading methods ([trevordev](https://github.com/trevordev))
 - Added [depth of field](https://www.babylonjs-playground.com/frame.html#8F5HYV#5), sharpening, MSAA, chromatic aberration and grain effect to the default pipeline ([trevordev](https://github.com/trevordev))
-- Added support for [animation weights](http://doc.babylonjs.com/babylon101/animations#animation-weights). Demo [here](https://www.babylonjs-playground.com/#IQN716#8) ([deltakosh](https://github.com/deltakosh))
+- Added support for [animation weights](http://doc.babylonjs.com/babylon101/animations#animation-weights). Demo [here](https://www.babylonjs-playground.com/#IQN716#9) ([deltakosh](https://github.com/deltakosh))
 - Added [sub emitters for particle system](http://doc.babylonjs.com/babylon101/particles#sub-emitters) which will spawn new particle systems when particles dies. Demo [here](https://www.babylonjs-playground.com/frame.html#9NHBCC#1) ([IbraheemOsama](https://github.com/IbraheemOsama))
 - New [Babylon.js](http://doc.babylonjs.com/resources/maya) and [glTF](http://doc.babylonjs.com/resources/maya_to_gltf) exporter for Autodesk Maya ([Noalak](https://github.com/Noalak))
 - New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))

+ 42 - 1
src/Animations/babylon.animatable.ts

@@ -7,10 +7,30 @@
         private _scene: Scene;
         private _speedRatio = 1;
         private _weight = -1.0;
+        private _syncRoot: Animatable;
 
         public animationStarted = false;
 
         /**
+         * Gets the root Animatable used to synchronize and normalize animations
+         */
+        public get syncRoot(): Animatable {
+            return this._syncRoot;
+        }
+
+        /**
+         * Gets the current frame of the first RuntimeAnimation
+         * Used to synchronize Animatables
+         */
+        public get masterFrame(): number {
+            if (this._runtimeAnimations.length === 0) {
+                return 0;
+            }
+
+            return this._runtimeAnimations[0].currentFrame;
+        }
+
+        /**
          * Gets or sets the animatable weight (-1.0 by default meaning not weighted)
          */
         public get weight(): number {
@@ -55,6 +75,27 @@
         }
 
         // Methods
+        /**
+         * Synchronize and normalize current Animatable with a source Animatable.
+         * This is useful when using animation weights and when animations are not of the same length
+         * @param root defines the root Animatable to synchronize with
+         * @returns the current Animatable
+         */
+        public syncWith(root: Animatable): Animatable {
+            this._syncRoot = root;
+
+            if (root) {
+                // Make sure this animatable will animate after the root
+                let index = this._scene._activeAnimatables.indexOf(this);
+                if (index > -1) {
+                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.push(this);
+                }
+            }
+
+            return this;
+        }
+
         public getAnimations(): RuntimeAnimation[] {
             return this._runtimeAnimations;
         }
@@ -63,7 +104,7 @@
             for (var index = 0; index < animations.length; index++) {
                 var animation = animations[index];
 
-                this._runtimeAnimations.push(new RuntimeAnimation(target, animation, this._scene));
+                this._runtimeAnimations.push(new RuntimeAnimation(target, animation, this._scene, this));
             }
         }
 

+ 23 - 5
src/Animations/babylon.runtimeAnimation.ts

@@ -1,9 +1,10 @@
 module BABYLON {
 
     export class RuntimeAnimation {
-        public currentFrame: number = 0;
+        private _currentFrame: number = 0;
         private _animation: Animation;
         private _target: any;
+        private _host: Animatable;
 
         private _originalValue: any;
         private _originalBlendValue: any;
@@ -16,7 +17,14 @@
         private _currentValue: any;
         private _activeTarget: any;
         private _targetPath: string = "";
-        private _weight = 1.0
+        private _weight = 1.0;
+
+        /**
+         * Gets the current frame
+         */
+        public get currentFrame(): number {
+            return this._currentFrame;
+        }
 
         /**
          * Gets the weight of the runtime animation
@@ -58,11 +66,13 @@
          * @param target defines the target of the animation
          * @param animation defines the source {BABYLON.Animation} object
          * @param scene defines the hosting scene
+         * @param host defines the initiating Animatable
          */
-        public constructor(target: any, animation: Animation, scene: Scene) {
+        public constructor(target: any, animation: Animation, scene: Scene, host: Animatable) {
             this._animation = animation;
             this._target = target;
             this._scene = scene;
+            this._host = host;
 
             animation._runtimeAnimations.push(this);
         }
@@ -74,7 +84,7 @@
         public reset(): void {
             this._offsetsCache = {};
             this._highLimitsCache = {};
-            this.currentFrame = 0;
+            this._currentFrame = 0;
             this._blendingFactor = 0;
             this._originalValue = null;
         }
@@ -104,7 +114,7 @@
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }
 
-            this.currentFrame = currentFrame;
+            this._currentFrame = currentFrame;
 
             let keys = this._animation.getKeys();
 
@@ -482,6 +492,14 @@
             // Compute value
             var repeatCount = (ratio / range) >> 0;
             var currentFrame = returnValue ? from + ratio % range : to;
+
+            // Need to normalize?
+            if (this._host && this._host.syncRoot) {
+                let syncRoot = this._host.syncRoot;
+                let hostNormalizedFrame = (syncRoot.masterFrame - syncRoot.fromFrame) / (syncRoot.toFrame - syncRoot.fromFrame);
+                currentFrame = from + (to - from) * hostNormalizedFrame;
+            }
+
             var currentValue = this._interpolate(currentFrame, repeatCount, this._getCorrectLoopMode(), offsetValue, highLimitValue);
 
             // Set value