|
@@ -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
|