Pārlūkot izejas kodu

update enter/exit xr buttons, expose environmentPointHittest on xr exprience helper

Trevor Baron 6 gadi atpakaļ
vecāks
revīzija
8326089a0a

+ 52 - 4
src/Cameras/XR/babylon.webXREnterExitUI.ts

@@ -1,5 +1,28 @@
 module BABYLON {
     /**
+     * Button which can be used to enter a different mode of XR
+     */
+    export class WebXREnterExitUIButton {
+        /**
+         * Creates a WebXREnterExitUIButton
+         * @param element button element
+         * @param initializationOptions XR initialization options for the button
+         */
+        constructor(
+            /** button element */
+            public element: HTMLElement,
+            /** XR initialization options for the button */
+            public initializationOptions: XRSessionCreationOptions
+        ) {}
+        /**
+         * Overwritable function which can be used to update the button's visuals when the state changes
+         * @param activeButton the current active button in the UI
+         */
+        update(activeButton: Nullable<WebXREnterExitUIButton>) {
+        }
+    }
+
+    /**
      * Options to create the webXR UI
      */
     export class WebXREnterExitUIOptions {
@@ -11,14 +34,15 @@ module BABYLON {
         /**
          * User provided buttons to enable/disable WebXR. The system will provide default if not set
          */
-        customButtons?: Array<{ element: HTMLElement, initializationOptions: XRSessionCreationOptions }>;
+        customButtons?: Array<WebXREnterExitUIButton>;
     }
     /**
      * UI to allow the user to enter/exit XR mode
      */
     export class WebXREnterExitUI implements IDisposable {
         private _overlay: HTMLDivElement;
-        private _buttons: Array<{ element: HTMLElement, initializationOptions: XRSessionCreationOptions }> = [];
+        private _buttons: Array<WebXREnterExitUIButton> = [];
+        private _activeButton: Nullable<WebXREnterExitUIButton> = null;
         /**
          * Creates UI to allow the user to enter/exit XR mode
          * @param scene the scene to add the ui to
@@ -31,15 +55,22 @@ module BABYLON {
             var supportedPromises = ui._buttons.map((btn) => {
                 return helper.supportsSession(btn.initializationOptions);
             });
+            helper.onStateChangedObservable.add((state) => {
+                if (state == WebXRState.NOT_IN_XR) {
+                    ui._updateButtons(null);
+                }
+            });
             return Promise.all(supportedPromises).then((results) => {
                 results.forEach((supported, i) => {
                     if (supported) {
                         ui._overlay.appendChild(ui._buttons[i].element);
                         ui._buttons[i].element.onclick = async() => {
                             if (helper.state == BABYLON.WebXRState.IN_XR) {
+                                ui._updateButtons(null);
                                 await helper.exitXR();
                                 return;
                             } else if (helper.state == BABYLON.WebXRState.NOT_IN_XR) {
+                                ui._updateButtons(ui._buttons[i]);
                                 await helper.enterXR(ui._buttons[i].initializationOptions, "eye-level");
                             }
                         };
@@ -58,12 +89,21 @@ module BABYLON {
                 var hmdBtn = document.createElement("button");
                 hmdBtn.style.cssText = "color: #868686; border-color: #868686; border-style: solid; margin-left: 10px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-repeat:no-repeat; background-position: center; outline: none;";
                 hmdBtn.innerText = "HMD";
-                this._buttons.push({element: hmdBtn, initializationOptions: {immersive: true, outputContext: options.outputCanvasContext}});
+                this._buttons.push(new WebXREnterExitUIButton(hmdBtn, {immersive: true, outputContext: options.outputCanvasContext}));
+                this._buttons[this._buttons.length - 1].update = function(activeButton: WebXREnterExitUIButton) {
+                    this.element.style.display = (activeButton === null || activeButton === this) ? "" : "none";
+                    this.element.innerText = activeButton === this ? "EXIT" : "HMD";
+                };
 
                 var windowBtn = document.createElement("button");
                 windowBtn.style.cssText = hmdBtn.style.cssText;
                 windowBtn.innerText = "Window";
-                this._buttons.push({ element: windowBtn, initializationOptions: { immersive: false, environmentIntegration: true, outputContext: options.outputCanvasContext } });
+                this._buttons.push(new WebXREnterExitUIButton(windowBtn, { immersive: false, environmentIntegration: true, outputContext: options.outputCanvasContext }));
+                this._buttons[this._buttons.length - 1].update = function(activeButton: WebXREnterExitUIButton) {
+                    this.element.style.display = (activeButton === null || activeButton === this) ? "" : "none";
+                    this.element.innerText = activeButton === this ? "EXIT" : "Window";
+                };
+                this._updateButtons(null);
             }
 
             var renderCanvas = scene.getEngine().getRenderingCanvas();
@@ -74,6 +114,14 @@ module BABYLON {
                 });
             }
         }
+
+        private _updateButtons(activeButton: Nullable<WebXREnterExitUIButton>) {
+            this._activeButton = activeButton;
+            this._buttons.forEach((b) => {
+                b.update(this._activeButton);
+            });
+        }
+
         /**
          * Disposes of the object
          */

+ 9 - 0
src/Cameras/XR/babylon.webXRExperienceHelper.ts

@@ -131,6 +131,15 @@ module BABYLON {
         }
 
         /**
+         * Fires a ray and returns the closest hit in the xr sessions enviornment, useful to place objects in AR
+         * @param ray ray to cast into the environment
+         * @returns Promise which resolves with a collision point in the environment if it exists
+         */
+        public environmentPointHitTest(ray: BABYLON.Ray): Promise<Nullable<Vector3>> {
+            return this._sessionManager.environmentPointHitTest(ray);
+        }
+
+        /**
          * Checks if the creation options are supported by the xr session
          * @param options creation options
          * @returns true if supported