private PointerEventCatcher CreatePointerEventCatcher(BaseNearInteractionTouchable touchable)
        {
            var catcher = PointerEventCatcher.Create(touchable.gameObject);

            catcher.OnPointerDownEvent.AddListener(() =>
            {
                touchable.GetComponent <Renderer>().material = pokeMaterial;
            });
            catcher.OnPointerUpEvent.AddListener(() =>
            {
                touchable.GetComponent <Renderer>().material = idleMaterial;
            });

            return(catcher);
        }
        private TouchEventCatcher CreateTouchEventCatcher(BaseNearInteractionTouchable touchable)
        {
            var catcher = TouchEventCatcher.Create(touchable.gameObject);

            catcher.OnTouchStartedEvent.AddListener(() =>
            {
                touchable.GetComponent <Renderer>().material = pokeMaterial;
            });
            catcher.OnTouchCompletedEvent.AddListener(() =>
            {
                touchable.GetComponent <Renderer>().material = idleMaterial;
            });

            return(catcher);
        }
        private IEnumerator TestTouchableDistances(BaseNearInteractionTouchable touchable, float colliderThickness, GameObject objectDownExpected)
        {
            Handedness handedness = Handedness.Right;

            ArticulatedHandPose.GestureId gesture = ArticulatedHandPose.GestureId.Open;

            yield return(PlayModeTestUtilities.ShowHand(handedness, inputSim));

            PokePointer       pokePointer = null;
            IMixedRealityHand hand        = HandJointUtils.FindHand(handedness);

            Assert.IsNotNull(hand);
            foreach (IMixedRealityPointer pointer in hand.InputSource.Pointers)
            {
                pokePointer = pointer as PokePointer;
                if (pokePointer)
                {
                    break;
                }
            }
            Assert.IsNotNull(pokePointer);
            float touchableDistance = pokePointer.TouchableDistance;

            float debounceThreshold = 0.01f;

            touchable.DebounceThreshold = debounceThreshold;

            Vector3 center = touchable.transform.position;

            float   margin    = 0.001f;
            Vector3 pStart    = center + new Vector3(0, 0, -touchableDistance - 0.5f);
            Vector3 pTouch    = center + new Vector3(0, 0, -touchableDistance + margin);
            Vector3 pPoke     = center + new Vector3(0, 0, -colliderThickness + margin);
            Vector3 pDebounce = center + new Vector3(0, 0, -colliderThickness - touchable.DebounceThreshold - margin);
            Vector3 pEnd      = center + new Vector3(0, 0, touchableDistance + 0.5f);

            // Test return beyond DebounceThreshold
            yield return(PlayModeTestUtilities.MoveHand(pStart, pStart, gesture, handedness, inputSim, 1));

            Assert.IsNull(pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pStart, pTouch, gesture, handedness, inputSim));

            Assert.AreEqual(touchable, pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pTouch, pPoke, gesture, handedness, inputSim));

            Assert.AreEqual(touchable, pokePointer.ClosestProximityTouchable);
            Assert.AreEqual(objectDownExpected, pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pPoke, pDebounce, gesture, handedness, inputSim));

            Assert.AreEqual(touchable, pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pDebounce, pStart, gesture, handedness, inputSim));

            Assert.IsNull(pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            // Test touchable distance behind the surface
            yield return(PlayModeTestUtilities.MoveHand(pStart, pStart, gesture, handedness, inputSim, 1));

            Assert.IsNull(pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pStart, pTouch, gesture, handedness, inputSim));

            Assert.AreEqual(touchable, pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pTouch, pPoke, gesture, handedness, inputSim));

            Assert.AreEqual(touchable, pokePointer.ClosestProximityTouchable);
            Assert.AreEqual(objectDownExpected, pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pPoke, pEnd, gesture, handedness, inputSim));

            Assert.IsNull(pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pEnd, pDebounce, gesture, handedness, inputSim));

            Assert.AreEqual(touchable, pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.MoveHand(pDebounce, pStart, gesture, handedness, inputSim));

            Assert.IsNull(pokePointer.ClosestProximityTouchable);
            Assert.IsNull(pokePointer.CurrentTouchableObjectDown);

            yield return(PlayModeTestUtilities.HideHand(handedness, inputSim));
        }