Forráskód Böngészése

Merge pull request #4731 from TrevorDev/appBar

App bar
David Catuhe 7 éve
szülő
commit
1b89e3ead2

+ 2 - 1
Tools/Gulp/config.json

@@ -340,7 +340,8 @@
             "files": [
                 "../../src/Behaviors/Mesh/babylon.pointerDragBehavior.js",
                 "../../src/Behaviors/Mesh/babylon.multiPointerScaleBehavior.js",
-                "../../src/Behaviors/Mesh/babylon.sixDofDragBehavior.js"
+                "../../src/Behaviors/Mesh/babylon.sixDofDragBehavior.js",
+                "../../src/Behaviors/Mesh/babylon.attachToBoxBehavior.js"
             ],
             "dependUpon": [
                 "behaviors"

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

@@ -72,6 +72,7 @@
 - Added predicate function `targetMask` argument to `scene.beginWeightedAnimation`, `scene.beginAnimation`, `scene.stopAnimation`, and `animatable.stop` to allow for selective application of animations.  ([fmmoret](http://github.com/fmmoret))
 - Oculus GO and GearVR 3dof controllers will now rotate with the user's head if they turn around in their room ([TrevorDev](https://github.com/TrevorDev))
 - Added onPoseUpdatedFromDeviceObservable to webVRCamera to detect when the camera's pose has been updated ([TrevorDev](https://github.com/TrevorDev))
+- Added attachToBoxBehavior to attach UI to a bounding box ([TrevorDev](https://github.com/TrevorDev))
 - Gizmo manager's internal gizmos are now public ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Loader

+ 166 - 0
src/Behaviors/Mesh/babylon.attachToBoxBehavior.ts

@@ -0,0 +1,166 @@
+module BABYLON {
+    /**
+     * @hidden
+     */
+    class FaceDirectionInfo {
+        constructor(public direction:Vector3, public rotatedDirection = new BABYLON.Vector3(), public diff = 0, public ignore = false){}
+    }
+    
+    /**
+     * A behavior that when attached to a mesh will will place a specified node on the meshes face pointing towards the camera
+     */
+    export class AttachToBoxBehavior implements BABYLON.Behavior<BABYLON.Mesh> {
+        /**
+         *  The name of the behavior
+         */
+        public name = "AttachToBoxBehavior";
+        /**
+         * The distance away from the face of the mesh that the UI should be attached to (default: 0.15)
+         */
+        public distanceAwayFromFace = 0.15;
+        /**
+         * The distance from the bottom of the face that the UI should be attached to (default: 0.15)
+         */
+        public distanceAwayFromBottomOfFace = 0.15;
+        private _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))];
+        private _target:Mesh;
+        private _scene:Scene;
+        private _onRenderObserver:Nullable<Observer<Scene>>;
+        private _tmpMatrix = new Matrix();
+        private _tmpVector = new Vector3();
+
+        /**
+         * 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
+         */
+        constructor(private ui: BABYLON.TransformNode){
+            /* Does nothing */
+        }
+
+        /**
+         *  Initializes the behavior
+         */
+        public init(){
+            /* Does nothing */
+        }
+        
+        private _closestFace(targetDirection:Vector3){
+            // Go over each face and calculate the angle between the face's normal and targetDirection
+            this._faceVectors.forEach((v)=>{
+                if(!this._target.rotationQuaternion){
+                    this._target.rotationQuaternion = 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((min,p)=>{
+                if(min.ignore){
+                    return p;
+                }else if(p.ignore){
+                    return min;
+                }else{
+                    return min.diff < p.diff ? min : p
+                }
+            }, this._faceVectors[0]);
+        }
+        
+        private _zeroVector = Vector3.Zero();
+        private _lookAtTmpMatrix = new Matrix();
+        private _lookAtToRef(pos:Vector3, up = new BABYLON.Vector3(0,1,0), ref:Quaternion){
+            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
+         */
+        attach(target: BABYLON.Mesh){
+            this._target = target;
+            this._scene = this._target.getScene();
+            
+            // Every frame, update the app bars position
+            this._onRenderObserver = this._scene.onBeforeRenderObservable.add(()=>{
+                if(!this._scene.activeCamera){
+                    return;
+                }
+
+                // Find the face closest to the cameras position
+                var cameraPos = this._scene.activeCamera.position;
+                if((<WebVRFreeCamera>this._scene.activeCamera).devicePosition){
+                    cameraPos = (<WebVRFreeCamera>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((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((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 = 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
+         */
+        detach(){
+            this._scene.onBeforeRenderObservable.remove(this._onRenderObserver);
+        }
+    }
+}

+ 1 - 1
src/PostProcess/babylon.postProcess.ts

@@ -468,7 +468,7 @@
             this.onActivateObservable.notifyObservers(camera);
 
             // Clear
-            if (this.autoClear && this.alphaMode === Engine.ALPHA_DISABLE) {
+            if (scene._allowPostProcessClear && this.autoClear && this.alphaMode === Engine.ALPHA_DISABLE) {
                 this._engine.clear(this.clearColor ? this.clearColor : scene.clearColor, true, true, true);
             }
 

+ 25 - 1
src/Rendering/babylon.utilityLayerRenderer.ts

@@ -53,6 +53,7 @@ module BABYLON {
         constructor(/** the original scene that will be rendered on top of */ public originalScene:Scene){
             // 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
@@ -171,7 +172,30 @@ module BABYLON {
          */
         public render(){
             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;
+                }
+            }
+            
         }
 
         /**

+ 2 - 2
src/babylon.node.ts

@@ -96,8 +96,8 @@
 
         /** @hidden */
         public _waitingParentId: Nullable<string>;
-
-        private _scene: Scene;
+        /** @hidden */
+        public _scene: Scene;
         /** @hidden */
         public _cache: any;
 

+ 2 - 1
src/babylon.scene.ts

@@ -4333,7 +4333,8 @@
         public updateAlternateTransformMatrix(alternateCamera: Camera): void {
             this._setAlternateTransformMatrix(alternateCamera.getViewMatrix(), alternateCamera.getProjectionMatrix());
         }
-
+        /** @hidden */
+        public _allowPostProcessClear = true;
         private _renderForCamera(camera: Camera, rigParent?: Camera): void {
             if (camera && camera._skipRendering) {
                 return;