소스 검색

Enable event-based user interaction

Raanan Weber 5 년 전
부모
커밋
50ad737f55
2개의 변경된 파일88개의 추가작업 그리고 34개의 파일을 삭제
  1. 13 0
      src/LibDeclarations/webxr.d.ts
  2. 75 34
      src/XR/features/WebXRControllerPointerSelection.ts

+ 13 - 0
src/LibDeclarations/webxr.d.ts

@@ -35,6 +35,19 @@ type XREye =
     | "left"
     | "right";
 
+type XREventType =
+    | "devicechange"
+    | "visibilitychange"
+    | "end"
+    | "inputsourceschange"
+    | "select"
+    | "selectstart"
+    | "selectend"
+    | "squeeze"
+    | "squeezestart"
+    | "squeezeend"
+    | "reset";
+
 interface XRSpace extends EventTarget {
 
 }

+ 75 - 34
src/XR/features/WebXRControllerPointerSelection.ts

@@ -113,6 +113,16 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
             pick: Nullable<PickingInfo>;
             id: number;
             tmpRay: Ray;
+            // event support
+            eventListeners?: {[event in XREventType]?: ((event: XRInputSourceEvent) => void)};
+            //  {
+            //     selectstart: (event: XRInputSourceEvent) => void;
+            //     selectend: (event: XRInputSourceEvent) => void;
+            //     select?: (event: XRInputSourceEvent) => void;
+            //     squeeze?: (event: XRInputSourceEvent) => void;
+            //     squeezestart?: (event: XRInputSourceEvent) => void;
+            //     squeezeend?: (event: XRInputSourceEvent) => void;
+            // }
         };
     } = {};
     private _scene: Scene;
@@ -196,6 +206,8 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
             this._detachController(controller.uniqueId);
         });
 
+        this._scene.constantlyUpdateMeshUnderPointer = true;
+
         return true;
     }
 
@@ -380,50 +392,71 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
     }
 
     private _attachTrackedPointerRayMode(xrController: WebXRInputSource) {
-        xrController.onMotionControllerInitObservable.add((motionController) => {
-            if (this._options.forceGazeMode) {
-                return this._attachGazeMode(xrController);
-            }
-
-            const controllerData = this._controllers[xrController.uniqueId];
+        const controllerData = this._controllers[xrController.uniqueId];
+        if (this._options.forceGazeMode) {
+            return this._attachGazeMode(xrController);
+        }
+        controllerData.onFrameObserver = this._xrSessionManager.onXRFrameObservable.add(() => {
+            controllerData.laserPointer.isVisible = this.displayLaserPointer;
+            (<StandardMaterial>controllerData.laserPointer.material).disableLighting = this.disablePointerLighting;
+            (<StandardMaterial>controllerData.selectionMesh.material).disableLighting = this.disableSelectionMeshLighting;
 
-            if (this._options.overrideButtonId) {
-                controllerData.selectionComponent = motionController.getComponent(this._options.overrideButtonId);
-            }
-            if (!controllerData.selectionComponent) {
-                controllerData.selectionComponent = motionController.getMainComponent();
+            if (controllerData.pick) {
+                this._scene.simulatePointerMove(controllerData.pick, { pointerId: controllerData.id });
             }
+        });
+        if (xrController.inputSource.gamepad) {
+            xrController.onMotionControllerInitObservable.add((motionController) => {
+                if (this._options.overrideButtonId) {
+                    controllerData.selectionComponent = motionController.getComponent(this._options.overrideButtonId);
+                }
+                if (!controllerData.selectionComponent) {
+                    controllerData.selectionComponent = motionController.getMainComponent();
+                }
 
-            controllerData.onFrameObserver = this._xrSessionManager.onXRFrameObservable.add(() => {
-                if (controllerData.selectionComponent && controllerData.selectionComponent.pressed) {
+                controllerData.onButtonChangedObserver = controllerData.selectionComponent.onButtonStateChangedObservable.add((component) => {
+                    if (component.changes.pressed) {
+                        const pressed = component.changes.pressed.current;
+                        if (controllerData.pick) {
+                            if (pressed) {
+                                this._scene.simulatePointerDown(controllerData.pick, { pointerId: controllerData.id });
+                                (<StandardMaterial>controllerData.selectionMesh.material).emissiveColor = this.selectionMeshPickedColor;
+                                (<StandardMaterial>controllerData.laserPointer.material).emissiveColor = this.laserPointerPickedColor;
+                            } else {
+                                this._scene.simulatePointerUp(controllerData.pick, { pointerId: controllerData.id });
+                                (<StandardMaterial>controllerData.selectionMesh.material).emissiveColor = this.selectionMeshDefaultColor;
+                        (<StandardMaterial>controllerData.laserPointer.material).emissiveColor = this.lasterPointerDefaultColor;
+                            }
+                        }
+                    }
+                });
+            });
+        } else {
+            // use the select and squeeze events
+            const selectStartListener = (event: XRInputSourceEvent) => {
+                if (event.inputSource === controllerData.xrController.inputSource && controllerData.pick) {
+                    this._scene.simulatePointerDown(controllerData.pick, { pointerId: controllerData.id });
                     (<StandardMaterial>controllerData.selectionMesh.material).emissiveColor = this.selectionMeshPickedColor;
                     (<StandardMaterial>controllerData.laserPointer.material).emissiveColor = this.laserPointerPickedColor;
-                } else {
+                }
+            };
+
+            const selectEndListener = (event: XRInputSourceEvent) => {
+                if (event.inputSource === controllerData.xrController.inputSource && controllerData.pick) {
+                    this._scene.simulatePointerUp(controllerData.pick, { pointerId: controllerData.id });
                     (<StandardMaterial>controllerData.selectionMesh.material).emissiveColor = this.selectionMeshDefaultColor;
                     (<StandardMaterial>controllerData.laserPointer.material).emissiveColor = this.lasterPointerDefaultColor;
                 }
-                controllerData.laserPointer.isVisible = this.displayLaserPointer;
-                (<StandardMaterial>controllerData.laserPointer.material).disableLighting = this.disablePointerLighting;
-                (<StandardMaterial>controllerData.selectionMesh.material).disableLighting = this.disableSelectionMeshLighting;
+            };
 
-                if (controllerData.pick) {
-                    this._scene.simulatePointerMove(controllerData.pick, { pointerId: controllerData.id });
-                }
-            });
+            controllerData.eventListeners = {
+                selectend: selectEndListener,
+                selectstart: selectStartListener
+            };
 
-            controllerData.onButtonChangedObserver = controllerData.selectionComponent.onButtonStateChangedObservable.add((component) => {
-                if (component.changes.pressed) {
-                    const pressed = component.changes.pressed.current;
-                    if (controllerData.pick) {
-                        if (pressed) {
-                            this._scene.simulatePointerDown(controllerData.pick, { pointerId: controllerData.id });
-                        } else {
-                            this._scene.simulatePointerUp(controllerData.pick, { pointerId: controllerData.id });
-                        }
-                    }
-                }
-            });
-        });
+            this._xrSessionManager.session.addEventListener('selectstart', selectStartListener);
+            this._xrSessionManager.session.addEventListener('selectend', selectEndListener);
+        }
     }
 
     private _convertNormalToDirectionOfRay(normal: Nullable<Vector3>, ray: Ray) {
@@ -447,6 +480,14 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
         if (controllerData.onFrameObserver) {
             this._xrSessionManager.onXRFrameObservable.remove(controllerData.onFrameObserver);
         }
+        if (controllerData.eventListeners) {
+            Object.keys(controllerData.eventListeners).forEach((eventName: string) => {
+                const func = controllerData.eventListeners && controllerData.eventListeners[eventName as XREventType];
+                if (func) {
+                    this._xrSessionManager.session.removeEventListener(eventName, func);
+                }
+            });
+        }
         controllerData.selectionMesh.dispose();
         controllerData.laserPointer.dispose();
         // remove from the map