David Catuhe 7 gadi atpakaļ
vecāks
revīzija
76a65cf8fb

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 14352 - 14264
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 29 - 29
dist/preview release/babylon.js


+ 267 - 13
dist/preview release/babylon.max.js

@@ -18381,7 +18381,7 @@ var BABYLON;
             return _this;
         }
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "TransformNode" string
          */
         TransformNode.prototype.getClassName = function () {
@@ -18495,7 +18495,7 @@ var BABYLON;
             configurable: true
         });
         /**
-         * Copies the paramater passed Matrix into the mesh Pose matrix.
+         * Copies the parameter passed Matrix into the mesh Pose matrix.
          * Returns the TransformNode.
          */
         TransformNode.prototype.updatePoseMatrix = function (matrix) {
@@ -18553,7 +18553,7 @@ var BABYLON;
         Object.defineProperty(TransformNode.prototype, "absolutePosition", {
             /**
              * Returns the current mesh absolute position.
-             * Retuns a Vector3.
+             * Returns a Vector3.
              */
             get: function () {
                 return this._absolutePosition;
@@ -50566,7 +50566,7 @@ var BABYLON;
         });
         Object.defineProperty(Animation, "ANIMATIONTYPE_VECTOR2", {
             /**
-             * Get the Vectpr2 animation type
+             * Get the Vector2 animation type
              */
             get: function () {
                 return Animation._ANIMATIONTYPE_VECTOR2;
@@ -50835,6 +50835,10 @@ var BABYLON;
              * This observable will notify when all animations have ended.
              */
             this.onAnimationGroupEndObservable = new BABYLON.Observable();
+            /**
+             * This observable will notify when all animations have paused.
+             */
+            this.onAnimationGroupPauseObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
@@ -51018,6 +51022,7 @@ var BABYLON;
                 var animatable = this._animatables[index];
                 animatable.pause();
             }
+            this.onAnimationGroupPauseObservable.notifyObservers(this);
             return this;
         };
         /**
@@ -51646,7 +51651,7 @@ var BABYLON;
                             index--;
                         }
                         event.isDone = true;
-                        event.action();
+                        event.action(currentFrame);
                     } // Don't do anything if the event has already be done.
                 }
             }
@@ -64350,11 +64355,17 @@ var BABYLON;
             this.maxDistance = 100;
             this.distanceModel = "linear";
             this._panningModel = "equalpower";
+            /**
+             * Observable event when the current playing sound finishes.
+             */
+            this.onEndedObservable = new BABYLON.Observable();
             this._playbackRate = 1;
             this._streaming = false;
             this._startTime = 0;
             this._startOffset = 0;
             this._position = BABYLON.Vector3.Zero();
+            /** @hidden */
+            this._positionInEmitterSpace = false;
             this._localDirection = new BABYLON.Vector3(1, 0, 0);
             this._volume = 1;
             this._isReadyToPlay = false;
@@ -64400,7 +64411,7 @@ var BABYLON;
                 this._soundGain = BABYLON.Engine.audioEngine.audioContext.createGain();
                 this._soundGain.gain.value = this._volume;
                 this._inputAudioNode = this._soundGain;
-                this._ouputAudioNode = this._soundGain;
+                this._outputAudioNode = this._soundGain;
                 if (this.spatialSound) {
                     this._createSpatialParameters();
                 }
@@ -64633,7 +64644,7 @@ var BABYLON;
                 }
                 this._soundPanner = BABYLON.Engine.audioEngine.audioContext.createPanner();
                 this._updateSpatialParameters();
-                this._soundPanner.connect(this._ouputAudioNode);
+                this._soundPanner.connect(this._outputAudioNode);
                 this._inputAudioNode = this._soundPanner;
             }
         };
@@ -64672,9 +64683,9 @@ var BABYLON;
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
                 if (this._isOutputConnected) {
-                    this._ouputAudioNode.disconnect();
+                    this._outputAudioNode.disconnect();
                 }
-                this._ouputAudioNode.connect(soundTrackAudioNode);
+                this._outputAudioNode.connect(soundTrackAudioNode);
                 this._isOutputConnected = true;
             }
         };
@@ -64698,9 +64709,59 @@ var BABYLON;
                 this.play();
             }
         };
+        Object.defineProperty(Sound.prototype, "directionalConeInnerAngle", {
+            /**
+             * Gets or sets the inner angle for the directional cone.
+             */
+            get: function () {
+                return this._coneInnerAngle;
+            },
+            /**
+             * Gets or sets the inner angle for the directional cone.
+             */
+            set: function (value) {
+                if (value != this._coneInnerAngle) {
+                    if (this._coneOuterAngle < value) {
+                        BABYLON.Tools.Error("directionalConeInnerAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneInnerAngle = value;
+                    if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner) {
+                        this._soundPanner.coneInnerAngle = this._coneInnerAngle;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Sound.prototype, "directionalConeOuterAngle", {
+            /**
+             * Gets or sets the outer angle for the directional cone.
+             */
+            get: function () {
+                return this._coneOuterAngle;
+            },
+            /**
+             * Gets or sets the outer angle for the directional cone.
+             */
+            set: function (value) {
+                if (value != this._coneOuterAngle) {
+                    if (value < this._coneInnerAngle) {
+                        BABYLON.Tools.Error("directionalConeOuterAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneOuterAngle = value;
+                    if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner) {
+                        this._soundPanner.coneOuterAngle = this._coneOuterAngle;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Sound.prototype.setPosition = function (newPosition) {
             this._position = newPosition;
-            if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner && !isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
             }
         };
@@ -64744,7 +64805,9 @@ var BABYLON;
                     var startTime = time ? BABYLON.Engine.audioEngine.audioContext.currentTime + time : BABYLON.Engine.audioEngine.audioContext.currentTime;
                     if (!this._soundSource || !this._streamingSource) {
                         if (this.spatialSound && this._soundPanner) {
-                            this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                            if (!isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
+                                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                            }
                             if (this._isDirectional) {
                                 this._soundPanner.coneInnerAngle = this._coneInnerAngle;
                                 this._soundPanner.coneOuterAngle = this._coneOuterAngle;
@@ -64795,6 +64858,7 @@ var BABYLON;
             if (this.onended) {
                 this.onended();
             }
+            this.onEndedObservable.notifyObservers(this);
         };
         /**
         * Stop the sound
@@ -64900,8 +64964,14 @@ var BABYLON;
                 return;
             }
             var mesh = node;
-            var boundingInfo = mesh.getBoundingInfo();
-            this.setPosition(boundingInfo.boundingSphere.centerWorld);
+            if (this._positionInEmitterSpace) {
+                mesh.worldMatrixFromCache.invertToRef(BABYLON.Tmp.Matrix[0]);
+                this.setPosition(BABYLON.Tmp.Matrix[0].getTranslation());
+            }
+            else {
+                var boundingInfo = mesh.getBoundingInfo();
+                this.setPosition(boundingInfo.boundingSphere.centerWorld);
+            }
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();
             }
@@ -65320,6 +65390,190 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.analyser.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Wraps one or more Sound objects and selects one with random weight for playback.
+     */
+    var WeightedSound = /** @class */ (function () {
+        /**
+         * Creates a new WeightedSound from the list of sounds given.
+         * @param loop When true a Sound will be selected and played when the current playing Sound completes.
+         * @param sounds Array of Sounds that will be selected from.
+         * @param weights Array of number values for selection weights; length must equal sounds, values will be normalized to 1
+         */
+        function WeightedSound(loop, sounds, weights) {
+            var _this = this;
+            /** When true a Sound will be selected and played when the current playing Sound completes. */
+            this.loop = false;
+            this._coneInnerAngle = 360;
+            this._coneOuterAngle = 360;
+            this._volume = 1;
+            /** A Sound is currently playing. */
+            this.isPlaying = false;
+            /** A Sound is currently paused. */
+            this.isPaused = false;
+            this._sounds = [];
+            this._weights = [];
+            if (sounds.length !== weights.length) {
+                throw new Error('Sounds length does not equal weights length');
+            }
+            this.loop = loop;
+            this._weights = weights;
+            // Normalize the weights
+            var weightSum = 0;
+            for (var _i = 0, weights_1 = weights; _i < weights_1.length; _i++) {
+                var weight = weights_1[_i];
+                weightSum += weight;
+            }
+            var invWeightSum = weightSum > 0 ? 1 / weightSum : 0;
+            for (var i = 0; i < this._weights.length; i++) {
+                this._weights[i] *= invWeightSum;
+            }
+            this._sounds = sounds;
+            for (var _a = 0, _b = this._sounds; _a < _b.length; _a++) {
+                var sound = _b[_a];
+                sound.onEndedObservable.add(function () { _this._onended(); });
+            }
+        }
+        Object.defineProperty(WeightedSound.prototype, "directionalConeInnerAngle", {
+            /**
+             * The size of cone in degrees for a directional sound in which there will be no attenuation.
+             */
+            get: function () {
+                return this._coneInnerAngle;
+            },
+            /**
+             * The size of cone in degress for a directional sound in which there will be no attenuation.
+             */
+            set: function (value) {
+                if (value !== this._coneInnerAngle) {
+                    if (this._coneOuterAngle < value) {
+                        BABYLON.Tools.Error("directionalConeInnerAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneInnerAngle = value;
+                    for (var _i = 0, _a = this._sounds; _i < _a.length; _i++) {
+                        var sound = _a[_i];
+                        sound.directionalConeInnerAngle = value;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(WeightedSound.prototype, "directionalConeOuterAngle", {
+            /**
+             * Size of cone in degrees for a directional sound outside of which there will be no sound.
+             * Listener angles between innerAngle and outerAngle will falloff linearly.
+             */
+            get: function () {
+                return this._coneOuterAngle;
+            },
+            /**
+             * Size of cone in degrees for a directional sound outside of which there will be no sound.
+             * Listener angles between innerAngle and outerAngle will falloff linearly.
+             */
+            set: function (value) {
+                if (value !== this._coneOuterAngle) {
+                    if (value < this._coneInnerAngle) {
+                        BABYLON.Tools.Error("directionalConeOuterAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneOuterAngle = value;
+                    for (var _i = 0, _a = this._sounds; _i < _a.length; _i++) {
+                        var sound = _a[_i];
+                        sound.directionalConeOuterAngle = value;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(WeightedSound.prototype, "volume", {
+            /**
+             * Playback volume.
+             */
+            get: function () {
+                return this._volume;
+            },
+            /**
+             * Playback volume.
+             */
+            set: function (value) {
+                if (value !== this._volume) {
+                    for (var _i = 0, _a = this._sounds; _i < _a.length; _i++) {
+                        var sound = _a[_i];
+                        sound.setVolume(value);
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        WeightedSound.prototype._onended = function () {
+            if (this._currentIndex !== undefined) {
+                this._sounds[this._currentIndex].autoplay = false;
+            }
+            if (this.loop && this.isPlaying) {
+                this.play();
+            }
+            else {
+                this.isPlaying = false;
+            }
+        };
+        /**
+         * Suspend playback
+         */
+        WeightedSound.prototype.pause = function () {
+            this.isPaused = true;
+            if (this._currentIndex !== undefined) {
+                this._sounds[this._currentIndex].pause();
+            }
+        };
+        /**
+         * Stop playback
+         */
+        WeightedSound.prototype.stop = function () {
+            this.isPlaying = false;
+            if (this._currentIndex !== undefined) {
+                this._sounds[this._currentIndex].stop();
+            }
+        };
+        /**
+         * Start playback.
+         * @param startOffset Position the clip head at a specific time in seconds.
+         */
+        WeightedSound.prototype.play = function (startOffset) {
+            if (!this.isPaused) {
+                this.stop();
+                var randomValue = Math.random();
+                var total = 0;
+                for (var i = 0; i < this._weights.length; i++) {
+                    total += this._weights[i];
+                    if (randomValue <= total) {
+                        this._currentIndex = i;
+                        break;
+                    }
+                }
+            }
+            var sound = this._sounds[this._currentIndex];
+            if (sound.isReady()) {
+                sound.play(0, this.isPaused ? undefined : startOffset);
+            }
+            else {
+                sound.autoplay = true;
+            }
+            this.isPlaying = true;
+            this.isPaused = false;
+        };
+        return WeightedSound;
+    }());
+    BABYLON.WeightedSound = WeightedSound;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.weightedsound.js.map
+
 
 
 

+ 267 - 13
dist/preview release/babylon.no-module.max.js

@@ -18348,7 +18348,7 @@ var BABYLON;
             return _this;
         }
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "TransformNode" string
          */
         TransformNode.prototype.getClassName = function () {
@@ -18462,7 +18462,7 @@ var BABYLON;
             configurable: true
         });
         /**
-         * Copies the paramater passed Matrix into the mesh Pose matrix.
+         * Copies the parameter passed Matrix into the mesh Pose matrix.
          * Returns the TransformNode.
          */
         TransformNode.prototype.updatePoseMatrix = function (matrix) {
@@ -18520,7 +18520,7 @@ var BABYLON;
         Object.defineProperty(TransformNode.prototype, "absolutePosition", {
             /**
              * Returns the current mesh absolute position.
-             * Retuns a Vector3.
+             * Returns a Vector3.
              */
             get: function () {
                 return this._absolutePosition;
@@ -50533,7 +50533,7 @@ var BABYLON;
         });
         Object.defineProperty(Animation, "ANIMATIONTYPE_VECTOR2", {
             /**
-             * Get the Vectpr2 animation type
+             * Get the Vector2 animation type
              */
             get: function () {
                 return Animation._ANIMATIONTYPE_VECTOR2;
@@ -50802,6 +50802,10 @@ var BABYLON;
              * This observable will notify when all animations have ended.
              */
             this.onAnimationGroupEndObservable = new BABYLON.Observable();
+            /**
+             * This observable will notify when all animations have paused.
+             */
+            this.onAnimationGroupPauseObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
@@ -50985,6 +50989,7 @@ var BABYLON;
                 var animatable = this._animatables[index];
                 animatable.pause();
             }
+            this.onAnimationGroupPauseObservable.notifyObservers(this);
             return this;
         };
         /**
@@ -51613,7 +51618,7 @@ var BABYLON;
                             index--;
                         }
                         event.isDone = true;
-                        event.action();
+                        event.action(currentFrame);
                     } // Don't do anything if the event has already be done.
                 }
             }
@@ -64317,11 +64322,17 @@ var BABYLON;
             this.maxDistance = 100;
             this.distanceModel = "linear";
             this._panningModel = "equalpower";
+            /**
+             * Observable event when the current playing sound finishes.
+             */
+            this.onEndedObservable = new BABYLON.Observable();
             this._playbackRate = 1;
             this._streaming = false;
             this._startTime = 0;
             this._startOffset = 0;
             this._position = BABYLON.Vector3.Zero();
+            /** @hidden */
+            this._positionInEmitterSpace = false;
             this._localDirection = new BABYLON.Vector3(1, 0, 0);
             this._volume = 1;
             this._isReadyToPlay = false;
@@ -64367,7 +64378,7 @@ var BABYLON;
                 this._soundGain = BABYLON.Engine.audioEngine.audioContext.createGain();
                 this._soundGain.gain.value = this._volume;
                 this._inputAudioNode = this._soundGain;
-                this._ouputAudioNode = this._soundGain;
+                this._outputAudioNode = this._soundGain;
                 if (this.spatialSound) {
                     this._createSpatialParameters();
                 }
@@ -64600,7 +64611,7 @@ var BABYLON;
                 }
                 this._soundPanner = BABYLON.Engine.audioEngine.audioContext.createPanner();
                 this._updateSpatialParameters();
-                this._soundPanner.connect(this._ouputAudioNode);
+                this._soundPanner.connect(this._outputAudioNode);
                 this._inputAudioNode = this._soundPanner;
             }
         };
@@ -64639,9 +64650,9 @@ var BABYLON;
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
                 if (this._isOutputConnected) {
-                    this._ouputAudioNode.disconnect();
+                    this._outputAudioNode.disconnect();
                 }
-                this._ouputAudioNode.connect(soundTrackAudioNode);
+                this._outputAudioNode.connect(soundTrackAudioNode);
                 this._isOutputConnected = true;
             }
         };
@@ -64665,9 +64676,59 @@ var BABYLON;
                 this.play();
             }
         };
+        Object.defineProperty(Sound.prototype, "directionalConeInnerAngle", {
+            /**
+             * Gets or sets the inner angle for the directional cone.
+             */
+            get: function () {
+                return this._coneInnerAngle;
+            },
+            /**
+             * Gets or sets the inner angle for the directional cone.
+             */
+            set: function (value) {
+                if (value != this._coneInnerAngle) {
+                    if (this._coneOuterAngle < value) {
+                        BABYLON.Tools.Error("directionalConeInnerAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneInnerAngle = value;
+                    if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner) {
+                        this._soundPanner.coneInnerAngle = this._coneInnerAngle;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Sound.prototype, "directionalConeOuterAngle", {
+            /**
+             * Gets or sets the outer angle for the directional cone.
+             */
+            get: function () {
+                return this._coneOuterAngle;
+            },
+            /**
+             * Gets or sets the outer angle for the directional cone.
+             */
+            set: function (value) {
+                if (value != this._coneOuterAngle) {
+                    if (value < this._coneInnerAngle) {
+                        BABYLON.Tools.Error("directionalConeOuterAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneOuterAngle = value;
+                    if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner) {
+                        this._soundPanner.coneOuterAngle = this._coneOuterAngle;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Sound.prototype.setPosition = function (newPosition) {
             this._position = newPosition;
-            if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner && !isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
             }
         };
@@ -64711,7 +64772,9 @@ var BABYLON;
                     var startTime = time ? BABYLON.Engine.audioEngine.audioContext.currentTime + time : BABYLON.Engine.audioEngine.audioContext.currentTime;
                     if (!this._soundSource || !this._streamingSource) {
                         if (this.spatialSound && this._soundPanner) {
-                            this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                            if (!isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
+                                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                            }
                             if (this._isDirectional) {
                                 this._soundPanner.coneInnerAngle = this._coneInnerAngle;
                                 this._soundPanner.coneOuterAngle = this._coneOuterAngle;
@@ -64762,6 +64825,7 @@ var BABYLON;
             if (this.onended) {
                 this.onended();
             }
+            this.onEndedObservable.notifyObservers(this);
         };
         /**
         * Stop the sound
@@ -64867,8 +64931,14 @@ var BABYLON;
                 return;
             }
             var mesh = node;
-            var boundingInfo = mesh.getBoundingInfo();
-            this.setPosition(boundingInfo.boundingSphere.centerWorld);
+            if (this._positionInEmitterSpace) {
+                mesh.worldMatrixFromCache.invertToRef(BABYLON.Tmp.Matrix[0]);
+                this.setPosition(BABYLON.Tmp.Matrix[0].getTranslation());
+            }
+            else {
+                var boundingInfo = mesh.getBoundingInfo();
+                this.setPosition(boundingInfo.boundingSphere.centerWorld);
+            }
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();
             }
@@ -65287,6 +65357,190 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.analyser.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Wraps one or more Sound objects and selects one with random weight for playback.
+     */
+    var WeightedSound = /** @class */ (function () {
+        /**
+         * Creates a new WeightedSound from the list of sounds given.
+         * @param loop When true a Sound will be selected and played when the current playing Sound completes.
+         * @param sounds Array of Sounds that will be selected from.
+         * @param weights Array of number values for selection weights; length must equal sounds, values will be normalized to 1
+         */
+        function WeightedSound(loop, sounds, weights) {
+            var _this = this;
+            /** When true a Sound will be selected and played when the current playing Sound completes. */
+            this.loop = false;
+            this._coneInnerAngle = 360;
+            this._coneOuterAngle = 360;
+            this._volume = 1;
+            /** A Sound is currently playing. */
+            this.isPlaying = false;
+            /** A Sound is currently paused. */
+            this.isPaused = false;
+            this._sounds = [];
+            this._weights = [];
+            if (sounds.length !== weights.length) {
+                throw new Error('Sounds length does not equal weights length');
+            }
+            this.loop = loop;
+            this._weights = weights;
+            // Normalize the weights
+            var weightSum = 0;
+            for (var _i = 0, weights_1 = weights; _i < weights_1.length; _i++) {
+                var weight = weights_1[_i];
+                weightSum += weight;
+            }
+            var invWeightSum = weightSum > 0 ? 1 / weightSum : 0;
+            for (var i = 0; i < this._weights.length; i++) {
+                this._weights[i] *= invWeightSum;
+            }
+            this._sounds = sounds;
+            for (var _a = 0, _b = this._sounds; _a < _b.length; _a++) {
+                var sound = _b[_a];
+                sound.onEndedObservable.add(function () { _this._onended(); });
+            }
+        }
+        Object.defineProperty(WeightedSound.prototype, "directionalConeInnerAngle", {
+            /**
+             * The size of cone in degrees for a directional sound in which there will be no attenuation.
+             */
+            get: function () {
+                return this._coneInnerAngle;
+            },
+            /**
+             * The size of cone in degress for a directional sound in which there will be no attenuation.
+             */
+            set: function (value) {
+                if (value !== this._coneInnerAngle) {
+                    if (this._coneOuterAngle < value) {
+                        BABYLON.Tools.Error("directionalConeInnerAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneInnerAngle = value;
+                    for (var _i = 0, _a = this._sounds; _i < _a.length; _i++) {
+                        var sound = _a[_i];
+                        sound.directionalConeInnerAngle = value;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(WeightedSound.prototype, "directionalConeOuterAngle", {
+            /**
+             * Size of cone in degrees for a directional sound outside of which there will be no sound.
+             * Listener angles between innerAngle and outerAngle will falloff linearly.
+             */
+            get: function () {
+                return this._coneOuterAngle;
+            },
+            /**
+             * Size of cone in degrees for a directional sound outside of which there will be no sound.
+             * Listener angles between innerAngle and outerAngle will falloff linearly.
+             */
+            set: function (value) {
+                if (value !== this._coneOuterAngle) {
+                    if (value < this._coneInnerAngle) {
+                        BABYLON.Tools.Error("directionalConeOuterAngle: outer angle of the cone must be superior or equal to the inner angle.");
+                        return;
+                    }
+                    this._coneOuterAngle = value;
+                    for (var _i = 0, _a = this._sounds; _i < _a.length; _i++) {
+                        var sound = _a[_i];
+                        sound.directionalConeOuterAngle = value;
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(WeightedSound.prototype, "volume", {
+            /**
+             * Playback volume.
+             */
+            get: function () {
+                return this._volume;
+            },
+            /**
+             * Playback volume.
+             */
+            set: function (value) {
+                if (value !== this._volume) {
+                    for (var _i = 0, _a = this._sounds; _i < _a.length; _i++) {
+                        var sound = _a[_i];
+                        sound.setVolume(value);
+                    }
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        WeightedSound.prototype._onended = function () {
+            if (this._currentIndex !== undefined) {
+                this._sounds[this._currentIndex].autoplay = false;
+            }
+            if (this.loop && this.isPlaying) {
+                this.play();
+            }
+            else {
+                this.isPlaying = false;
+            }
+        };
+        /**
+         * Suspend playback
+         */
+        WeightedSound.prototype.pause = function () {
+            this.isPaused = true;
+            if (this._currentIndex !== undefined) {
+                this._sounds[this._currentIndex].pause();
+            }
+        };
+        /**
+         * Stop playback
+         */
+        WeightedSound.prototype.stop = function () {
+            this.isPlaying = false;
+            if (this._currentIndex !== undefined) {
+                this._sounds[this._currentIndex].stop();
+            }
+        };
+        /**
+         * Start playback.
+         * @param startOffset Position the clip head at a specific time in seconds.
+         */
+        WeightedSound.prototype.play = function (startOffset) {
+            if (!this.isPaused) {
+                this.stop();
+                var randomValue = Math.random();
+                var total = 0;
+                for (var i = 0; i < this._weights.length; i++) {
+                    total += this._weights[i];
+                    if (randomValue <= total) {
+                        this._currentIndex = i;
+                        break;
+                    }
+                }
+            }
+            var sound = this._sounds[this._currentIndex];
+            if (sound.isReady()) {
+                sound.play(0, this.isPaused ? undefined : startOffset);
+            }
+            else {
+                sound.autoplay = true;
+            }
+            this.isPlaying = true;
+            this.isPaused = false;
+        };
+        return WeightedSound;
+    }());
+    BABYLON.WeightedSound = WeightedSound;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.weightedsound.js.map
+
 
 
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 29 - 29
dist/preview release/babylon.worker.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 269 - 15
dist/preview release/es6.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 28 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -512,7 +512,7 @@ declare module BABYLON.GLTF2 {
         private _getNodeMatrix(node);
         private _loadCamera(context, camera, babylonMesh);
         private _loadAnimationsAsync();
-        private _loadAnimationAsync(context, animation);
+        _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Promise<void>;
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
@@ -620,6 +620,8 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /** Override this method to modify the default behavior for loading animations. */
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
         /**
          * Helper method called by a loader extension to load an glTF extension.
          * @hidden
@@ -680,6 +682,11 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         static _LoadUriAsync(loader: GLTFLoader, context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /**
+         * Helper method called by the loader to allow extensions to override loading animations.
+         * @hidden
+         */
+        static _LoadAnimationAsync(loader: GLTFLoader, context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
     }
 }
 /**
@@ -691,6 +698,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter extends GLTFLoaderExtension {
+        readonly name: string;
+        private _loadClipAsync(context, clip);
+        private _loadEmitterAsync(context, emitter);
+        protected _loadSceneAsync(context: string, scene: _ILoaderScene): Nullable<Promise<void>>;
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
+        private _getEventAction(context, sound, action, time, startOffset?);
+        private _loadAnimationEventAsync(context, animationContext, animation, event, babylonAnimationGroup);
+        private readonly _extension;
+        private readonly _clips;
+        private readonly _emitters;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod extends GLTFLoaderExtension {

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

@@ -1431,6 +1431,10 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadAnimationAsync = function (context, animation) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadAnimationAsync(this, context, animation);
+                if (promise) {
+                    return promise;
+                }
                 var babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation._index, this._babylonScene);
                 animation._babylonAnimationGroup = babylonAnimationGroup;
                 var promises = new Array();
@@ -2290,6 +2294,8 @@ var BABYLON;
              * @hidden
              */
             GLTFLoaderExtension.prototype._loadUriAsync = function (context, uri) { return null; };
+            /** Override this method to modify the default behavior for loading animations. */
+            GLTFLoaderExtension.prototype._loadAnimationAsync = function (context, animation) { return null; };
             // #endregion
             /**
              * Helper method called by a loader extension to load an glTF extension.
@@ -2407,6 +2413,13 @@ var BABYLON;
             GLTFLoaderExtension._LoadUriAsync = function (loader, context, uri) {
                 return loader._applyExtensions(function (extension) { return extension._loadUriAsync(context, uri); });
             };
+            /**
+             * Helper method called by the loader to allow extensions to override loading animations.
+             * @hidden
+             */
+            GLTFLoaderExtension._LoadAnimationAsync = function (loader, context, animation) {
+                return loader._applyExtensions(function (extension) { return extension._loadAnimationAsync(context, animation); });
+            };
             return GLTFLoaderExtension;
         }());
         GLTF2.GLTFLoaderExtension = GLTFLoaderExtension;
@@ -2432,6 +2445,238 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            var NAME = "MSFT_audio_emitter";
+            /**
+             * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+             */
+            var MSFT_audio_emitter = /** @class */ (function (_super) {
+                __extends(MSFT_audio_emitter, _super);
+                function MSFT_audio_emitter() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                MSFT_audio_emitter.prototype._loadClipAsync = function (context, clip) {
+                    if (clip._objectURL) {
+                        return clip._objectURL;
+                    }
+                    var promise;
+                    if (clip.uri) {
+                        promise = this._loader._loadUriAsync(context, clip.uri);
+                    }
+                    else {
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(context + "/bufferView", this._loader._gltf.bufferViews, clip.bufferView);
+                        promise = this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView);
+                    }
+                    clip._objectURL = promise.then(function (data) {
+                        return URL.createObjectURL(new Blob([data], { type: clip.mimeType }));
+                    });
+                    return clip._objectURL;
+                };
+                MSFT_audio_emitter.prototype._loadEmitterAsync = function (context, emitter) {
+                    var _this = this;
+                    emitter._babylonSounds = emitter._babylonSounds || [];
+                    if (!emitter._babylonData) {
+                        var clipPromises = new Array();
+                        var name_1 = emitter.name || "emitter" + emitter._index;
+                        var options_1 = {
+                            loop: false,
+                            autoplay: false,
+                            volume: emitter.volume == undefined ? 1 : emitter.volume,
+                        };
+                        GLTF2._ArrayItem.Assign(this._clips);
+                        var _loop_1 = function (i) {
+                            var clipContext = "#/extensions/" + NAME + "/clips";
+                            var clip = GLTF2.GLTFLoader._GetProperty(clipContext, this_1._clips, emitter.clips[i].clip);
+                            clipPromises.push(this_1._loadClipAsync(clipContext + "/" + emitter.clips[i].clip, clip).then(function (objectURL) {
+                                var sound = emitter._babylonSounds[i] = new BABYLON.Sound(name_1, objectURL, _this._loader._babylonScene, null, options_1);
+                                sound.refDistance = emitter.refDistance || 1;
+                                sound.maxDistance = emitter.maxDistance || 256;
+                                sound.rolloffFactor = emitter.rolloffFactor || 1;
+                                sound.distanceModel = emitter.distanceModel || 'exponential';
+                                sound._positionInEmitterSpace = true;
+                            }));
+                        };
+                        var this_1 = this;
+                        for (var i = 0; i < emitter.clips.length; i++) {
+                            _loop_1(i);
+                        }
+                        var promise = Promise.all(clipPromises).then(function () {
+                            var weights = emitter.clips.map(function (clip) { return clip.weight || 1; });
+                            var weightedSound = new BABYLON.WeightedSound(emitter.loop || false, emitter._babylonSounds, weights);
+                            if (emitter.innerAngle)
+                                weightedSound.directionalConeInnerAngle = 2 * BABYLON.Tools.ToDegrees(emitter.innerAngle);
+                            if (emitter.outerAngle)
+                                weightedSound.directionalConeOuterAngle = 2 * BABYLON.Tools.ToDegrees(emitter.outerAngle);
+                            if (emitter.volume)
+                                weightedSound.volume = emitter.volume;
+                            emitter._babylonData.sound = weightedSound;
+                        });
+                        emitter._babylonData = {
+                            loaded: promise
+                        };
+                    }
+                    return emitter._babylonData.loaded;
+                };
+                MSFT_audio_emitter.prototype._loadSceneAsync = function (context, scene) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, scene, function (extensionContext, extension) {
+                        return _this._loader._loadSceneAsync(context, scene).then(function () {
+                            var promises = new Array();
+                            GLTF2._ArrayItem.Assign(_this._emitters);
+                            for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) {
+                                var emitterIndex = _a[_i];
+                                var emitter = GLTF2.GLTFLoader._GetProperty(extensionContext + "/emitters", _this._emitters, emitterIndex);
+                                if (emitter.refDistance != undefined || emitter.maxDistance != undefined || emitter.rolloffFactor != undefined ||
+                                    emitter.distanceModel != undefined || emitter.innerAngle != undefined || emitter.outerAngle != undefined) {
+                                    throw new Error(extensionContext + ": Direction or Distance properties are not allowed on emitters attached to a scene");
+                                }
+                                promises.push(_this._loadEmitterAsync(extensionContext + "/emitters/" + emitter._index, emitter));
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._loadNodeAsync = function (context, node) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, node, function (extensionContext, extension) {
+                        return _this._loader._loadNodeAsync(extensionContext, node).then(function () {
+                            var promises = new Array();
+                            GLTF2._ArrayItem.Assign(_this._emitters);
+                            var _loop_2 = function (emitterIndex) {
+                                var emitter = GLTF2.GLTFLoader._GetProperty(extensionContext + "/emitters", _this._emitters, emitterIndex);
+                                promises.push(_this._loadEmitterAsync(extensionContext + "/emitters/" + emitter._index, emitter).then(function () {
+                                    if (node._babylonMesh) {
+                                        for (var _i = 0, _a = emitter._babylonSounds; _i < _a.length; _i++) {
+                                            var sound = _a[_i];
+                                            sound.attachToMesh(node._babylonMesh);
+                                            if (emitter.innerAngle != undefined || emitter.outerAngle != undefined) {
+                                                sound.setLocalDirectionToMesh(new BABYLON.Vector3(0, 0, 1));
+                                                sound.setDirectionalCone(2 * BABYLON.Tools.ToDegrees(emitter.innerAngle == undefined ? Math.PI : emitter.innerAngle), 2 * BABYLON.Tools.ToDegrees(emitter.outerAngle == undefined ? Math.PI : emitter.outerAngle), 0);
+                                            }
+                                        }
+                                    }
+                                }));
+                            };
+                            for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) {
+                                var emitterIndex = _a[_i];
+                                _loop_2(emitterIndex);
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._loadAnimationAsync = function (context, animation) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, animation, function (extensionContext, extension) {
+                        return _this._loader._loadAnimationAsync(extensionContext, animation).then(function () {
+                            var promises = new Array();
+                            var babylonAnimationGroup = animation._babylonAnimationGroup;
+                            GLTF2._ArrayItem.Assign(extension.events);
+                            for (var _i = 0, _a = extension.events; _i < _a.length; _i++) {
+                                var event_1 = _a[_i];
+                                promises.push(_this._loadAnimationEventAsync(extensionContext + "/events/" + event_1._index, context, animation, event_1, babylonAnimationGroup));
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._getEventAction = function (context, sound, action, time, startOffset) {
+                    if (action == "play" /* play */) {
+                        return function (currentFrame) {
+                            var frameOffset = (startOffset || 0) + (currentFrame - time);
+                            sound.play(frameOffset);
+                        };
+                    }
+                    else if (action == "stop" /* stop */) {
+                        return function (currentFrame) {
+                            sound.stop();
+                        };
+                    }
+                    else if (action == "pause" /* pause */) {
+                        return function (currentFrame) {
+                            sound.pause();
+                        };
+                    }
+                    else {
+                        throw new Error(context + ": Unsupported action " + action);
+                    }
+                };
+                MSFT_audio_emitter.prototype._loadAnimationEventAsync = function (context, animationContext, animation, event, babylonAnimationGroup) {
+                    var _this = this;
+                    if (babylonAnimationGroup.targetedAnimations.length == 0) {
+                        return Promise.resolve();
+                    }
+                    var babylonAnimation = babylonAnimationGroup.targetedAnimations[0];
+                    var emitterIndex = event.emitter;
+                    var emitter = GLTF2.GLTFLoader._GetProperty("#/extensions/" + NAME + "/emitters", this._emitters, emitterIndex);
+                    return this._loadEmitterAsync(context, emitter).then(function () {
+                        var sound = emitter._babylonData.sound;
+                        if (sound) {
+                            var babylonAnimationEvent = new BABYLON.AnimationEvent(event.time, _this._getEventAction(context, sound, event.action, event.time, event.startOffset));
+                            babylonAnimation.animation.addEvent(babylonAnimationEvent);
+                            // Make sure all started audio stops when this animation is terminated.
+                            babylonAnimationGroup.onAnimationGroupEndObservable.add(function () {
+                                sound.stop();
+                            });
+                            babylonAnimationGroup.onAnimationGroupPauseObservable.add(function () {
+                                sound.pause();
+                            });
+                        }
+                    });
+                };
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_extension", {
+                    get: function () {
+                        var extensions = this._loader._gltf.extensions;
+                        if (!extensions || !extensions[this.name]) {
+                            throw new Error("#/extensions: '" + this.name + "' not found");
+                        }
+                        return extensions[this.name];
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_clips", {
+                    get: function () {
+                        return this._extension.clips;
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_emitters", {
+                    get: function () {
+                        return this._extension.emitters;
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                return MSFT_audio_emitter;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_audio_emitter = MSFT_audio_emitter;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_audio_emitter(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_audio_emitter.js.map
+
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             var NAME = "MSFT_lod";
             /**
              * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3 - 3
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 28 - 1
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -1074,7 +1074,7 @@ declare module BABYLON.GLTF2 {
         private _getNodeMatrix(node);
         private _loadCamera(context, camera, babylonMesh);
         private _loadAnimationsAsync();
-        private _loadAnimationAsync(context, animation);
+        _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Promise<void>;
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
@@ -1182,6 +1182,8 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /** Override this method to modify the default behavior for loading animations. */
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
         /**
          * Helper method called by a loader extension to load an glTF extension.
          * @hidden
@@ -1242,6 +1244,11 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         static _LoadUriAsync(loader: GLTFLoader, context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /**
+         * Helper method called by the loader to allow extensions to override loading animations.
+         * @hidden
+         */
+        static _LoadAnimationAsync(loader: GLTFLoader, context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
     }
 }
 /**
@@ -1253,6 +1260,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter extends GLTFLoaderExtension {
+        readonly name: string;
+        private _loadClipAsync(context, clip);
+        private _loadEmitterAsync(context, emitter);
+        protected _loadSceneAsync(context: string, scene: _ILoaderScene): Nullable<Promise<void>>;
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
+        private _getEventAction(context, sound, action, time, startOffset?);
+        private _loadAnimationEventAsync(context, animationContext, animation, event, babylonAnimationGroup);
+        private readonly _extension;
+        private readonly _clips;
+        private readonly _emitters;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod extends GLTFLoaderExtension {

+ 245 - 2
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3632,6 +3632,10 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadAnimationAsync = function (context, animation) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadAnimationAsync(this, context, animation);
+                if (promise) {
+                    return promise;
+                }
                 var babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation._index, this._babylonScene);
                 animation._babylonAnimationGroup = babylonAnimationGroup;
                 var promises = new Array();
@@ -4491,6 +4495,8 @@ var BABYLON;
              * @hidden
              */
             GLTFLoaderExtension.prototype._loadUriAsync = function (context, uri) { return null; };
+            /** Override this method to modify the default behavior for loading animations. */
+            GLTFLoaderExtension.prototype._loadAnimationAsync = function (context, animation) { return null; };
             // #endregion
             /**
              * Helper method called by a loader extension to load an glTF extension.
@@ -4608,6 +4614,13 @@ var BABYLON;
             GLTFLoaderExtension._LoadUriAsync = function (loader, context, uri) {
                 return loader._applyExtensions(function (extension) { return extension._loadUriAsync(context, uri); });
             };
+            /**
+             * Helper method called by the loader to allow extensions to override loading animations.
+             * @hidden
+             */
+            GLTFLoaderExtension._LoadAnimationAsync = function (loader, context, animation) {
+                return loader._applyExtensions(function (extension) { return extension._loadAnimationAsync(context, animation); });
+            };
             return GLTFLoaderExtension;
         }());
         GLTF2.GLTFLoaderExtension = GLTFLoaderExtension;
@@ -4633,6 +4646,238 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            var NAME = "MSFT_audio_emitter";
+            /**
+             * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+             */
+            var MSFT_audio_emitter = /** @class */ (function (_super) {
+                __extends(MSFT_audio_emitter, _super);
+                function MSFT_audio_emitter() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                MSFT_audio_emitter.prototype._loadClipAsync = function (context, clip) {
+                    if (clip._objectURL) {
+                        return clip._objectURL;
+                    }
+                    var promise;
+                    if (clip.uri) {
+                        promise = this._loader._loadUriAsync(context, clip.uri);
+                    }
+                    else {
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(context + "/bufferView", this._loader._gltf.bufferViews, clip.bufferView);
+                        promise = this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView);
+                    }
+                    clip._objectURL = promise.then(function (data) {
+                        return URL.createObjectURL(new Blob([data], { type: clip.mimeType }));
+                    });
+                    return clip._objectURL;
+                };
+                MSFT_audio_emitter.prototype._loadEmitterAsync = function (context, emitter) {
+                    var _this = this;
+                    emitter._babylonSounds = emitter._babylonSounds || [];
+                    if (!emitter._babylonData) {
+                        var clipPromises = new Array();
+                        var name_1 = emitter.name || "emitter" + emitter._index;
+                        var options_1 = {
+                            loop: false,
+                            autoplay: false,
+                            volume: emitter.volume == undefined ? 1 : emitter.volume,
+                        };
+                        GLTF2._ArrayItem.Assign(this._clips);
+                        var _loop_1 = function (i) {
+                            var clipContext = "#/extensions/" + NAME + "/clips";
+                            var clip = GLTF2.GLTFLoader._GetProperty(clipContext, this_1._clips, emitter.clips[i].clip);
+                            clipPromises.push(this_1._loadClipAsync(clipContext + "/" + emitter.clips[i].clip, clip).then(function (objectURL) {
+                                var sound = emitter._babylonSounds[i] = new BABYLON.Sound(name_1, objectURL, _this._loader._babylonScene, null, options_1);
+                                sound.refDistance = emitter.refDistance || 1;
+                                sound.maxDistance = emitter.maxDistance || 256;
+                                sound.rolloffFactor = emitter.rolloffFactor || 1;
+                                sound.distanceModel = emitter.distanceModel || 'exponential';
+                                sound._positionInEmitterSpace = true;
+                            }));
+                        };
+                        var this_1 = this;
+                        for (var i = 0; i < emitter.clips.length; i++) {
+                            _loop_1(i);
+                        }
+                        var promise = Promise.all(clipPromises).then(function () {
+                            var weights = emitter.clips.map(function (clip) { return clip.weight || 1; });
+                            var weightedSound = new BABYLON.WeightedSound(emitter.loop || false, emitter._babylonSounds, weights);
+                            if (emitter.innerAngle)
+                                weightedSound.directionalConeInnerAngle = 2 * BABYLON.Tools.ToDegrees(emitter.innerAngle);
+                            if (emitter.outerAngle)
+                                weightedSound.directionalConeOuterAngle = 2 * BABYLON.Tools.ToDegrees(emitter.outerAngle);
+                            if (emitter.volume)
+                                weightedSound.volume = emitter.volume;
+                            emitter._babylonData.sound = weightedSound;
+                        });
+                        emitter._babylonData = {
+                            loaded: promise
+                        };
+                    }
+                    return emitter._babylonData.loaded;
+                };
+                MSFT_audio_emitter.prototype._loadSceneAsync = function (context, scene) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, scene, function (extensionContext, extension) {
+                        return _this._loader._loadSceneAsync(context, scene).then(function () {
+                            var promises = new Array();
+                            GLTF2._ArrayItem.Assign(_this._emitters);
+                            for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) {
+                                var emitterIndex = _a[_i];
+                                var emitter = GLTF2.GLTFLoader._GetProperty(extensionContext + "/emitters", _this._emitters, emitterIndex);
+                                if (emitter.refDistance != undefined || emitter.maxDistance != undefined || emitter.rolloffFactor != undefined ||
+                                    emitter.distanceModel != undefined || emitter.innerAngle != undefined || emitter.outerAngle != undefined) {
+                                    throw new Error(extensionContext + ": Direction or Distance properties are not allowed on emitters attached to a scene");
+                                }
+                                promises.push(_this._loadEmitterAsync(extensionContext + "/emitters/" + emitter._index, emitter));
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._loadNodeAsync = function (context, node) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, node, function (extensionContext, extension) {
+                        return _this._loader._loadNodeAsync(extensionContext, node).then(function () {
+                            var promises = new Array();
+                            GLTF2._ArrayItem.Assign(_this._emitters);
+                            var _loop_2 = function (emitterIndex) {
+                                var emitter = GLTF2.GLTFLoader._GetProperty(extensionContext + "/emitters", _this._emitters, emitterIndex);
+                                promises.push(_this._loadEmitterAsync(extensionContext + "/emitters/" + emitter._index, emitter).then(function () {
+                                    if (node._babylonMesh) {
+                                        for (var _i = 0, _a = emitter._babylonSounds; _i < _a.length; _i++) {
+                                            var sound = _a[_i];
+                                            sound.attachToMesh(node._babylonMesh);
+                                            if (emitter.innerAngle != undefined || emitter.outerAngle != undefined) {
+                                                sound.setLocalDirectionToMesh(new BABYLON.Vector3(0, 0, 1));
+                                                sound.setDirectionalCone(2 * BABYLON.Tools.ToDegrees(emitter.innerAngle == undefined ? Math.PI : emitter.innerAngle), 2 * BABYLON.Tools.ToDegrees(emitter.outerAngle == undefined ? Math.PI : emitter.outerAngle), 0);
+                                            }
+                                        }
+                                    }
+                                }));
+                            };
+                            for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) {
+                                var emitterIndex = _a[_i];
+                                _loop_2(emitterIndex);
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._loadAnimationAsync = function (context, animation) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, animation, function (extensionContext, extension) {
+                        return _this._loader._loadAnimationAsync(extensionContext, animation).then(function () {
+                            var promises = new Array();
+                            var babylonAnimationGroup = animation._babylonAnimationGroup;
+                            GLTF2._ArrayItem.Assign(extension.events);
+                            for (var _i = 0, _a = extension.events; _i < _a.length; _i++) {
+                                var event_1 = _a[_i];
+                                promises.push(_this._loadAnimationEventAsync(extensionContext + "/events/" + event_1._index, context, animation, event_1, babylonAnimationGroup));
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._getEventAction = function (context, sound, action, time, startOffset) {
+                    if (action == "play" /* play */) {
+                        return function (currentFrame) {
+                            var frameOffset = (startOffset || 0) + (currentFrame - time);
+                            sound.play(frameOffset);
+                        };
+                    }
+                    else if (action == "stop" /* stop */) {
+                        return function (currentFrame) {
+                            sound.stop();
+                        };
+                    }
+                    else if (action == "pause" /* pause */) {
+                        return function (currentFrame) {
+                            sound.pause();
+                        };
+                    }
+                    else {
+                        throw new Error(context + ": Unsupported action " + action);
+                    }
+                };
+                MSFT_audio_emitter.prototype._loadAnimationEventAsync = function (context, animationContext, animation, event, babylonAnimationGroup) {
+                    var _this = this;
+                    if (babylonAnimationGroup.targetedAnimations.length == 0) {
+                        return Promise.resolve();
+                    }
+                    var babylonAnimation = babylonAnimationGroup.targetedAnimations[0];
+                    var emitterIndex = event.emitter;
+                    var emitter = GLTF2.GLTFLoader._GetProperty("#/extensions/" + NAME + "/emitters", this._emitters, emitterIndex);
+                    return this._loadEmitterAsync(context, emitter).then(function () {
+                        var sound = emitter._babylonData.sound;
+                        if (sound) {
+                            var babylonAnimationEvent = new BABYLON.AnimationEvent(event.time, _this._getEventAction(context, sound, event.action, event.time, event.startOffset));
+                            babylonAnimation.animation.addEvent(babylonAnimationEvent);
+                            // Make sure all started audio stops when this animation is terminated.
+                            babylonAnimationGroup.onAnimationGroupEndObservable.add(function () {
+                                sound.stop();
+                            });
+                            babylonAnimationGroup.onAnimationGroupPauseObservable.add(function () {
+                                sound.pause();
+                            });
+                        }
+                    });
+                };
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_extension", {
+                    get: function () {
+                        var extensions = this._loader._gltf.extensions;
+                        if (!extensions || !extensions[this.name]) {
+                            throw new Error("#/extensions: '" + this.name + "' not found");
+                        }
+                        return extensions[this.name];
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_clips", {
+                    get: function () {
+                        return this._extension.clips;
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_emitters", {
+                    get: function () {
+                        return this._extension.emitters;
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                return MSFT_audio_emitter;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_audio_emitter = MSFT_audio_emitter;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_audio_emitter(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_audio_emitter.js.map
+
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             var NAME = "MSFT_lod";
             /**
              * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
@@ -5216,8 +5461,6 @@ var BABYLON;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=KHR_materials_unlit.js.map
-
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = Object.setPrototypeOf ||

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4 - 4
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 28 - 1
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -1176,7 +1176,7 @@ declare module BABYLON.GLTF2 {
         private _getNodeMatrix(node);
         private _loadCamera(context, camera, babylonMesh);
         private _loadAnimationsAsync();
-        private _loadAnimationAsync(context, animation);
+        _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Promise<void>;
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
@@ -1284,6 +1284,8 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /** Override this method to modify the default behavior for loading animations. */
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
         /**
          * Helper method called by a loader extension to load an glTF extension.
          * @hidden
@@ -1344,6 +1346,11 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         static _LoadUriAsync(loader: GLTFLoader, context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /**
+         * Helper method called by the loader to allow extensions to override loading animations.
+         * @hidden
+         */
+        static _LoadAnimationAsync(loader: GLTFLoader, context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
     }
 }
 /**
@@ -1355,6 +1362,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter extends GLTFLoaderExtension {
+        readonly name: string;
+        private _loadClipAsync(context, clip);
+        private _loadEmitterAsync(context, emitter);
+        protected _loadSceneAsync(context: string, scene: _ILoaderScene): Nullable<Promise<void>>;
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
+        private _getEventAction(context, sound, action, time, startOffset?);
+        private _loadAnimationEventAsync(context, animationContext, animation, event, babylonAnimationGroup);
+        private readonly _extension;
+        private readonly _clips;
+        private readonly _emitters;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod extends GLTFLoaderExtension {

+ 236 - 2
dist/preview release/loaders/babylonjs.loaders.js

@@ -4669,6 +4669,10 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadAnimationAsync = function (context, animation) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadAnimationAsync(this, context, animation);
+                if (promise) {
+                    return promise;
+                }
                 var babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation._index, this._babylonScene);
                 animation._babylonAnimationGroup = babylonAnimationGroup;
                 var promises = new Array();
@@ -5528,6 +5532,8 @@ var BABYLON;
              * @hidden
              */
             GLTFLoaderExtension.prototype._loadUriAsync = function (context, uri) { return null; };
+            /** Override this method to modify the default behavior for loading animations. */
+            GLTFLoaderExtension.prototype._loadAnimationAsync = function (context, animation) { return null; };
             // #endregion
             /**
              * Helper method called by a loader extension to load an glTF extension.
@@ -5645,6 +5651,13 @@ var BABYLON;
             GLTFLoaderExtension._LoadUriAsync = function (loader, context, uri) {
                 return loader._applyExtensions(function (extension) { return extension._loadUriAsync(context, uri); });
             };
+            /**
+             * Helper method called by the loader to allow extensions to override loading animations.
+             * @hidden
+             */
+            GLTFLoaderExtension._LoadAnimationAsync = function (loader, context, animation) {
+                return loader._applyExtensions(function (extension) { return extension._loadAnimationAsync(context, animation); });
+            };
             return GLTFLoaderExtension;
         }());
         GLTF2.GLTFLoaderExtension = GLTFLoaderExtension;
@@ -5661,6 +5674,229 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            var NAME = "MSFT_audio_emitter";
+            /**
+             * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+             */
+            var MSFT_audio_emitter = /** @class */ (function (_super) {
+                __extends(MSFT_audio_emitter, _super);
+                function MSFT_audio_emitter() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                MSFT_audio_emitter.prototype._loadClipAsync = function (context, clip) {
+                    if (clip._objectURL) {
+                        return clip._objectURL;
+                    }
+                    var promise;
+                    if (clip.uri) {
+                        promise = this._loader._loadUriAsync(context, clip.uri);
+                    }
+                    else {
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(context + "/bufferView", this._loader._gltf.bufferViews, clip.bufferView);
+                        promise = this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView);
+                    }
+                    clip._objectURL = promise.then(function (data) {
+                        return URL.createObjectURL(new Blob([data], { type: clip.mimeType }));
+                    });
+                    return clip._objectURL;
+                };
+                MSFT_audio_emitter.prototype._loadEmitterAsync = function (context, emitter) {
+                    var _this = this;
+                    emitter._babylonSounds = emitter._babylonSounds || [];
+                    if (!emitter._babylonData) {
+                        var clipPromises = new Array();
+                        var name_1 = emitter.name || "emitter" + emitter._index;
+                        var options_1 = {
+                            loop: false,
+                            autoplay: false,
+                            volume: emitter.volume == undefined ? 1 : emitter.volume,
+                        };
+                        GLTF2._ArrayItem.Assign(this._clips);
+                        var _loop_1 = function (i) {
+                            var clipContext = "#/extensions/" + NAME + "/clips";
+                            var clip = GLTF2.GLTFLoader._GetProperty(clipContext, this_1._clips, emitter.clips[i].clip);
+                            clipPromises.push(this_1._loadClipAsync(clipContext + "/" + emitter.clips[i].clip, clip).then(function (objectURL) {
+                                var sound = emitter._babylonSounds[i] = new BABYLON.Sound(name_1, objectURL, _this._loader._babylonScene, null, options_1);
+                                sound.refDistance = emitter.refDistance || 1;
+                                sound.maxDistance = emitter.maxDistance || 256;
+                                sound.rolloffFactor = emitter.rolloffFactor || 1;
+                                sound.distanceModel = emitter.distanceModel || 'exponential';
+                                sound._positionInEmitterSpace = true;
+                            }));
+                        };
+                        var this_1 = this;
+                        for (var i = 0; i < emitter.clips.length; i++) {
+                            _loop_1(i);
+                        }
+                        var promise = Promise.all(clipPromises).then(function () {
+                            var weights = emitter.clips.map(function (clip) { return clip.weight || 1; });
+                            var weightedSound = new BABYLON.WeightedSound(emitter.loop || false, emitter._babylonSounds, weights);
+                            if (emitter.innerAngle)
+                                weightedSound.directionalConeInnerAngle = 2 * BABYLON.Tools.ToDegrees(emitter.innerAngle);
+                            if (emitter.outerAngle)
+                                weightedSound.directionalConeOuterAngle = 2 * BABYLON.Tools.ToDegrees(emitter.outerAngle);
+                            if (emitter.volume)
+                                weightedSound.volume = emitter.volume;
+                            emitter._babylonData.sound = weightedSound;
+                        });
+                        emitter._babylonData = {
+                            loaded: promise
+                        };
+                    }
+                    return emitter._babylonData.loaded;
+                };
+                MSFT_audio_emitter.prototype._loadSceneAsync = function (context, scene) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, scene, function (extensionContext, extension) {
+                        return _this._loader._loadSceneAsync(context, scene).then(function () {
+                            var promises = new Array();
+                            GLTF2._ArrayItem.Assign(_this._emitters);
+                            for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) {
+                                var emitterIndex = _a[_i];
+                                var emitter = GLTF2.GLTFLoader._GetProperty(extensionContext + "/emitters", _this._emitters, emitterIndex);
+                                if (emitter.refDistance != undefined || emitter.maxDistance != undefined || emitter.rolloffFactor != undefined ||
+                                    emitter.distanceModel != undefined || emitter.innerAngle != undefined || emitter.outerAngle != undefined) {
+                                    throw new Error(extensionContext + ": Direction or Distance properties are not allowed on emitters attached to a scene");
+                                }
+                                promises.push(_this._loadEmitterAsync(extensionContext + "/emitters/" + emitter._index, emitter));
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._loadNodeAsync = function (context, node) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, node, function (extensionContext, extension) {
+                        return _this._loader._loadNodeAsync(extensionContext, node).then(function () {
+                            var promises = new Array();
+                            GLTF2._ArrayItem.Assign(_this._emitters);
+                            var _loop_2 = function (emitterIndex) {
+                                var emitter = GLTF2.GLTFLoader._GetProperty(extensionContext + "/emitters", _this._emitters, emitterIndex);
+                                promises.push(_this._loadEmitterAsync(extensionContext + "/emitters/" + emitter._index, emitter).then(function () {
+                                    if (node._babylonMesh) {
+                                        for (var _i = 0, _a = emitter._babylonSounds; _i < _a.length; _i++) {
+                                            var sound = _a[_i];
+                                            sound.attachToMesh(node._babylonMesh);
+                                            if (emitter.innerAngle != undefined || emitter.outerAngle != undefined) {
+                                                sound.setLocalDirectionToMesh(new BABYLON.Vector3(0, 0, 1));
+                                                sound.setDirectionalCone(2 * BABYLON.Tools.ToDegrees(emitter.innerAngle == undefined ? Math.PI : emitter.innerAngle), 2 * BABYLON.Tools.ToDegrees(emitter.outerAngle == undefined ? Math.PI : emitter.outerAngle), 0);
+                                            }
+                                        }
+                                    }
+                                }));
+                            };
+                            for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) {
+                                var emitterIndex = _a[_i];
+                                _loop_2(emitterIndex);
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._loadAnimationAsync = function (context, animation) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, animation, function (extensionContext, extension) {
+                        return _this._loader._loadAnimationAsync(extensionContext, animation).then(function () {
+                            var promises = new Array();
+                            var babylonAnimationGroup = animation._babylonAnimationGroup;
+                            GLTF2._ArrayItem.Assign(extension.events);
+                            for (var _i = 0, _a = extension.events; _i < _a.length; _i++) {
+                                var event_1 = _a[_i];
+                                promises.push(_this._loadAnimationEventAsync(extensionContext + "/events/" + event_1._index, context, animation, event_1, babylonAnimationGroup));
+                            }
+                            return Promise.all(promises).then(function () { });
+                        });
+                    });
+                };
+                MSFT_audio_emitter.prototype._getEventAction = function (context, sound, action, time, startOffset) {
+                    if (action == "play" /* play */) {
+                        return function (currentFrame) {
+                            var frameOffset = (startOffset || 0) + (currentFrame - time);
+                            sound.play(frameOffset);
+                        };
+                    }
+                    else if (action == "stop" /* stop */) {
+                        return function (currentFrame) {
+                            sound.stop();
+                        };
+                    }
+                    else if (action == "pause" /* pause */) {
+                        return function (currentFrame) {
+                            sound.pause();
+                        };
+                    }
+                    else {
+                        throw new Error(context + ": Unsupported action " + action);
+                    }
+                };
+                MSFT_audio_emitter.prototype._loadAnimationEventAsync = function (context, animationContext, animation, event, babylonAnimationGroup) {
+                    var _this = this;
+                    if (babylonAnimationGroup.targetedAnimations.length == 0) {
+                        return Promise.resolve();
+                    }
+                    var babylonAnimation = babylonAnimationGroup.targetedAnimations[0];
+                    var emitterIndex = event.emitter;
+                    var emitter = GLTF2.GLTFLoader._GetProperty("#/extensions/" + NAME + "/emitters", this._emitters, emitterIndex);
+                    return this._loadEmitterAsync(context, emitter).then(function () {
+                        var sound = emitter._babylonData.sound;
+                        if (sound) {
+                            var babylonAnimationEvent = new BABYLON.AnimationEvent(event.time, _this._getEventAction(context, sound, event.action, event.time, event.startOffset));
+                            babylonAnimation.animation.addEvent(babylonAnimationEvent);
+                            // Make sure all started audio stops when this animation is terminated.
+                            babylonAnimationGroup.onAnimationGroupEndObservable.add(function () {
+                                sound.stop();
+                            });
+                            babylonAnimationGroup.onAnimationGroupPauseObservable.add(function () {
+                                sound.pause();
+                            });
+                        }
+                    });
+                };
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_extension", {
+                    get: function () {
+                        var extensions = this._loader._gltf.extensions;
+                        if (!extensions || !extensions[this.name]) {
+                            throw new Error("#/extensions: '" + this.name + "' not found");
+                        }
+                        return extensions[this.name];
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_clips", {
+                    get: function () {
+                        return this._extension.clips;
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                Object.defineProperty(MSFT_audio_emitter.prototype, "_emitters", {
+                    get: function () {
+                        return this._extension.emitters;
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                return MSFT_audio_emitter;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_audio_emitter = MSFT_audio_emitter;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_audio_emitter(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_audio_emitter.js.map
+
+
+
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             var NAME = "MSFT_lod";
             /**
              * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
@@ -6199,8 +6435,6 @@ var BABYLON;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=KHR_materials_unlit.js.map
-
 
 
 var BABYLON;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4 - 4
dist/preview release/loaders/babylonjs.loaders.min.js


+ 28 - 1
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -1183,7 +1183,7 @@ declare module BABYLON.GLTF2 {
         private _getNodeMatrix(node);
         private _loadCamera(context, camera, babylonMesh);
         private _loadAnimationsAsync();
-        private _loadAnimationAsync(context, animation);
+        _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Promise<void>;
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
@@ -1291,6 +1291,8 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /** Override this method to modify the default behavior for loading animations. */
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
         /**
          * Helper method called by a loader extension to load an glTF extension.
          * @hidden
@@ -1351,6 +1353,11 @@ declare module BABYLON.GLTF2 {
          * @hidden
          */
         static _LoadUriAsync(loader: GLTFLoader, context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
+        /**
+         * Helper method called by the loader to allow extensions to override loading animations.
+         * @hidden
+         */
+        static _LoadAnimationAsync(loader: GLTFLoader, context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
     }
 }
 /**
@@ -1362,6 +1369,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter extends GLTFLoaderExtension {
+        readonly name: string;
+        private _loadClipAsync(context, clip);
+        private _loadEmitterAsync(context, emitter);
+        protected _loadSceneAsync(context: string, scene: _ILoaderScene): Nullable<Promise<void>>;
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;
+        protected _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Nullable<Promise<void>>;
+        private _getEventAction(context, sound, action, time, startOffset?);
+        private _loadAnimationEventAsync(context, animationContext, animation, event, babylonAnimationGroup);
+        private readonly _extension;
+        private readonly _clips;
+        private readonly _emitters;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod extends GLTFLoaderExtension {

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js