Пример #1
0
        public IEnumerator PrefabTouchZoom()
        {
            InstantiateFromPrefab();

            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.Show(Vector3.zero));

            yield return(handRight.MoveTo(panZoom.transform.position, 10));

            TestHand handLeft = new TestHand(Handedness.Left);

            yield return(handLeft.Show(Vector3.zero));

            yield return(handLeft.MoveTo(panZoom.transform.position + Vector3.right * -0.01f, 10));

            yield return(handRight.Move(new Vector3(0.01f, 0f, 0f)));

            yield return(handLeft.Move(new Vector3(-0.01f, 0f, 0f)));

            Assert.AreEqual(0.4, panZoom.CurrentScale, 0.1, "slate did not zoom in using two finger touch");

            yield return(handRight.Hide());

            yield return(handLeft.Hide());
        }
        public IEnumerator TestClickEvents()
        {
            PlayModeTestUtilities.PushHandSimulationProfile();
            PlayModeTestUtilities.SetHandSimulationMode(HandSimulationMode.Gestures);

            // Subscribe to interactable's on click so we know the click went through
            bool wasClicked = false;

            interactable.OnClick.AddListener(() => { wasClicked = true; });

            var testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(Vector3.zero));

            CameraCache.Main.transform.LookAt(interactable.transform);
            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(testHand.Hide());

            Assert.True(wasClicked);

            PlayModeTestUtilities.PopHandSimulationProfile();
        }
        public IEnumerator TestTouchEvents()
        {
            interactable.gameObject.AddComponent <NearInteractionTouchableVolume>();
            var  touchReceiver = interactable.AddReceiver <InteractableOnTouchReceiver>();
            bool didTouch      = false;
            bool didUntouch    = false;

            touchReceiver.OnTouchStart.AddListener(() => didTouch = true);
            touchReceiver.OnTouchEnd.AddListener(() => didUntouch = true);

            var testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(Vector3.forward));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(testHand.MoveTo(interactable.transform.position));

            yield return(testHand.MoveTo(Vector3.forward));

            yield return(testHand.Hide());

            Assert.True(didTouch, "Did not receive touch event");
            Assert.True(didUntouch, "Did not receive touch end event");
        }
Пример #4
0
        public IEnumerator TestClickEvents()
        {
            var iss        = PlayModeTestUtilities.GetInputSimulationService();
            var oldSimMode = iss.ControllerSimulationMode;

            iss.ControllerSimulationMode = ControllerSimulationMode.HandGestures;

            // Subscribe to interactable's on click so we know the click went through
            bool wasClicked = false;

            interactable.OnClick.AddListener(() => { wasClicked = true; });

            var testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(Vector3.zero));

            CameraCache.Main.transform.LookAt(interactable.transform);
            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(testHand.Hide());

            Assert.True(wasClicked);

            iss.ControllerSimulationMode = oldSimMode;
        }
        private IEnumerator DirectPinchAndMoveSlider(PinchSlider slider, float toSliderValue)
        {
            Debug.Log($"moving hand to value {toSliderValue}");
            var     rightHand  = new TestHand(Handedness.Right);
            Vector3 initialPos = new Vector3(0.05f, 0, 1.0f);

            yield return(rightHand.Show(initialPos));

            yield return(rightHand.MoveTo(slider.ThumbRoot.transform.position));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            if (!(toSliderValue >= 0 && toSliderValue <= 1))
            {
                throw new System.ArgumentException("toSliderValue must be between 0 and 1");
            }

            yield return(rightHand.MoveTo(Vector3.Lerp(slider.SliderStartPosition, slider.SliderEndPosition, toSliderValue)));

            // Buffer time for the hand to move to finish moving
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(rightHand.Hide());
        }
        public IEnumerator TestGrabEvents()
        {
            var grabReceiver = interactable.AddReceiver <InteractableOnGrabReceiver>();

            interactable.gameObject.AddComponent <NearInteractionGrabbable>();
            bool didGrab = false;

            grabReceiver.OnGrab.AddListener(() => didGrab = true);
            bool didRelease = false;

            grabReceiver.OnRelease.AddListener(() => didRelease = true);

            var testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(interactable.transform.position));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(testHand.Hide());

            Assert.True(didGrab, "Did not receive grab event");
            Assert.True(didRelease, "Did not receive release event");
            GameObject.Destroy(cube);
            yield return(null);
        }
        /// <summary>
        /// Scroll a slate using GGV and ensure that the slate scrolls
        /// expected amount. Assumes panZoom has already been created.
        /// </summary>
        /// <param name="expectedScroll">The amount panZoom is expected to scroll</param>
        private IEnumerator RunGGVScrollTest(float expectedScroll)
        {
            var iss        = PlayModeTestUtilities.GetInputSimulationService();
            var oldSimMode = iss.ControllerSimulationMode;

            iss.ControllerSimulationMode = ControllerSimulationMode.HandGestures;

            Vector2 totalPanDelta = Vector2.zero;

            panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta);

            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(handRight.Show(Vector3.zero));

            // Move requires a slower action (i.e. higher numSteps) in order to
            // achieve a reliable pan.
            yield return(handRight.Move(new Vector3(0.0f, -0.1f, 0f), 30));

            Assert.AreEqual(expectedScroll, totalPanDelta.y, 0.1, "pan delta is not correct");

            yield return(handRight.Hide());

            iss.ControllerSimulationMode = oldSimMode;
            yield return(null);
        }
Пример #8
0
        public IEnumerator TestAssembleInteractableAndFarManip()
        {
            GameObject  pinchSliderObject;
            PinchSlider slider;

            // This should not throw exception
            AssembleSlider(Vector3.forward, Vector3.zero, out pinchSliderObject, out slider);

            Debug.Assert(slider.SliderValue == 0.5, "Slider should have value 0.5 at start");

            // Set up ggv simulation
            PlayModeTestUtilities.PushHandSimulationProfile();
            PlayModeTestUtilities.SetHandSimulationMode(ControllerSimulationMode.HandGestures);

            var     rightHand  = new TestHand(Handedness.Right);
            Vector3 initialPos = new Vector3(0.05f, 0, 1.0f);

            yield return(rightHand.Show(initialPos));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(rightHand.Move(new Vector3(0.1f, 0, 0)));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(rightHand.Hide());

            Assert.That(slider.SliderValue, Is.GreaterThan(0.5));

            // clean up
            GameObject.Destroy(pinchSliderObject);
            PlayModeTestUtilities.PopHandSimulationProfile();
        }
Пример #9
0
        public IEnumerator Prefab_RayScroll()
        {
            InstantiateFromPrefab(Vector3.forward);
            Vector2 totalPanDelta = Vector2.zero;

            panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta);

            TestHand h           = new TestHand(Handedness.Right);
            Vector3  screenPoint = CameraCache.Main.ViewportToScreenPoint(new Vector3(0.5f, 0.25f, 0.5f));

            yield return(h.Show(CameraCache.Main.ScreenToWorldPoint(screenPoint)));

            Assert.True(PointerUtils.TryGetHandRayEndPoint(Handedness.Right, out Vector3 hitPointStart));

            yield return(h.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(h.Move(new Vector3(0, -0.05f, 0), 10));

            Assert.True(PointerUtils.TryGetHandRayEndPoint(Handedness.Right, out Vector3 hitPointEnd));
            yield return(h.SetGesture(ArticulatedHandPose.GestureId.Open));

            TestUtilities.AssertNotAboutEqual(hitPointStart, hitPointEnd, "ray should not stick on slate scrolling");
            Assert.AreEqual(0.1, totalPanDelta.y, 0.05, "pan delta is not correct");



            yield return(h.Hide());
        }
Пример #10
0
        public IEnumerator PrefabGGVZoom()
        {
            InstantiateFromPrefab();

            PlayModeTestUtilities.SetHandSimulationMode(HandSimulationMode.Gestures);

            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.Show(new Vector3(0.0f, 0.0f, 0.6f)));

            TestHand handLeft = new TestHand(Handedness.Left);

            yield return(handLeft.Show(new Vector3(-0.1f, 0.0f, 0.6f)));

            yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(handRight.Move(new Vector3(0.005f, 0.0f, 0.0f), 10));

            yield return(handLeft.Move(new Vector3(-0.005f, 0.0f, 0.0f), 10));

            Assert.AreEqual(0.5, panZoom.CurrentScale, 0.1, "slate did not zoom in using two ggv hands");

            yield return(handRight.Hide());

            yield return(handLeft.Hide());
        }
        public IEnumerator NearInteractionTouchableVariant()
        {
            var touchable = CreateTouchable <NearInteractionTouchable>(ObjectScale);

            touchable.SetLocalForward(touchNormal);
            touchable.SetBounds(new Vector2(0.5f, 0.5f));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            TestHand testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(initialHandPosition));

            using (var catcher = CreateTouchEventCatcher(touchable))
            {
                yield return(testHand.MoveTo(objectPosition));

                Assert.AreEqual(1, catcher.EventsStarted);
                Assert.AreEqual(0, catcher.EventsCompleted);
                yield return(testHand.MoveTo(rightPosition));

                Assert.AreEqual(1, catcher.EventsStarted);
                Assert.AreEqual(1, catcher.EventsCompleted);

                // Touch started and completed when entering and exiting behind the plane
                yield return(testHand.MoveTo(initialHandPosition));

                yield return(testHand.MoveTo(objectPosition));

                Assert.AreEqual(2, catcher.EventsStarted);
                Assert.AreEqual(1, catcher.EventsCompleted);
                yield return(testHand.MoveTo(backPosition));

                Assert.AreEqual(2, catcher.EventsStarted);
                Assert.AreEqual(2, catcher.EventsCompleted);

                // No touch when moving at behind the plane
                yield return(testHand.MoveTo(rightPosition));

                Assert.AreEqual(2, catcher.EventsStarted);
                Assert.AreEqual(2, catcher.EventsCompleted);

                // No touch when moving outside the bounds
                yield return(testHand.MoveTo(initialHandPosition + outOfBoundsOffset));

                yield return(testHand.MoveTo(objectPosition + outOfBoundsOffset));

                yield return(testHand.MoveTo(rightPosition));

                Assert.AreEqual(2, catcher.EventsStarted);
                Assert.AreEqual(2, catcher.EventsCompleted);
            }

            yield return(testHand.Hide());

            Object.Destroy(touchable.gameObject);
        }
        public IEnumerator TestHandConstraintPalmUpSolverPlacement()
        {
            // Instantiate our test GameObject with solver.
            var testObjects = InstantiateTestSolver <HandConstraintPalmUp>();

            testObjects.handler.TrackedTargetType = TrackedObjectType.HandJoint;
            testObjects.handler.TrackedHandness   = Handedness.Both;

            var handConstraintSolver = (HandConstraintPalmUp)testObjects.solver;

            handConstraintSolver.FollowHandUntilFacingCamera = true;

            // Ensure that FacingCameraTrackingThreshold is greater than FollowHandCameraFacingThresholdAngle
            Assert.AreEqual(handConstraintSolver.FacingCameraTrackingThreshold - handConstraintSolver.FollowHandCameraFacingThresholdAngle > 0, true);

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            TestUtilities.AssertAboutEqual(testObjects.target.transform.position, Vector3.zero, "HandConstraintPalmUp solver did not start at the origin");

            var cameraTransform = CameraCache.Main.transform;

            // Place hand 1 meter in front of user, 50 cm below eye level
            var handTestPos = cameraTransform.position + cameraTransform.forward - (Vector3.up * 0.5f);

            var cameraLookVector = (handTestPos - cameraTransform.position).normalized;

            // Generate hand rotation with hand palm facing camera
            var handRoation = Quaternion.LookRotation(cameraTransform.up, cameraLookVector);

            // Add a right hand.
            var rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(handTestPos));

            yield return(rightHand.SetRotation(handRoation));

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            // Ensure Rotation and offset behavior are following camera
            Assert.AreEqual(handConstraintSolver.RotationBehavior, HandConstraint.SolverRotationBehavior.LookAtMainCamera);
            Assert.AreEqual(handConstraintSolver.OffsetBehavior, HandConstraint.SolverOffsetBehavior.LookAtCameraRotation);

            // Rotate hand so palm is no longer within the FollowHandCameraFacingThresholdAngle
            var newHandRot = handRoation * Quaternion.Euler(-(handConstraintSolver.FollowHandCameraFacingThresholdAngle + 1), 0f, 0f);

            yield return(rightHand.SetRotation(newHandRot));

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            // Ensure Rotation and offset behavior are following camera
            Assert.AreEqual(handConstraintSolver.RotationBehavior, HandConstraint.SolverRotationBehavior.LookAtTrackedObject);
            Assert.AreEqual(handConstraintSolver.OffsetBehavior, HandConstraint.SolverOffsetBehavior.TrackedObjectRotation);

            yield return(rightHand.Hide());

            yield return(new WaitForSeconds(SolverUpdateWaitTime));
        }
        public IEnumerator TestAssembleTouchSnapSlider()
        {
            GameObject  pinchSliderObject;
            PinchSlider slider;

            // This should not throw exception
            AssembleSlider(Vector3.forward, Vector3.zero, out pinchSliderObject, out slider);

            // Set the slider to use step divisions
            slider.UseSliderStepDivisions = true;
            slider.SliderStepDivisions    = 4;

            // Set slider to snap with touch
            slider.SnapToPosition = true;
            slider.IsTouchable    = true;

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            bool interactionStarted = false;

            slider.OnInteractionStarted.AddListener((x) => interactionStarted = true);
            bool interactionUpdated = false;

            slider.OnValueUpdated.AddListener((x) => interactionUpdated = true);

            var     rightHand  = new TestHand(Handedness.Right);
            Vector3 initialPos = new Vector3(0.3f, 0, 0.0f);

            yield return(rightHand.Show(initialPos));

            yield return(rightHand.Move(new Vector3(0, 0, 1.0f)));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.IsTrue(interactionStarted, "Slider did not raise interaction started.");
            Assert.IsTrue(interactionUpdated, "Slider did not raise SliderUpdated event.");

            Assert.AreEqual(0.75f, slider.SliderValue);

            yield return(rightHand.Move(new Vector3(-0.6f, 0, 0)));

            Assert.AreEqual(0.25f, slider.SliderValue);

            yield return(rightHand.Move(new Vector3(0.3f, 0, 0)));

            Assert.AreEqual(0.5f, slider.SliderValue);

            bool interactionEnded = false;

            slider.OnInteractionEnded.AddListener((x) => interactionEnded = true);

            yield return(rightHand.Hide());

            Assert.IsTrue(interactionEnded, "Slider did not raise interaction ended.");

            GameObject.Destroy(pinchSliderObject);
        }
Пример #14
0
        public IEnumerator ManipulationHandlerThrow()
        {
            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            Vector3 initialObjectPosition = new Vector3(0f, 0f, 1f);

            testObject.transform.position = initialObjectPosition;

            var rigidBody = testObject.AddComponent <Rigidbody>();

            rigidBody.useGravity = false;

            var manipHandler = testObject.AddComponent <ManipulationHandler>();

            manipHandler.HostTransform   = testObject.transform;
            manipHandler.SmoothingActive = false;

            // add near interaction grabbable to be able to grab the cube with the simulated articulated hand
            testObject.AddComponent <NearInteractionGrabbable>();

            yield return(new WaitForFixedUpdate());

            yield return(null);

            TestHand hand = new TestHand(Handedness.Right);

            // grab the cube - move it to the right
            var inputSimulationService = PlayModeTestUtilities.GetInputSimulationService();

            Vector3 handOffset          = new Vector3(0, 0, 0.1f);
            Vector3 initialHandPosition = new Vector3(0, 0, 0.5f);
            Vector3 rightPosition       = new Vector3(1f, 0f, 1f);

            yield return(hand.Show(initialHandPosition));

            yield return(hand.MoveTo(initialObjectPosition));

            yield return(hand.GrabAndThrowAt(rightPosition));

            // With simulated hand angular velocity would not be equal to 0, because of how simulation
            // moves hand when releasing the Pitch. Even though it doesn't directly follow from hand movement, there will always be some rotation.
            Assert.NotZero(rigidBody.angularVelocity.magnitude, "Manipulationhandler should apply angular velocity to rigidBody upon release.");
            Assert.AreEqual(rigidBody.velocity, hand.GetVelocity(), "Manipulationhandler should apply hand velocity to rigidBody upon release.");

            // This is just for debugging purposes, so object's movement after release can be seen.
            yield return(hand.MoveTo(initialHandPosition));

            yield return(hand.Hide());

            GameObject.Destroy(testObject);
            yield return(null);
        }
Пример #15
0
        public IEnumerator ZoomRotatedSlate()
        {
            // Configuring camera and hands to interact with rotated slate
            InstantiateFromPrefab(Vector3.right, Quaternion.LookRotation(Vector3.right));
            MixedRealityPlayspace.PerformTransformation(p => p.Rotate(Vector3.up, 90));
            yield return(null);

            // Right hand pinches slate
            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.Show(panZoom.transform.position + Vector3.forward * -0.1f + Vector3.right * -0.3f));

            yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            // Left hand pinches slate
            TestHand handLeft = new TestHand(Handedness.Left);

            yield return(handLeft.Show(panZoom.transform.position + Vector3.forward * 0.1f + Vector3.right * -0.3f));

            yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            // Use both hands to zoom in
            yield return(handRight.Move(new Vector3(0f, 0f, -0.1f), 5));

            yield return(handLeft.Move(new Vector3(0f, 0f, 0.1f), 5));

            Assert.AreEqual(0.6, panZoom.CurrentScale, 0.1, "Rotated slate did not zoom in using near interaction");

            // Reset slate and hands configuration
            panZoom.Reset();
            yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(null);

            // Both hands touch slate
            yield return(handRight.MoveTo(panZoom.transform.position + Vector3.forward * -0.1f));

            yield return(handLeft.MoveTo(panZoom.transform.position + Vector3.forward * 0.1f));

            yield return(null);

            // Use both hands to zoom in
            yield return(handRight.Move(new Vector3(0f, 0f, -0.1f), 5));

            yield return(handLeft.Move(new Vector3(0f, 0f, 0.1f), 5));

            Assert.AreEqual(0.6, panZoom.CurrentScale, 0.1, "Rotated slate did not zoom in using far interaction");

            yield return(handRight.Hide());

            yield return(handLeft.Hide());
        }
        public IEnumerator TestPressEvents()
        {
            var testHand = new TestHand(Handedness.Right);

            interactable.gameObject.AddComponent <NearInteractionGrabbable>();
            var  pressReceiver = interactable.AddReceiver <InteractableOnPressReceiver>();
            bool didPress      = false;

            pressReceiver.OnPress.AddListener(() => didPress = true);
            yield return(testHand.Show(interactable.transform.position));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(testHand.Hide());

            Assert.True(didPress, "did not receive press event");
        }
Пример #17
0
        public IEnumerator Prefab_TouchScroll()
        {
            InstantiateFromPrefab(Vector3.forward);
            Vector2 totalPanDelta = Vector2.zero;

            panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta);

            TestHand h = new TestHand(Handedness.Right);;

            yield return(h.MoveTo(panObject.transform.position));

            yield return(h.Move(new Vector3(0, -0.05f, 0), 10));

            Assert.AreEqual(0.1, totalPanDelta.y, 0.05, "pan delta is not correct");

            yield return(h.Hide());
        }
        public IEnumerator TestAssembleInteractableAndEventsRaised()
        {
            GameObject  pinchSliderObject;
            PinchSlider slider;

            // This should not throw exception
            AssembleSlider(Vector3.forward, Vector3.zero, out pinchSliderObject, out slider);

            var     rightHand  = new TestHand(Handedness.Right);
            Vector3 initialPos = new Vector3(0.05f, 0, 1.0f);

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            bool interactionStarted = false;

            slider.OnInteractionStarted.AddListener((x) => interactionStarted = true);
            yield return(rightHand.Show(initialPos));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            Assert.IsTrue(interactionStarted, "Slider did not raise interaction started.");

            bool interactionUpdated = false;

            slider.OnValueUpdated.AddListener((x) => interactionUpdated = true);

            yield return(rightHand.Move(new Vector3(0.1f, 0, 0)));

            Assert.IsTrue(interactionUpdated, "Slider did not raise SliderUpdated event.");

            bool interactionEnded = false;

            slider.OnInteractionEnded.AddListener((x) => interactionEnded = true);

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(rightHand.Hide());

            Assert.IsTrue(interactionEnded, "Slider did not raise interaction ended.");

            Assert.That(slider.SliderValue, Is.GreaterThan(0.5));

            GameObject.Destroy(pinchSliderObject);
        }
Пример #19
0
        public IEnumerator TestHandConstraint()
        {
            // Instantiate our test GameObject with solver.
            var testObjects = InstantiateTestSolver <HandConstraint>();

            testObjects.handler.TrackedTargetType = TrackedObjectType.HandJoint;
            testObjects.handler.TrackedHandness   = Handedness.Both;

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            TestUtilities.AssertAboutEqual(testObjects.target.transform.position, Vector3.zero, "HandConstraint solver did not start at the origin");

            // Add a right hand.
            var rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(Vector3.zero));

            // Move the hand to 0, 0, 1 and ensure that the hand constraint followed.
            var handPosition = Vector3.forward;

            yield return(rightHand.MoveTo(handPosition));

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            // Make sure the solver is not in the same location as the hand because the solver should move to a hand safe zone.
            TestUtilities.AssertNotAboutEqual(testObjects.target.transform.position, handPosition, "HandConstraint solver is in the same location of the hand when it should be slightly offset from the hand.");

            // Make sure the solver is near the hand.
            Assert.LessOrEqual(Vector3.Distance(testObjects.target.transform.position, handPosition), HandDistanceThreshold, "HandConstraint solver is not within {0} units of the hand", HandDistanceThreshold);

            // Hide the right hand and create a left hand.
            yield return(rightHand.Hide());

            var leftHand = new TestHand(Handedness.Left);

            handPosition = Vector3.zero;
            yield return(leftHand.Show(handPosition));

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            // Make sure the solver is now near the other hand.
            Assert.LessOrEqual(Vector3.Distance(testObjects.target.transform.position, handPosition), HandDistanceThreshold, "HandConstraint solver is not within {0} units of the hand", HandDistanceThreshold);
        }
        public IEnumerator PrefabScrollUpZoomOutLimited()
        {
            var maxPanHorizontal = 4f;
            var maxPanVertical   = 4f;

            InstantiatePanLimitedSlateFromPrefab(maxPanHorizontal: maxPanHorizontal, maxPanVertical: maxPanVertical);

            yield return(ScrollToLimit(new Vector3(1, 1, 0)));

            // Right hand pinches slate
            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.MoveTo(panZoom.transform.position + Vector3.forward * -0.5f + Vector3.right * 0.2f));

            yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            // Left hand pinches slate
            TestHand handLeft = new TestHand(Handedness.Left);

            yield return(handLeft.Show(panZoom.transform.position + Vector3.forward * -0.5f + Vector3.right * -0.2f));

            yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            // Use both hands to zoom out
            yield return(handLeft.Move(new Vector3(0.1f, 0.1f, 0f), 10));

            var uvs = new List <Vector2>();

            meshFilter.mesh.GetUVs(0, uvs);

#if UNITY_2019_1_OR_NEWER
            Assert.AreEqual(maxPanHorizontal * material.mainTextureScale.x, uvs[3].x, 0.05, "mesh uv is not correct");
            Assert.AreEqual(maxPanVertical * material.mainTextureScale.y, uvs[3].y, 0.05, "mesh uv is not correct");
#else
            Assert.AreEqual(maxPanHorizontal * material.mainTextureScale.x, uvs[1].x, 0.05, "mesh uv is not correct");
            Assert.AreEqual(maxPanVertical * material.mainTextureScale.y, uvs[1].y, 0.05, "mesh uv is not correct");
#endif

            yield return(handRight.Hide());

            yield return(handLeft.Hide());
        }
Пример #21
0
        /// <summary>
        /// Scroll a slate using GGV and ensure that the slate scrolls
        /// expected amount. Assumes panZoom has already been created.
        /// </summary>
        /// <param name="expectedScroll">The amount panZoom is expected to scroll</param>
        private IEnumerator RunGGVScrollTest(float expectedScroll)
        {
            PlayModeTestUtilities.SetHandSimulationMode(HandSimulationMode.Gestures);

            Vector2 totalPanDelta = Vector2.zero;

            panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta);

            TestHand h = new TestHand(Handedness.Right);

            yield return(h.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(h.Show(Vector3.zero));

            yield return(h.Move(new Vector3(0.0f, -0.1f, 0f)));

            Assert.AreEqual(expectedScroll, totalPanDelta.y, 0.05, "pan delta is not correct");

            yield return(h.Hide());
        }
Пример #22
0
        public IEnumerator TestUseSourcePoseDataAsFallback()
        {
            TestHand rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(Vector3.zero));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            PokePointer pokePointer = PointerUtils.GetPointer <PokePointer>(Handedness.Right);

            Assert.IsNotNull(pokePointer);
            pokePointer.UseSourcePoseAsFallback = true;

            SpherePointer grabPointer = PointerUtils.GetPointer <SpherePointer>(Handedness.Right);

            Assert.IsNotNull(grabPointer);
            grabPointer.UseSourcePoseAsFallback = true;

            // Setting the pointer's pose action to a new input action is functionally equivalent to ensuring that an event is never raised of the pointer's desired pose action
            // This makes it so it will have to use the source pose data as a fallback
            pokePointer.PoseAction = new MixedRealityInputAction();
            grabPointer.PoseAction = new MixedRealityInputAction();
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(rightHand.Hide());

            yield return(rightHand.Show(Vector3.zero));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            // The source pose is centered on the palm
            MixedRealityPose palmPose;

            HandJointUtils.TryGetJointPose(TrackedHandJoint.Palm, Handedness.Right, out palmPose);

            // This offset value is derived from the PokePointer's sourcePoseOffset property
            float pokePointerOffset = 0.075f;

            TestUtilities.AssertAboutEqual(pokePointer.Position, grabPointer.Position + pokePointer.transform.forward * pokePointerOffset, "pointer was not in the expected position");
            TestUtilities.AssertAboutEqual(grabPointer.Position, palmPose.Position, "pointer was not in the expected position");
        }
        /// <summary>
        /// Scroll contents to the limit in the specified direction
        /// </summary>
        /// <param name="direction">Scroll direction</param>
        private IEnumerator ScrollToLimit(Vector3 direction)
        {
            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.Show(Vector3.zero));

            Vector3 screenPoint = CameraCache.Main.ViewportToScreenPoint(new Vector3(0.5f, 0.0f, 0.5f));
            var     moveDelta   = -0.5f * direction;

            for (var i = 0; i < 3; i++)
            {
                yield return(handRight.MoveTo(CameraCache.Main.ScreenToWorldPoint(screenPoint)));

                yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch));

                yield return(handRight.Move(moveDelta, 10));

                yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Open));
            }

            yield return(handRight.Hide());
        }
Пример #24
0
        public IEnumerator Prefab_RayScroll()
        {
            InstantiateFromPrefab(Vector3.forward);
            Vector2 totalPanDelta = Vector2.zero;

            panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta);

            TestHand h           = new TestHand(Handedness.Right);
            Vector3  screenPoint = CameraCache.Main.ViewportToScreenPoint(new Vector3(0.5f, 0.25f, 0.5f));

            yield return(h.Show(CameraCache.Main.ScreenToWorldPoint(screenPoint)));

            yield return(h.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(h.Move(new Vector3(0, -0.05f, 0), 10));

            yield return(h.SetGesture(ArticulatedHandPose.GestureId.Open));

            Assert.AreEqual(0.1, totalPanDelta.y, 0.05, "pan delta is not correct");

            yield return(h.Hide());
        }
        public IEnumerator TestHoldEvents()
        {
            // Hold
            var  holdReceiver = interactable.AddReceiver <InteractableOnHoldReceiver>();
            bool didHold      = false;

            holdReceiver.OnHold.AddListener(() => didHold = true);

            var testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(interactable.transform.position));

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(new WaitForSeconds(holdReceiver.HoldTime));

            yield return(testHand.Hide());

            Assert.True(didHold, "Did not receive hold event");
            GameObject.Destroy(cube);
            yield return(null);
        }
Пример #26
0
        public IEnumerator TestOverlap()
        {
            // Instantiate our test GameObject with solver.
            var testObjects = InstantiateTestSolver <Overlap>();

            testObjects.handler.TrackedTargetType = TrackedObjectType.HandJoint;
            var targetTransform = testObjects.target.transform;

            TestUtilities.AssertAboutEqual(targetTransform.position, Vector3.zero, "Overlap not at original position");
            TestUtilities.AssertAboutEqual(targetTransform.rotation, Quaternion.identity, "Overlap not at original rotation");

            // Test that the solver flies to the position of the left hand
            var handPosition = Vector3.forward - Vector3.right;
            var handRotation = Quaternion.LookRotation(handPosition);
            var leftHand     = new TestHand(Handedness.Left);

            yield return(leftHand.Show(handPosition));

            yield return(leftHand.SetRotation(handRotation));

            yield return(WaitForFrames(2));

            var hand = PlayModeTestUtilities.GetInputSimulationService().GetHandDevice(Handedness.Left);

            Assert.IsNotNull(hand);
            Assert.IsTrue(hand.TryGetJoint(TrackedHandJoint.Palm, out MixedRealityPose pose));

            TestUtilities.AssertAboutEqual(targetTransform.position, pose.Position, "Overlap solver is not at the same position as the left hand.");
            Assert.IsTrue(Quaternion.Angle(targetTransform.rotation, pose.Rotation) < 2.0f);

            // Make sure the solver did not move when hand was hidden
            yield return(leftHand.Hide());

            yield return(WaitForFrames(2));

            TestUtilities.AssertAboutEqual(targetTransform.position, pose.Position, "Overlap solver moved when the hand was hidden.");
            Assert.IsTrue(Quaternion.Angle(targetTransform.rotation, pose.Rotation) < 2.0f);
        }
Пример #27
0
        public IEnumerator TestToggleEvents()
        {
            var iss        = PlayModeTestUtilities.GetInputSimulationService();
            var oldSimMode = iss.ControllerSimulationMode;

            iss.ControllerSimulationMode = ControllerSimulationMode.HandGestures;

            var toggleReceiver = interactable.AddReceiver <InteractableOnToggleReceiver>();

            interactable.transform.position = Vector3.forward * 2f;
            interactable.NumOfDimensions    = 2;
            interactable.CanSelect          = true;
            interactable.CanDeselect        = true;
            bool didSelect   = false;
            bool didUnselect = false;

            toggleReceiver.OnSelect.AddListener(() => didSelect     = true);
            toggleReceiver.OnDeselect.AddListener(() => didUnselect = true);

            var testHand = new TestHand(Handedness.Right);

            yield return(testHand.Show(Vector3.forward));

            CameraCache.Main.transform.LookAt(interactable.transform.position);

            yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(testHand.Click());

            yield return(testHand.Click());

            yield return(testHand.Hide());

            Assert.True(didSelect, "Toggle select did not fire");
            Assert.True(didUnselect, "Toggle unselect did not fire");

            iss.ControllerSimulationMode = oldSimMode;
        }
Пример #28
0
        public IEnumerator TestPointerFOV()
        {
            var rightHand = new TestHand(Handedness.Right);

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.AddComponent <NearInteractionGrabbable>();
            cube.AddComponent <NearInteractionTouchableVolume>();
            yield return(rightHand.Show(Vector3.zero));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            var spherePointer = PointerUtils.GetPointer <SpherePointer>(Handedness.Right);
            var pokePointer   = PointerUtils.GetPointer <PokePointer>(Handedness.Right);

            yield return(TestPointerFOVHelper(spherePointer, cube, rightHand));

            yield return(TestPointerFOVHelper(pokePointer, cube, rightHand));

            rightHand.Hide();
            GameObject.Destroy(cube);
        }
Пример #29
0
        public IEnumerator TestUseSourcePoseData()
        {
            TestHand rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(Vector3.zero));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            PokePointer pokePointer = PointerUtils.GetPointer <PokePointer>(Handedness.Right);

            Assert.IsNotNull(pokePointer);
            SpherePointer grabPointer = PointerUtils.GetPointer <SpherePointer>(Handedness.Right);

            Assert.IsNotNull(grabPointer);

            pokePointer.UseSourcePoseData = true;
            grabPointer.UseSourcePoseData = true;
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(rightHand.Hide());

            yield return(rightHand.Show(Vector3.zero));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());


            // The source pose is centered on the palm
            MixedRealityPose palmPose;

            HandJointUtils.TryGetJointPose(TrackedHandJoint.Palm, Handedness.Right, out palmPose);
            // This offset value is derived from the PokePointer's sourcePoseOffset property
            float pokePointerOffset = 0.075f;

            TestUtilities.AssertAboutEqual(pokePointer.Position, grabPointer.Position + pokePointer.transform.forward * pokePointerOffset, "pointer was not in the expected position");
            TestUtilities.AssertAboutEqual(grabPointer.Position, palmPose.Position, "pointer was not in the expected position");
        }
Пример #30
0
        public IEnumerator CursorContextMove()
        {
            var inputSystem = PlayModeTestUtilities.GetInputSystem();

            // The cube needs to be moved from under the gaze cursor before we add the manipulation handler.
            // Because the cube is under the gaze cursor from the beginning, it gets a focus gained event
            // in Setup(). When we show the right hand, we get a focus lost event from the gaze pointer.
            // This messes with the CursorContextManipulationHandler hoverCount, as it decrements without
            // ever having incremented. To avoid this, we move the cube out of focus before we add the
            // ManipulationHandler and CursorContextManipulationHandler.
            cube.transform.localPosition = new Vector3(0, -2, 2);
            yield return(new WaitForFixedUpdate());

            yield return(null);

            cube.AddComponent <ManipulationHandler>();
            var temp = cube.AddComponent <CursorContextManipulationHandler>();

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Move cube back to original postion (described above)
            cube.transform.localPosition = new Vector3(0, 0, 2);
            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Show right hand on object
            var     rightHand = new TestHand(Handedness.Right);
            Vector3 rightPos  = new Vector3(0.05f, 0, 1.5f);

            yield return(rightHand.Show(rightPos));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            VerifyCursorContextFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorContextEnum.None);

            // Pinch right hand
            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            VerifyCursorContextFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorContextEnum.MoveCross);

            // Show left hand on object
            var     leftHand = new TestHand(Handedness.Left);
            Vector3 leftPos  = new Vector3(-0.05f, 0, 1.5f);

            yield return(rightHand.Hide());

            yield return(leftHand.Show(leftPos));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            VerifyCursorContextFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorContextEnum.None);

            // Pinch left hand
            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            VerifyCursorContextFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorContextEnum.MoveCross);

            // Show both hands on object
            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(rightHand.Show(rightPos));

            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            VerifyCursorContextFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorContextEnum.MoveCross);

            Object.Destroy(cube.GetComponent <ManipulationHandler>());
            Object.Destroy(cube.GetComponent <CursorContextManipulationHandler>());
        }