|
@@ -9470,6 +9470,10 @@ var BABYLON;
|
|
|
* @param fileName defines the name of the downloaded file
|
|
|
*/
|
|
|
Tools.Download = function (blob, fileName) {
|
|
|
+ if (navigator && navigator.msSaveBlob) {
|
|
|
+ navigator.msSaveBlob(blob, fileName);
|
|
|
+ return;
|
|
|
+ }
|
|
|
var url = window.URL.createObjectURL(blob);
|
|
|
var a = document.createElement("a");
|
|
|
document.body.appendChild(a);
|
|
@@ -24175,6 +24179,8 @@ var BABYLON;
|
|
|
*/
|
|
|
_this._afterCameraDrawStage = BABYLON.Stage.Create();
|
|
|
_this._activeMeshesFrozen = false;
|
|
|
+ /** @hidden */
|
|
|
+ _this._allowPostProcessClear = true;
|
|
|
_this._tempPickingRay = BABYLON.Ray ? BABYLON.Ray.Zero() : null;
|
|
|
_this._engine = engine || BABYLON.Engine.LastCreatedEngine;
|
|
|
_this._engine.scenes.push(_this);
|
|
@@ -67162,7 +67168,7 @@ var BABYLON;
|
|
|
}
|
|
|
this.onActivateObservable.notifyObservers(camera);
|
|
|
// Clear
|
|
|
- if (this.autoClear && this.alphaMode === BABYLON.Engine.ALPHA_DISABLE) {
|
|
|
+ if (scene._allowPostProcessClear && this.autoClear && this.alphaMode === BABYLON.Engine.ALPHA_DISABLE) {
|
|
|
this._engine.clear(this.clearColor ? this.clearColor : scene.clearColor, true, true, true);
|
|
|
}
|
|
|
if (this._reusable) {
|
|
@@ -89282,6 +89288,7 @@ var BABYLON;
|
|
|
this.onPointerOutObservable = new BABYLON.Observable();
|
|
|
// Create scene which will be rendered in the foreground and remove it from being referenced by engine to avoid interfering with existing app
|
|
|
this.utilityLayerScene = new BABYLON.Scene(originalScene.getEngine());
|
|
|
+ this.utilityLayerScene._allowPostProcessClear = false;
|
|
|
originalScene.getEngine().scenes.pop();
|
|
|
// Detach controls on utility scene, events will be fired by logic below to handle picking priority
|
|
|
this.utilityLayerScene.detachControl();
|
|
@@ -89399,7 +89406,27 @@ var BABYLON;
|
|
|
*/
|
|
|
UtilityLayerRenderer.prototype.render = function () {
|
|
|
this._updateCamera();
|
|
|
- this.utilityLayerScene.render(false);
|
|
|
+ if (this.utilityLayerScene.activeCamera) {
|
|
|
+ // Set the camera's scene to utility layers scene
|
|
|
+ var oldScene = this.utilityLayerScene.activeCamera.getScene();
|
|
|
+ var camera = this.utilityLayerScene.activeCamera;
|
|
|
+ camera._scene = this.utilityLayerScene;
|
|
|
+ if (camera.leftCamera) {
|
|
|
+ camera.leftCamera._scene = this.utilityLayerScene;
|
|
|
+ }
|
|
|
+ if (camera.rightCamera) {
|
|
|
+ camera.rightCamera._scene = this.utilityLayerScene;
|
|
|
+ }
|
|
|
+ this.utilityLayerScene.render(false);
|
|
|
+ // Reset camera's scene back to original
|
|
|
+ camera._scene = oldScene;
|
|
|
+ if (camera.leftCamera) {
|
|
|
+ camera.leftCamera._scene = oldScene;
|
|
|
+ }
|
|
|
+ if (camera.rightCamera) {
|
|
|
+ camera.rightCamera._scene = oldScene;
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
/**
|
|
|
* Disposes of the renderer
|
|
@@ -90005,6 +90032,178 @@ var BABYLON;
|
|
|
var BABYLON;
|
|
|
(function (BABYLON) {
|
|
|
/**
|
|
|
+ * @hidden
|
|
|
+ */
|
|
|
+ var FaceDirectionInfo = /** @class */ (function () {
|
|
|
+ function FaceDirectionInfo(direction, rotatedDirection, diff, ignore) {
|
|
|
+ if (rotatedDirection === void 0) { rotatedDirection = new BABYLON.Vector3(); }
|
|
|
+ if (diff === void 0) { diff = 0; }
|
|
|
+ if (ignore === void 0) { ignore = false; }
|
|
|
+ this.direction = direction;
|
|
|
+ this.rotatedDirection = rotatedDirection;
|
|
|
+ this.diff = diff;
|
|
|
+ this.ignore = ignore;
|
|
|
+ }
|
|
|
+ return FaceDirectionInfo;
|
|
|
+ }());
|
|
|
+ /**
|
|
|
+ * A behavior that when attached to a mesh will will place a specified node on the meshes face pointing towards the camera
|
|
|
+ */
|
|
|
+ var AttachToBoxBehavior = /** @class */ (function () {
|
|
|
+ /**
|
|
|
+ * Creates the AttachToBoxBehavior, used to attach UI to the closest face of the box to a camera
|
|
|
+ * @param ui The transform node that should be attched to the mesh
|
|
|
+ */
|
|
|
+ function AttachToBoxBehavior(ui) {
|
|
|
+ this.ui = ui;
|
|
|
+ /**
|
|
|
+ * The name of the behavior
|
|
|
+ */
|
|
|
+ this.name = "AttachToBoxBehavior";
|
|
|
+ /**
|
|
|
+ * The distance away from the face of the mesh that the UI should be attached to (default: 0.15)
|
|
|
+ */
|
|
|
+ this.distanceAwayFromFace = 0.15;
|
|
|
+ /**
|
|
|
+ * The distance from the bottom of the face that the UI should be attached to (default: 0.15)
|
|
|
+ */
|
|
|
+ this.distanceAwayFromBottomOfFace = 0.15;
|
|
|
+ this._faceVectors = [new FaceDirectionInfo(BABYLON.Vector3.Up()), new FaceDirectionInfo(BABYLON.Vector3.Down()), new FaceDirectionInfo(BABYLON.Vector3.Left()), new FaceDirectionInfo(BABYLON.Vector3.Right()), new FaceDirectionInfo(BABYLON.Vector3.Forward()), new FaceDirectionInfo(BABYLON.Vector3.Forward().scaleInPlace(-1))];
|
|
|
+ this._tmpMatrix = new BABYLON.Matrix();
|
|
|
+ this._tmpVector = new BABYLON.Vector3();
|
|
|
+ this._zeroVector = BABYLON.Vector3.Zero();
|
|
|
+ this._lookAtTmpMatrix = new BABYLON.Matrix();
|
|
|
+ /* Does nothing */
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Initializes the behavior
|
|
|
+ */
|
|
|
+ AttachToBoxBehavior.prototype.init = function () {
|
|
|
+ /* Does nothing */
|
|
|
+ };
|
|
|
+ AttachToBoxBehavior.prototype._closestFace = function (targetDirection) {
|
|
|
+ var _this = this;
|
|
|
+ // Go over each face and calculate the angle between the face's normal and targetDirection
|
|
|
+ this._faceVectors.forEach(function (v) {
|
|
|
+ if (!_this._target.rotationQuaternion) {
|
|
|
+ _this._target.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(_this._target.rotation.y, _this._target.rotation.x, _this._target.rotation.z);
|
|
|
+ }
|
|
|
+ _this._target.rotationQuaternion.toRotationMatrix(_this._tmpMatrix);
|
|
|
+ BABYLON.Vector3.TransformCoordinatesToRef(v.direction, _this._tmpMatrix, v.rotatedDirection);
|
|
|
+ v.diff = BABYLON.Vector3.GetAngleBetweenVectors(v.rotatedDirection, targetDirection, BABYLON.Vector3.Cross(v.rotatedDirection, targetDirection));
|
|
|
+ });
|
|
|
+ // Return the face information of the one with the normal closeset to target direction
|
|
|
+ return this._faceVectors.reduce(function (min, p) {
|
|
|
+ if (min.ignore) {
|
|
|
+ return p;
|
|
|
+ }
|
|
|
+ else if (p.ignore) {
|
|
|
+ return min;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return min.diff < p.diff ? min : p;
|
|
|
+ }
|
|
|
+ }, this._faceVectors[0]);
|
|
|
+ };
|
|
|
+ AttachToBoxBehavior.prototype._lookAtToRef = function (pos, up, ref) {
|
|
|
+ if (up === void 0) { up = new BABYLON.Vector3(0, 1, 0); }
|
|
|
+ BABYLON.Matrix.LookAtLHToRef(this._zeroVector, pos, up, this._lookAtTmpMatrix);
|
|
|
+ this._lookAtTmpMatrix.invert();
|
|
|
+ BABYLON.Quaternion.FromRotationMatrixToRef(this._lookAtTmpMatrix, ref);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Attaches the AttachToBoxBehavior to the passed in mesh
|
|
|
+ * @param target The mesh that the specified node will be attached to
|
|
|
+ */
|
|
|
+ AttachToBoxBehavior.prototype.attach = function (target) {
|
|
|
+ var _this = this;
|
|
|
+ this._target = target;
|
|
|
+ this._scene = this._target.getScene();
|
|
|
+ // Every frame, update the app bars position
|
|
|
+ this._onRenderObserver = this._scene.onBeforeRenderObservable.add(function () {
|
|
|
+ if (!_this._scene.activeCamera) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Find the face closest to the cameras position
|
|
|
+ var cameraPos = _this._scene.activeCamera.position;
|
|
|
+ if (_this._scene.activeCamera.devicePosition) {
|
|
|
+ cameraPos = _this._scene.activeCamera.devicePosition;
|
|
|
+ }
|
|
|
+ var facing = _this._closestFace(cameraPos.subtract(target.position));
|
|
|
+ if (_this._scene.activeCamera.leftCamera) {
|
|
|
+ _this._scene.activeCamera.leftCamera.computeWorldMatrix().getRotationMatrixToRef(_this._tmpMatrix);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ _this._scene.activeCamera.computeWorldMatrix().getRotationMatrixToRef(_this._tmpMatrix);
|
|
|
+ }
|
|
|
+ // Get camera up direction
|
|
|
+ BABYLON.Vector3.TransformCoordinatesToRef(BABYLON.Vector3.Up(), _this._tmpMatrix, _this._tmpVector);
|
|
|
+ // Ignore faces to not select a parrelel face for the up vector of the UI
|
|
|
+ _this._faceVectors.forEach(function (v) {
|
|
|
+ if (facing.direction.x && v.direction.x) {
|
|
|
+ v.ignore = true;
|
|
|
+ }
|
|
|
+ if (facing.direction.y && v.direction.y) {
|
|
|
+ v.ignore = true;
|
|
|
+ }
|
|
|
+ if (facing.direction.z && v.direction.z) {
|
|
|
+ v.ignore = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ var facingUp = _this._closestFace(_this._tmpVector);
|
|
|
+ // Unignore faces
|
|
|
+ _this._faceVectors.forEach(function (v) {
|
|
|
+ v.ignore = false;
|
|
|
+ });
|
|
|
+ // Position the app bar on that face
|
|
|
+ _this.ui.position.copyFrom(target.position);
|
|
|
+ if (facing.direction.x) {
|
|
|
+ facing.rotatedDirection.scaleToRef((target.scaling.x / 2) + _this.distanceAwayFromFace, _this._tmpVector);
|
|
|
+ _this.ui.position.addInPlace(_this._tmpVector);
|
|
|
+ }
|
|
|
+ if (facing.direction.y) {
|
|
|
+ facing.rotatedDirection.scaleToRef((target.scaling.y / 2) + _this.distanceAwayFromFace, _this._tmpVector);
|
|
|
+ _this.ui.position.addInPlace(_this._tmpVector);
|
|
|
+ }
|
|
|
+ if (facing.direction.z) {
|
|
|
+ facing.rotatedDirection.scaleToRef((target.scaling.z / 2) + _this.distanceAwayFromFace, _this._tmpVector);
|
|
|
+ _this.ui.position.addInPlace(_this._tmpVector);
|
|
|
+ }
|
|
|
+ // Rotate to be oriented properly to the camera
|
|
|
+ if (!_this.ui.rotationQuaternion) {
|
|
|
+ _this.ui.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(_this.ui.rotation.y, _this.ui.rotation.x, _this.ui.rotation.z);
|
|
|
+ }
|
|
|
+ facing.rotatedDirection.scaleToRef(-1, _this._tmpVector);
|
|
|
+ _this._lookAtToRef(_this._tmpVector, facingUp.rotatedDirection, _this.ui.rotationQuaternion);
|
|
|
+ // Place ui the correct distance from the bottom of the mesh
|
|
|
+ if (facingUp.direction.x) {
|
|
|
+ _this.ui.up.scaleToRef(_this.distanceAwayFromBottomOfFace - target.scaling.x / 2, _this._tmpVector);
|
|
|
+ }
|
|
|
+ if (facingUp.direction.y) {
|
|
|
+ _this.ui.up.scaleToRef(_this.distanceAwayFromBottomOfFace - target.scaling.y / 2, _this._tmpVector);
|
|
|
+ }
|
|
|
+ if (facingUp.direction.z) {
|
|
|
+ _this.ui.up.scaleToRef(_this.distanceAwayFromBottomOfFace - target.scaling.z / 2, _this._tmpVector);
|
|
|
+ }
|
|
|
+ _this.ui.position.addInPlace(_this._tmpVector);
|
|
|
+ });
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Detaches the behavior from the mesh
|
|
|
+ */
|
|
|
+ AttachToBoxBehavior.prototype.detach = function () {
|
|
|
+ this._scene.onBeforeRenderObservable.remove(this._onRenderObserver);
|
|
|
+ };
|
|
|
+ return AttachToBoxBehavior;
|
|
|
+ }());
|
|
|
+ BABYLON.AttachToBoxBehavior = AttachToBoxBehavior;
|
|
|
+})(BABYLON || (BABYLON = {}));
|
|
|
+
|
|
|
+//# sourceMappingURL=babylon.attachToBoxBehavior.js.map
|
|
|
+
|
|
|
+var BABYLON;
|
|
|
+(function (BABYLON) {
|
|
|
+ /**
|
|
|
* Renders gizmos on top of an existing scene which provide controls for position, rotation, etc.
|
|
|
*/
|
|
|
var Gizmo = /** @class */ (function () {
|