Browse Source

Oh those buttons be responding fine

rickfromwork 4 years ago
parent
commit
0fb272cea6
2 changed files with 89 additions and 44 deletions
  1. 79 42
      gui/src/3D/controls/touchButton3D.ts
  2. 10 2
      gui/src/3D/controls/touchMeshButton3D.ts

+ 79 - 42
gui/src/3D/controls/touchButton3D.ts

@@ -29,7 +29,7 @@ export enum ButtonState {
  */
 export class TouchButton3D extends Button3D {
     /** @hidden */
-    private _buttonState: ButtonState;
+    //private _buttonState: ButtonState;
     private _collisionMesh: Mesh;
     private _collidableFrontDirection: Vector3;
     private _lastTouchPoint: Vector3;
@@ -42,6 +42,9 @@ export class TouchButton3D extends Button3D {
 
     private _drawDebugData = false;
 
+    private _activeInteractions = new Map<number, ButtonState>();
+    private _previousHeight = new Map<number, number>();
+
     /**
      * Creates a new button
      * @param collisionMesh mesh to track collisions with
@@ -50,7 +53,7 @@ export class TouchButton3D extends Button3D {
     constructor(name?: string, collisionMesh?: Mesh) {
         super(name);
 
-        this._buttonState = ButtonState.None;
+       // this._buttonState = ButtonState.None;
 
         if (collisionMesh) {
             this.collisionMesh = collisionMesh;
@@ -100,8 +103,9 @@ export class TouchButton3D extends Button3D {
     private _isPrimedForInteraction(collidable: Vector3): boolean {
         // Check if the collidable has an appropriate planar height
         const heightFromCenter = this._getHeightFromButtonCenter(collidable);
+        const heightPadding = (this._offsetToFront - this._offsetToBack) / 2;
 
-        if (heightFromCenter > this._hoverOffset || heightFromCenter < this._offsetToBack) {
+        if (heightFromCenter > (this._hoverOffset + heightPadding) || heightFromCenter < (this._offsetToBack - heightPadding)) {
             return false;
         }
 
@@ -207,10 +211,11 @@ export class TouchButton3D extends Button3D {
         // For the hover/hitTest, compute point-plane distance, using button front for plane
         //    -> Right now only have front direction. Can't rely on mesh for getting front face
         //       since mesh might not be aligned properly... Make that a requirement?
-                
+
+
         const func_new = function () {
             if (_this._collidableInitialized) {
-                const indexTipMeshes = scene.getMeshesByTags("indexTip");
+                const indexTipMeshes = scene.getMeshesByTags("touchEnabled");
 
                 var debugLineMesh: LinesMesh;
 
@@ -218,9 +223,64 @@ export class TouchButton3D extends Button3D {
                     const collidablePosition = indexMesh.getAbsolutePosition();
                     const inRange = _this._isPrimedForInteraction(collidablePosition);
 
+                    const uniqueId = indexMesh.uniqueId;
+
                     var debugButtonPoint = _this._collisionMesh.getAbsolutePosition();
                     var debugColour = Color3.Red();
 
+                    const updateButtonState = function (id: number, newState: ButtonState, pointOnButton: Vector3) {
+                        const buttonStateForId = _this._activeInteractions.get(id) || ButtonState.None;
+
+                        // Take into account all inputs interacting with the button to avoid state flickering
+                        let previousPushDepth = 0;
+                        _this._activeInteractions.forEach(function(value, key) {
+                            previousPushDepth = Math.max(previousPushDepth, value);
+                        });
+
+                        if (buttonStateForId != newState) {
+                            if (newState == ButtonState.None) {
+                                _this._activeInteractions.delete(id);
+                            }
+                            else {
+                                _this._activeInteractions.set(id, newState);
+                            }
+                        }
+
+                        let newPushDepth = 0;
+                        _this._activeInteractions.forEach(function(value, key) {
+                            newPushDepth = Math.max(newPushDepth, value);
+                        });
+
+                        if (newPushDepth == ButtonState.Press) {
+                            if (previousPushDepth == ButtonState.Hover) {
+                                _this._onPointerDown(_this, pointOnButton, dummyPointerId, buttonIndex);
+                            }
+                            else if (previousPushDepth == ButtonState.Press) {
+                                _this._onPointerMove(_this, pointOnButton);
+                            }
+                        }
+                        else if (newPushDepth == ButtonState.Hover) {
+                            if (previousPushDepth == ButtonState.None) {
+                                _this._onPointerEnter(_this);
+                            }
+                            else if (previousPushDepth == ButtonState.Press) {
+                                _this._onPointerUp(_this, pointOnButton, dummyPointerId, buttonIndex, false);
+                            }
+                            else {
+                                _this._onPointerMove(_this, pointOnButton);
+                            }
+                        }
+                        else if (newPushDepth == ButtonState.None) {
+                            if (previousPushDepth == ButtonState.Hover) {
+                                _this._onPointerOut(_this);
+                            }
+                            else if (previousPushDepth == ButtonState.Press) {
+                                _this._onPointerUp(_this, pointOnButton, dummyPointerId, buttonIndex, false);
+                                _this._onPointerOut(_this);
+                            }
+                        }
+                    }
+
                     if (inRange) {
                         const pointOnButton = _this._getPointOnButton(collidablePosition);
                         const heightFromCenter = _this._getHeightFromButtonCenter(collidablePosition);
@@ -229,77 +289,54 @@ export class TouchButton3D extends Button3D {
                         debugButtonPoint = pointOnButton;
 
                         const isGreater = function (height: number, compareHeight: number) {
-                            const flickerDelta = 0.01;
+                            const flickerDelta = 0.003;
                             return height >= (compareHeight + flickerDelta);
                         };
 
                         const isLower = function (height: number, compareHeight: number) {
-                            const flickerDelta = 0.01;
+                            const flickerDelta = 0.003;
                             return height <= (compareHeight - flickerDelta);
                         };
 
                         // Update button state and fire events
-                        switch(_this._buttonState) {
+                        switch(_this._activeInteractions.get(uniqueId) || ButtonState.None) {
                             case ButtonState.None:
-                                if (isGreater(heightFromCenter, _this._offsetToBack) &&
+                                if (isGreater(heightFromCenter, _this._offsetToFront) &&
                                     isLower(heightFromCenter, _this._hoverOffset)) {
-                                    console.log("Now hovering");
-                                    _this._buttonState = ButtonState.Hover;
-                                    _this._onPointerEnter(_this);
+                                    updateButtonState(uniqueId, ButtonState.Hover, pointOnButton);
                                 }
 
                                 break;
                             case ButtonState.Hover:
                                 debugColour = Color3.Yellow();
                                 if (isGreater(heightFromCenter, _this._hoverOffset)) {
-                                    console.log("Out of range");
-                                    _this._buttonState = ButtonState.None;
-                                    _this._onPointerOut(_this);
+                                    updateButtonState(uniqueId, ButtonState.None, pointOnButton);
                                 }
                                 else if (isLower(heightFromCenter, _this._offsetToFront)) {
-                                    console.log("now pressing");
-                                    _this._buttonState = ButtonState.Press;
-                                    _this._onPointerDown(_this, pointOnButton, dummyPointerId, buttonIndex);
-                                }
-                                else {
-                                    _this._onPointerMove(_this, pointOnButton);
+                                    updateButtonState(uniqueId, ButtonState.Press, pointOnButton);
                                 }
 
                                 break;
                             case ButtonState.Press:
                                 debugColour = Color3.Green();
                                 if (isGreater(heightFromCenter, _this._offsetToFront)) {
-                                    console.log("no longer pressing");
-                                    _this._buttonState = ButtonState.Hover;
-                                    _this._onPointerUp(_this, pointOnButton, dummyPointerId, buttonIndex, false);
+                                    updateButtonState(uniqueId, ButtonState.Hover, pointOnButton);
                                 }
                                 else if (isLower(heightFromCenter, _this._offsetToBack)) {
-                                    console.log("Exiting out the back");
-                                    _this._buttonState = ButtonState.None;
-                                    _this._onPointerUp(_this, pointOnButton, dummyPointerId, buttonIndex, false);
-                                    _this._onPointerOut(_this);
-                                }
-                                else {
-                                    _this._onPointerMove(_this, pointOnButton);
+                                    updateButtonState(uniqueId, ButtonState.None, pointOnButton);
                                 }
 
                                 break;
                         }
+
+                        _this._previousHeight.set(uniqueId, heightFromCenter);
                     }
                     else {
-                        // Safely return to ButtonState.None
-                        switch(_this._buttonState) {
-                            case ButtonState.Hover:
-                                _this._buttonState = ButtonState.None;
-                                _this._onPointerOut(_this);
-                                break;
-                            case ButtonState.Press:
-                                _this._buttonState = ButtonState.Hover;
-                                _this._onPointerUp(_this, _this._lastTouchPoint, dummyPointerId, buttonIndex, false);
-                                break;
-                        }
+                        updateButtonState(uniqueId, ButtonState.None, _this._lastTouchPoint);
+                        _this._previousHeight.delete(uniqueId);
                     }
 
+
                     
                     if (_this._drawDebugData) {
                         // Debug line mesh

+ 10 - 2
gui/src/3D/controls/touchMeshButton3D.ts

@@ -18,8 +18,16 @@ export class TouchMeshButton3D extends TouchButton3D {
      * @param collisionMesh mesh to track collisions with
      * @param name defines the control name
      */
-    constructor(mesh: Mesh, collisionMesh: Mesh, name?: string) {
-        super(name, collisionMesh);
+    constructor(mesh: Mesh, options: {collisionMesh: Mesh, useDynamicMesh?: boolean}, name?: string) {
+        if (options.useDynamicMesh) {
+            super(name, options.collisionMesh);
+        }
+        else {
+            var newCollisionMesh = options.collisionMesh.clone();
+            newCollisionMesh.isVisible = false;
+            super(name, newCollisionMesh);
+        }
+
         this._currentMesh = mesh;
 
         /**