public IEnumerator TestPoke()
        {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.AddComponent <NearInteractionTouchableVolume>();
            cube.transform.position = Vector3.forward * 0.5f;

            TestHand rightHand = new TestHand(Handedness.Right);
            TestHand leftHand  = new TestHand(Handedness.Left);

            TestContext.Out.WriteLine("Show both hands near touchable cube");
            yield return(rightHand.Show(Vector3.zero));

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

            yield return(new WaitForFixedUpdate());

            PointerStateContainer touchOn = new PointerStateContainer()
            {
                GazePointerEnabled   = false,
                GGVPointerEnabled    = null,
                PokePointerEnabled   = true,
                SpherePointerEnabled = false,
                LinePointerEnabled   = false
            };

            EnsurePointerStates(Handedness.Right, touchOn);
            EnsurePointerStates(Handedness.Left, touchOn);

            TestContext.Out.WriteLine("Turn off poke pointer right hand");
            PointerUtils.SetHandPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);
            yield return(null);

            PointerStateContainer touchOff = new PointerStateContainer()
            {
                GazePointerEnabled   = false,
                GGVPointerEnabled    = null,
                PokePointerEnabled   = false,
                SpherePointerEnabled = false,
                LinePointerEnabled   = true
            };

            EnsurePointerStates(Handedness.Right, touchOff);
            EnsurePointerStates(Handedness.Left, touchOn);

            TestContext.Out.WriteLine("Turn off poke pointer both hands");
            PointerUtils.SetHandPokePointerBehavior(PointerBehavior.AlwaysOff);
            yield return(null);

            EnsurePointerStates(Handedness.Right, touchOff);
            EnsurePointerStates(Handedness.Left, touchOff);
        }
Ejemplo n.º 2
0
        public IEnumerator ConstrainScaleApparentSize()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            testObject.transform.position   = new Vector3(0f, 0f, 1f);
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform          = testObject.transform;
            manipHandler.SmoothingActive        = false;
            manipHandler.ManipulationType       = ObjectManipulator.HandMovementType.OneHanded;
            manipHandler.OneHandRotationModeFar = ObjectManipulator.RotateInOneHandType.RotateAboutObjectCenter;

            // add an xy move constraint so that the object's position does not change on screen
            var moveConstraint = manipHandler.EnsureComponent <MoveAxisConstraint>();

            moveConstraint.UseLocalSpaceForConstraint = false;
            moveConstraint.ConstraintOnMovement       = AxisFlags.XAxis | AxisFlags.YAxis;

            var constraint = manipHandler.EnsureComponent <MaintainApparentSizeConstraint>();

            Vector3 topLeft       = testObject.transform.TransformPoint(new Vector3(-0.5f, 0.5f, -0.5f));
            Vector3 bottomRight   = testObject.transform.TransformPoint(new Vector3(0.5f, -0.5f, -0.5f));
            float   originalAngle = Vector3.Angle(topLeft - CameraCache.Main.transform.position, bottomRight - CameraCache.Main.transform.position);

            yield return(new WaitForFixedUpdate());

            yield return(null);

            const int numHandSteps = 100;

            // Hand pointing at middle of cube
            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(new Vector3(0.044f, -0.1f, 0.45f)));

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

            // Move and test that still same distance from head
            yield return(hand.Move(Vector3.forward * 0.5f, numHandSteps));

            yield return(null);

            Vector3 newtopLeft     = testObject.transform.TransformPoint(new Vector3(-0.5f, 0.5f, -0.5f));
            Vector3 newBottomRight = testObject.transform.TransformPoint(new Vector3(0.5f, -0.5f, -0.5f));
            float   newAngle       = Vector3.Angle(newtopLeft - CameraCache.Main.transform.position, newBottomRight - CameraCache.Main.transform.position);

            Assert.AreEqual(originalAngle, newAngle, 0.05f);
        }
        public IEnumerator GrabLayerMasks()
        {
            // Initialize hand
            var rightHand = new TestHand(Handedness.Right);

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

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

            var pointer = rightHand.GetPointer <SpherePointer>();

            Assert.IsNotNull(pointer, "Expected to find SpherePointer in the hand controller");
            Vector3 interactionEnabledPos = new Vector3(0.05f, 0, colliderSurfaceZ - pointer.SphereCastRadius);

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Move hand to object, IsNearObject, IsInteractionEnabled should be true
            yield return(rightHand.MoveTo(interactionEnabledPos));

            Assert.True(pointer.IsNearObject);
            Assert.True(pointer.IsInteractionEnabled);

            // Set layer to spatial mesh, which sphere pointer should be ignoring
            // assumption: layer 31 is the spatial mesh layer
            cube.SetLayerRecursively(31);
            yield return(null);

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Set layer back to default
            cube.SetLayerRecursively(0);
            yield return(null);

            Assert.True(pointer.IsNearObject);
            Assert.True(pointer.IsInteractionEnabled);

            // Remove the grabbable component, ray should turn on
            GameObject.Destroy(cube.GetComponent <NearInteractionGrabbable>());
            yield return(null);

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Add back the grabbable, ray should turn off
            cube.AddComponent <NearInteractionGrabbable>();
            yield return(null);

            Assert.True(pointer.IsNearObject);
            Assert.True(pointer.IsInteractionEnabled);
        }
Ejemplo n.º 4
0
        public IEnumerator TestTapToPlaceCodeConfigurability()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

            // Create a cube with Tap to Place attached
            var tapToPlaceObj = InstantiateTestSolver <TapToPlace>();

            tapToPlaceObj.target.transform.position = Vector3.forward;
            TapToPlace tapToPlace = tapToPlaceObj.solver as TapToPlace;

            // Start Placing the object immediately
            tapToPlace.AutoStart = true;

            Vector3 handStartPosition = new Vector3(0, -0.1f, 0.6f);
            var     leftHand          = new TestHand(Handedness.Left);

            yield return(leftHand.Show(handStartPosition));

            // Make sure the object is being placed after setting AutoStart
            Assert.True(tapToPlace.IsBeingPlaced);

            // Move the playspace to simulate head movement
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.left * 1.5f;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Make sure the target obj is following the head
            Assert.AreEqual(CameraCache.Main.transform.position.x, tapToPlaceObj.target.transform.position.x, "The tap to place object position.x does not match the camera position.x");

            // Stop the placement via code instead of click from the hand
            tapToPlace.StopPlacement();

            Assert.False(tapToPlace.IsBeingPlaced);

            // Move the playspace to simulate head movement again
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.right;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Make sure the target obj is NOT following the head
            Assert.AreNotEqual(CameraCache.Main.transform.position.x, tapToPlaceObj.target.transform.position.x, "The tap to place object position.x matches the camera position.x, when it should not");
        }
Ejemplo n.º 5
0
        public IEnumerator ConstrainRotationFixToWorld()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

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

            testObject.transform.localScale = Vector3.one * 0.2f;
            testObject.transform.position   = Vector3.forward;
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform           = testObject.transform;
            manipHandler.SmoothingActive         = false;
            manipHandler.ManipulationType        = ManipulationHandFlags.OneHanded;
            manipHandler.OneHandRotationModeNear = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint;

            var rotConstraint = manipHandler.EnsureComponent <FixedRotationToWorldConstraint>();

            rotConstraint.TargetTransform = manipHandler.HostTransform;

            // Face user first
            const int numHandSteps = 1;
            TestHand  hand         = new TestHand(Handedness.Right);

            yield return(hand.Show(new Vector3(0.05f, -0.1f, 0.45f)));

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

            yield return(null);

            // rotate the hand
            yield return(hand.SetRotation(Quaternion.Euler(45, 45, 45), numHandSteps));

            yield return(null);

            Assert.AreEqual(Quaternion.identity, testObject.transform.rotation);

            // move the hand
            yield return(hand.Move(Vector3.right * 0.2f, numHandSteps));

            yield return(null);

            Assert.AreEqual(Quaternion.identity, testObject.transform.rotation);

            // rotate the head
            CameraCache.Main.transform.Rotate(new Vector3(0, 10, 0));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.AreEqual(Quaternion.identity, testObject.transform.rotation);
        }
        public IEnumerator ScaleViaHoloLens1Interaction()
        {
            var bbox = InstantiateSceneAndDefaultBbox();

            yield return(null);

            yield return(null);

            var bounds      = bbox.GetComponent <BoxCollider>().bounds;
            var startCenter = new Vector3(0, 0, 1.5f);
            var startSize   = new Vector3(.5f, .5f, .5f);

            TestUtilities.AssertAboutEqual(bounds.center, startCenter, "bbox incorrect center at start");
            TestUtilities.AssertAboutEqual(bounds.size, startSize, "bbox incorrect size at start");

            PlayModeTestUtilities.PushHandSimulationProfile();
            PlayModeTestUtilities.SetHandSimulationMode(HandSimulationMode.Gestures);

            CameraCache.Main.transform.LookAt(bbox.ScaleCorners[3].transform);

            var      startHandPos = CameraCache.Main.transform.TransformPoint(new Vector3(0.1f, 0f, 1.5f));
            TestHand rightHand    = new TestHand(Handedness.Right);

            yield return(rightHand.Show(startHandPos));

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

            // After pinching, center should remain the same
            var afterPinchbounds = bbox.GetComponent <BoxCollider>().bounds;

            TestUtilities.AssertAboutEqual(afterPinchbounds.center, startCenter, "bbox incorrect center after pinch");
            TestUtilities.AssertAboutEqual(afterPinchbounds.size, startSize, "bbox incorrect size after pinch");

            var delta = new Vector3(0.1f, 0.1f, 0f);

            yield return(rightHand.Move(delta));

            var endBounds = bbox.GetComponent <BoxCollider>().bounds;

            TestUtilities.AssertAboutEqual(endBounds.center, new Vector3(0.033f, 0.033f, 1.467f), "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, Vector3.one * .561f, "endBounds incorrect size", 0.02f);

            GameObject.Destroy(bbox.gameObject);
            // Wait for a frame to give Unity a change to actually destroy the object
            yield return(null);

            // Restore the input simulation profile
            PlayModeTestUtilities.PopHandSimulationProfile();

            yield return(null);
        }
        public IEnumerator TestAddingAndSettingNewState()
        {
            // Create an interactive cube
            InteractiveElement interactiveElement = CreateInteractiveCube();

            yield return(null);

            // Create a new state and add it to Tracked States
            interactiveElement.AddNewState(newStateName);

            // Change the value of my new state by using the focus state events to set the new state
            InteractionState focusState = interactiveElement.GetState(CoreInteractionState.Focus.ToString());

            var focusEventConfiguration = interactiveElement.GetStateEvents <FocusEvents>(focusStateName);

            yield return(null);

            focusEventConfiguration.OnFocusOn.AddListener((focusEventData) =>
            {
                // When the object comes into focus, set my new state to on
                interactiveElement.SetStateOn(newStateName);
            });

            focusEventConfiguration.OnFocusOff.AddListener((focusEventData) =>
            {
                // When the object comes out of  focus, set my new state to off
                interactiveElement.SetStateOff(newStateName);
            });

            // Make sure MyNewState is being tracked
            InteractionState myNewState = interactiveElement.GetState(newStateName);

            Assert.IsNotNull(myNewState);

            // Make sure the value is 0/off initially
            Assert.AreEqual(0, myNewState.Value);

            // Create a new hand and initialize it with an object in focus
            var leftHand = new TestHand(Handedness.Left);

            yield return(ShowHandWithObjectInFocus(leftHand));

            // Make sure the value of MyNewState was changed when the object is in focus
            Assert.AreEqual(1, myNewState.Value);

            // Move hand away from object to remove focus
            yield return(MoveHandOutOfFocus(leftHand));

            // Make sure the value of MyNewState was changed when the object is no longer in focus
            Assert.AreEqual(0, myNewState.Value);
        }
        public IEnumerator TestSelectFarEventConfiguration()
        {
            // Create an interactive cube
            InteractiveElement interactiveElement = CreateInteractiveCube();

            yield return(null);

            // Add the selectFar state
            InteractionState selectFar = interactiveElement.AddNewState(selectFarStateName);

            yield return(null);

            // Get the event configuration for the SelectFar state
            var eventConfiguration = interactiveElement.GetStateEvents <SelectFarEvents>(selectFarStateName);

            // Set global to true, this registers the IMixedRealityPointerHandler
            eventConfiguration.Global = true;

            bool onSelectDown    = false;
            bool onSelectHold    = false;
            bool onSelectClicked = false;
            bool onSelectUp      = false;

            eventConfiguration.OnSelectDown.AddListener((eventData) => { onSelectDown = true; });
            eventConfiguration.OnSelectHold.AddListener((eventData) => { onSelectHold = true; });
            eventConfiguration.OnSelectClicked.AddListener((eventData) => { onSelectClicked = true; });
            eventConfiguration.OnSelectUp.AddListener((eventData) => { onSelectUp = true; });

            // Create a new hand and initialize it with an object in focus
            var leftHand = new TestHand(Handedness.Left);

            // Show hand at starting position
            yield return(ShowHandWithObjectInFocus(leftHand));

            yield return(MoveHandOutOfFocus(leftHand));

            // Click the hand to trigger far select events
            yield return(leftHand.Click());

            Assert.True(onSelectDown);
            Assert.True(onSelectHold);
            Assert.True(onSelectClicked);
            Assert.True(onSelectUp);

            eventConfiguration.Global = false;

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

            // Make sure the SelectFar state is not active after setting global to false without an object in focus
            Assert.AreEqual(0, selectFar.Value);
        }
        /// <summary>
        /// Tests button depth and focus state after enabling, disabling and re-enabling Interactable
        /// internally via IsEnabled. The focus state after re-enabling should be false and button
        /// depth should be in its default position.  This test is specifically addressing behavior described
        /// in issue 4967.
        /// </summary>
        public IEnumerator TestInteractableDisableOnClick()
        {
            var     rightHand = new TestHand(Handedness.Right);
            Vector3 p1        = Vector3.zero;
            Vector3 p2        = new Vector3(0.05f, 0f, 0.51f);

            // Load the Model_PushButton interactable prefab
            Interactable interactable;
            Transform    innerCylinderTransform;

            InstantiatePressButtonPrefab(
                new Vector3(0.0f, 0.0f, 0.5f),
                DefaultRotation,
                out interactable,
                out innerCylinderTransform);

            Assert.True(interactable.IsEnabled);

            // OnClick, disable Interactable
            interactable.OnClick.AddListener(() => { interactable.IsEnabled = false; });

            // Get start position of the inner cylinder before button is pressed
            Vector3 innerCylinderStartPosition = innerCylinderTransform.localPosition;

            // Move the hand forward to press button
            yield return(rightHand.Show(p1));

            yield return(rightHand.MoveTo(p2));

            // Ensure that the inner cylinder in the button has moved on press
            yield return(CheckButtonTranslation(innerCylinderStartPosition, innerCylinderTransform));

            // Move the hand back
            yield return(rightHand.MoveTo(p1));

            yield return(new WaitForSeconds(ButtonReleaseAnimationDelay));

            Assert.False(interactable.IsEnabled);

            // Re-enable Interactable
            interactable.IsEnabled = true;
            yield return(null);

            // Make sure the button depth is back at the starting position when re-enable the gameObject
            Assert.True(innerCylinderTransform.localPosition == innerCylinderStartPosition);

            // Make sure the focus state is false after we re-enable Interactable
            Assert.False(interactable.HasFocus);

            GameObject.Destroy(interactable.gameObject);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Move the hand forward to press button, then off to the right
        /// </summary>
        private IEnumerator PressButtonWithHand()
        {
            Vector3 p1 = new Vector3(0, 0, 0.5f);
            Vector3 p2 = new Vector3(0, 0, 1.08f);
            Vector3 p3 = new Vector3(0.1f, 0, 1.08f);

            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(p1));

            yield return(hand.MoveTo(p2));

            yield return(hand.MoveTo(p3));
        }
        public IEnumerator TestPressableToggleHoloLens2()
        {
            var     rightHand = new TestHand(Handedness.Right);
            Vector3 p2        = new Vector3(0.015f, 0f, 0.3f);

            Interactable interactable;
            Transform    frontPlateTransform;

            InstantiatePressableButtonPrefab(
                new Vector3(0.0f, 0.1f, 0.4f),
                DefaultRotationToggle,
                PressableHoloLens2TogglePrefabPath,
                "CompressableButtonVisuals/FrontPlate",
                out interactable,
                out frontPlateTransform);

            Assert.True(interactable.IsEnabled);

            bool wasClicked = false;

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

            // Get start position of the front plate before button is pressed
            Vector3 frontPlateStartPosition = frontPlateTransform.localPosition;

            yield return(rightHand.Show(p2));

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.IsTrue(interactable.HasFocus, "Interactable does not have focus when hand is pointing at it.");

            int numClicks = 3;

            for (int i = 0; i < numClicks; i++)
            {
                wasClicked = false;
                yield return(rightHand.Click());

                // Wait for button animation to complete
                yield return(new WaitForSeconds(0.33f));

                Assert.True(wasClicked, "Toggle button was not clicked");
                Assert.AreEqual((i + 1) % 2, interactable.CurrentDimension, $"Toggle button is in incorrect toggle state on click {i}");

                // Make sure the button depth is back at the starting position
                Assert.True(frontPlateTransform.localPosition == frontPlateStartPosition, "Toggle button front plate did not return to starting position.");
            }

            GameObject.Destroy(interactable.gameObject);
        }
Ejemplo n.º 12
0
        public IEnumerator ConstrainMovementFixedDistance()
        {
            TestUtilities.PlayspaceToArbitraryPose();

            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            testObject.transform.position   = TestUtilities.PositionRelativeToPlayspace(new Vector3(0f, 0f, 1f));
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform          = testObject.transform;
            manipHandler.SmoothingFar           = false;
            manipHandler.ManipulationType       = ManipulationHandFlags.OneHanded;
            manipHandler.OneHandRotationModeFar = ObjectManipulator.RotateInOneHandType.RotateAboutObjectCenter;

            var constraint = manipHandler.EnsureComponent <FixedDistanceConstraint>();

            constraint.ConstraintTransform = CameraCache.Main.transform;

            float originalDist = (CameraCache.Main.transform.position - testObject.transform.position).magnitude;

            yield return(new WaitForFixedUpdate());

            yield return(null);

            const int numHandSteps = 1;

            // Hand pointing at middle of cube
            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(TestUtilities.PositionRelativeToPlayspace(new Vector3(0.044f, -0.1f, 0.45f))));

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

            Vector3 worldDelta = TestUtilities.DirectionRelativeToPlayspace(Vector3.one);

            // Move and test that still same distance from head
            yield return(hand.Move(worldDelta * 0.5f, numHandSteps));

            yield return(null);

            Assert.AreEqual(originalDist, (CameraCache.Main.transform.position - testObject.transform.position).magnitude, 0.001f);

            yield return(hand.Move(worldDelta * -1f, numHandSteps));

            yield return(null);

            Assert.AreEqual(originalDist, (CameraCache.Main.transform.position - testObject.transform.position).magnitude, 0.001f);
        }
        public IEnumerator TestActiveInactive()
        {
            // Create an interactive cube
            InteractiveElement interactiveElement = CreateInteractiveCube();

            yield return(null);

            // Get the focus state
            InteractionState focusState = interactiveElement.GetState(focusStateName);

            // Add the touch state
            InteractionState touchState = interactiveElement.AddNewState(touchStateName);

            yield return(null);

            Assert.True(interactiveElement.Active);

            // Make sure the Focus and Touch state are not on
            Assert.AreEqual(0, touchState.Value);
            Assert.AreEqual(0, focusState.Value);

            // Create a new hand and initialize it with an object in focus
            var leftHand = new TestHand(Handedness.Left);

            yield return(ShowHandWithObjectInFocus(leftHand));

            // Move hand to Touch the object
            yield return(MoveHandTouchObject(leftHand));

            // Make sure the values change when the hand is moved to touch the cube
            Assert.AreEqual(1, touchState.Value);
            Assert.AreEqual(1, focusState.Value);
            yield return(null);

            yield return(MoveHandOutOfFocus(leftHand));

            // Set Active to false to disable internal updates
            interactiveElement.Active = false;

            // Show hand at starting position
            yield return(ShowHandWithObjectInFocus(leftHand));

            // Move hand to Touch the object
            yield return(MoveHandTouchObject(leftHand));

            // Make sure the values do not change when the hand is moved to touch the cube
            Assert.AreEqual(0, touchState.Value);
            Assert.AreEqual(0, focusState.Value);
            yield return(null);
        }
        public IEnumerator TestTeleportStrafe()
        {
            var iss = PlayModeTestUtilities.GetInputSimulationService();

            // Create a floor and make sure it's below the camera
            var floor = GameObject.CreatePrimitive(PrimitiveType.Cube);

            floor.transform.position = -0.5f * Vector3.up;

            // Bring out the right hand and set it to the teleport gesture
            TestUtilities.PlayspaceToOriginLookingForward();
            Vector3 initialPosition = MixedRealityPlayspace.Position;

            TestHand rightHand = new TestHand(Handedness.Right);

            // Make sure the hand is in front of the camera
            yield return(rightHand.Show(Vector3.forward * 0.6f));

            rightHand.SetRotation(Quaternion.identity);

            TeleportPointer teleportPointer = rightHand.GetPointer <TeleportPointer>();

            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition - Vector3.forward * teleportPointer.strafeAmount, "Did not strafe to the expected position");

            teleportPointer.checkForFloorOnStrafe   = true;
            teleportPointer.adjustHeightOnStrafe    = true;
            teleportPointer.strafeAmount            = 1.0f;
            teleportPointer.maxHeightChangeOnStrafe = 0.5f;

            TestUtilities.PlayspaceToOriginLookingForward();
            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition, "Performed an invalid strafe");

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

            floor2.transform.position = new Vector3(0, -0.25f, -1.0f);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            TestUtilities.PlayspaceToOriginLookingForward();
            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition + new Vector3(0, 0.25f, -teleportPointer.strafeAmount), "Height did not change on strafe");

            floor2.transform.position = new Vector3(0, -0.75f, -1.0f);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            TestUtilities.PlayspaceToOriginLookingForward();
            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition + new Vector3(0, -0.25f, -teleportPointer.strafeAmount), "Height did not change on strafe");
        }
Ejemplo n.º 15
0
        public IEnumerator TestDefaultProfile()
        {
            PlayModeTestUtilities.Setup();

            TestHand hand = new TestHand(Handedness.Right);

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


            var allPointers = GetAllPointers();

            // https://nunit.org/docs/2.5.5/collectionConstraints.html
            Assert.That(allPointers, Has.No.InstanceOf(typeof(GGVPointer)));
            Assert.That(allPointers, Has.Some.InstanceOf(typeof(ShellHandRayPointer)));
        }
Ejemplo n.º 16
0
        public IEnumerator TestTeleportLayers()
        {
            var iss = PlayModeTestUtilities.GetInputSimulationService();

            // Create a floor and make sure it's below the camera
            var floor = GameObject.CreatePrimitive(PrimitiveType.Plane);

            floor.transform.position = -0.5f * Vector3.up;

            // Bring out the right hand and set it to the teleport gesture
            TestUtilities.PlayspaceToOriginLookingForward();
            float initialForwardPosition = MixedRealityPlayspace.Position.z;

            TestHand rightHand = new TestHand(Handedness.Right);

            // Make sure the hand is in front of the camera
            yield return(rightHand.Show(Vector3.forward * 0.6f));

            rightHand.SetRotation(Quaternion.identity);

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

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            TeleportPointer teleportPointer = rightHand.GetPointer <TeleportPointer>();

            teleportPointer.PrioritizedLayerMasksOverride = new LayerMask[1] {
                UnityEngine.Physics.AllLayers ^ (1 << LayerMask.NameToLayer("UI"))
            };

            floor.layer = LayerMask.NameToLayer("Default");
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.AreEqual(Physics.TeleportSurfaceResult.Valid, teleportPointer.TeleportSurfaceResult);

            floor.layer = LayerMask.NameToLayer("Ignore Raycast");
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.AreEqual(Physics.TeleportSurfaceResult.Invalid, teleportPointer.TeleportSurfaceResult);

            floor.layer = LayerMask.NameToLayer("UI");
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.AreEqual(Physics.TeleportSurfaceResult.None, teleportPointer.TeleportSurfaceResult);
        }
        public IEnumerator ScaleMinMax()
        {
            float minScale = 0.5f;
            float maxScale = 2f;

            var bbox         = InstantiateSceneAndDefaultBbox();
            var scaleHandler = bbox.EnsureComponent <MinMaxScaleConstraint>();

            scaleHandler.ScaleMinimum = minScale;
            scaleHandler.ScaleMaximum = maxScale;
            yield return(null);

            Vector3 initialScale = bbox.transform.localScale;

            const int numHandSteps = 1;

            Vector3  initialHandPosition = new Vector3(0, 0, 0.5f);
            var      frontRightCornerPos = bbox.ScaleCorners[3].transform.position; // front right corner is corner 3
            TestHand hand = new TestHand(Handedness.Right);

            // Hands grab object at initial position
            yield return(hand.Show(initialHandPosition));

            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint));

            yield return(hand.MoveTo(frontRightCornerPos, numHandSteps));

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

            // No change to scale yet
            Assert.AreEqual(initialScale, bbox.transform.localScale);

            // Move hands beyond max scale limit
            yield return(hand.MoveTo(new Vector3(scaleHandler.ScaleMaximum * 2, scaleHandler.ScaleMaximum * 2, 0) + frontRightCornerPos, numHandSteps));

            // Assert scale at max
            Assert.AreEqual(Vector3.one * scaleHandler.ScaleMaximum, bbox.transform.localScale);

            // Move hands beyond min scale limit
            yield return(hand.MoveTo(new Vector3(-scaleHandler.ScaleMinimum * 2, -scaleHandler.ScaleMinimum * 2, 0) + frontRightCornerPos, numHandSteps));

            // Assert scale at min
            Assert.AreEqual(Vector3.one * scaleHandler.ScaleMinimum, bbox.transform.localScale);

            GameObject.Destroy(bbox.gameObject);
            // Wait for a frame to give Unity a change to actually destroy the object
            yield return(null);
        }
        public IEnumerator GrabLayerMasksWithOverlap()
        {
            // Initialize hand
            var rightHand = new TestHand(Handedness.Right);

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

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

            var pointer = rightHand.GetPointer <SpherePointer>();

            Assert.IsNotNull(pointer, "Expected to find SpherePointer in the hand controller");
            Vector3 interactionEnabledPos = new Vector3(0.05f, 0, colliderSurfaceZ - pointer.SphereCastRadius);

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Initialize overlapRect
            overlapRect.SetActive(true);

            // Set the cube's layer to spatial mesh, which sphere pointer should be ignoring
            // assumption: layer 31 is the spatial mesh layer
            cube.SetLayerRecursively(31);
            yield return(null);

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Move hand to object, IsNearObject, IsInteractionEnabled should be true
            yield return(rightHand.MoveTo(interactionEnabledPos));

            Assert.True(CoreServices.InputSystem.FocusProvider.GetFocusedObject(pointer) == overlapRect, " the overlapping rectangle was not in focus");
            Assert.True(pointer.IsNearObject);
            Assert.True(pointer.IsInteractionEnabled);

            // Set cube's layer back to default
            // Set overlapRect's layer to spatial mesh, which sphere pointer should be ignoring
            // assumption: layer 31 is the spatial mesh layer
            overlapRect.SetLayerRecursively(31);
            cube.SetLayerRecursively(0);
            yield return(null);

            Assert.True(CoreServices.InputSystem.FocusProvider.GetFocusedObject(pointer) == cube, " the inner cube was not in focus");

            // Reinitialize the overlapRect
            overlapRect.SetLayerRecursively(0);
            overlapRect.SetActive(false);
        }
Ejemplo n.º 19
0
        private static IEnumerator MoveAround(bool moveHands, bool moveCamera, bool moveGaze)
        {
            if (moveHands)
            {
                var rightHand = new TestHand(Handedness.Right);

                yield return(rightHand.Show(new Vector3(0, 0, 0.5f)));

                yield return(rightHand.SetRotation(Quaternion.identity, 0));

                yield return(rightHand.MoveTo(new Vector3(0, 0, 2f), 40));

                yield return(rightHand.MoveTo(new Vector3(0, 0, 0.5f), 40));

                yield return(rightHand.SetRotation(Quaternion.AngleAxis(-90f, Vector3.forward), 40));

                yield return(rightHand.SetRotation(Quaternion.AngleAxis(90f, Vector3.forward), 40));

                yield return(rightHand.SetRotation(Quaternion.identity, 20));
            }

            if (moveCamera)
            {
                var camera = CameraCache.Main.transform;

                camera.rotation = Quaternion.identity;

                yield return(InterpRotation(camera, 0.5f, Quaternion.AngleAxis(-90f, Vector3.up)));

                yield return(InterpRotation(camera, 0.5f, Quaternion.AngleAxis(90f, Vector3.up)));

                yield return(InterpRotation(camera, 0.5f, Quaternion.identity));
            }

            if (moveGaze)
            {
                var gazeProvider = CoreServices.InputSystem.EyeGazeProvider;

                gazeProvider.UpdateEyeTrackingStatus(null, true);
                gazeProvider.UpdateEyeGaze(null, new Ray(Vector3.zero, Vector3.forward), DateTime.UtcNow);

                yield return(InterpGaze(gazeProvider, 0.5f, new Vector3(-1f, 0f, 1f).normalized));

                yield return(InterpGaze(gazeProvider, 0.5f, new Vector3(1f, 0f, 1f).normalized));

                yield return(InterpGaze(gazeProvider, 0.5f, Vector3.forward));
            }
        }
        public IEnumerator TestDisableFocusLockedObject()
        {
            TestUtilities.PlayspaceToOriginLookingForward();
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.AddComponent <ManipulationHandler>(); // Add focus handler so focus can lock
            cube.transform.position   = Vector3.right;
            cube.transform.localScale = Vector3.one * 0.2f;

            const int numHandSteps = 1;

            // No initial focus
            cube.transform.position = Vector3.forward;
            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(Vector3.forward * 0.5f));

            yield return(null);

            var handRayPointer = hand.GetPointer <ShellHandRayPointer>();

            Assert.IsNull(handRayPointer.Result.CurrentPointerTarget);

            // Focus lock cube
            yield return(hand.MoveTo(new Vector3(0.06f, -0.1f, 0.5f), numHandSteps));

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

            yield return(null);

            Assert.IsTrue(handRayPointer.IsFocusLocked);
            Assert.AreEqual(cube, handRayPointer.Result.CurrentPointerTarget);

            // Deactivate the cube
            cube.SetActive(false);
            yield return(null);

            Assert.IsFalse(handRayPointer.IsFocusLocked);
            Assert.IsNull(handRayPointer.Result.CurrentPointerTarget);

            // Reactivate the cube
            cube.SetActive(true);
            yield return(null);

            Assert.IsFalse(handRayPointer.IsFocusLocked);
            Assert.AreEqual(cube, handRayPointer.Result.CurrentPointerTarget);
        }
        public IEnumerator TestAssembleTouchNoSnapSlider()
        {
            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    = 100;

            // Set slider to not snap with touch
            slider.SnapToPosition = false;
            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.0f, 0, 1.00f);

            yield return(rightHand.Show(initialPos));

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

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

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

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

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

            yield return(rightHand.Hide());

            Assert.AreEqual(0.20f, slider.SliderValue, 0.005f);

            GameObject.Destroy(pinchSliderObject);
        }
Ejemplo n.º 22
0
        public IEnumerator TriggerButtonFarInteraction([ValueSource(nameof(PressableButtonsTestPrefabPaths))] string prefabFilename)
        {
            GameObject testButton = InstantiateDefaultPressableButton(prefabFilename);

            TestUtilities.PlayspaceToOriginLookingForward();

            Interactable interactableComponent = testButton.GetComponent <Interactable>();
            Button       buttonComponent       = testButton.GetComponent <Button>();

            Assert.IsTrue(interactableComponent != null || buttonComponent != null, "Depending on button type, there should be either an Interactable or a UnityUI Button on the control");

            var objectToMoveAndScale = testButton.transform;

            if (buttonComponent != null)
            {
                objectToMoveAndScale = testButton.transform.parent;
            }

            objectToMoveAndScale.position   += new Vector3(0f, 0.3f, 0.8f);
            objectToMoveAndScale.localScale *= 15f; // scale button up so it's easier to hit it with the far interaction pointer
            yield return(new WaitForFixedUpdate());

            yield return(null);

            bool buttonTriggered = false;

            var onClickEvent = (interactableComponent != null) ? interactableComponent.OnClick : buttonComponent.onClick;

            onClickEvent.AddListener(() =>
            {
                buttonTriggered = true;
            });

            TestHand hand = new TestHand(Handedness.Right);
            Vector3  initialHandPosition = new Vector3(0.05f, -0.05f, 0.3f); // orient hand so far interaction ray will hit button

            yield return(hand.Show(initialHandPosition));

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

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

            Assert.IsTrue(buttonTriggered, "Button did not get triggered with far interaction.");

            Object.Destroy(testButton);
            yield return(null);
        }
Ejemplo n.º 23
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());
        }
Ejemplo n.º 24
0
        public IEnumerator TestHL1Profile()
        {
            var hl1Profile = ScriptableObjectExtensions.GetAllInstances <MixedRealityToolkitConfigurationProfile>()
                             .FirstOrDefault(x => x.name.Equals(HoloLens1ProfileName));

            TestUtilities.InitializeMixedRealityToolkit(hl1Profile);

            TestHand hand = new TestHand(Handedness.Right);

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

            var allPointers = GetAllPointers();

            // https://nunit.org/docs/2.5.5/collectionConstraints.html
            Assert.That(allPointers, Has.Some.InstanceOf(typeof(GGVPointer)));
            Assert.That(allPointers, Has.No.InstanceOf(typeof(ShellHandRayPointer)));
        }
Ejemplo n.º 25
0
        public IEnumerator TestSpherePointerInsideGrabbable()
        {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.AddComponent <NearInteractionGrabbable>();
            var rightHand = new TestHand(Handedness.Right);

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

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

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

            Assert.IsNotNull(spherePointer, "Right hand does not have a sphere pointer");
            Assert.IsTrue(spherePointer.IsInteractionEnabled, "Sphere pointer should be enabled because it is near grabbable cube and visible, even if inside a giant cube.");
            GameObject.Destroy(cube);
        }
        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");
        }
        public IEnumerator TestDialogPrefabInitializations()
        {
            TestHand handRight = new TestHand(Handedness.Right);
            float    dialogDistance;

            handRight.Show(Vector3.zero);

            InstantiateFromPrefab("Test Dialog", "This is an example dialog", DialogButtonType.OK, true);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            // near distances determined by the Dialog.Open() function
            dialogDistance = dialogGameObject.transform.position.magnitude;
            Assert.AreEqual(dialogComponent.Result.Buttons, DialogButtonType.OK);
            Assert.AreEqual(dialogComponent.Result.Message, "This is an example dialog");
            Assert.AreEqual(dialogComponent.Result.Title, "Test Dialog");
            Assert.AreEqual(dialogComponent.Result.Buttons, DialogButtonType.OK);
            Assert.IsTrue(dialogDistance > 0.5f && dialogDistance < 1.0f);

            GameObject.Destroy(dialogGameObject);
            GameObject.Destroy(dialogComponent);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            // The dialog only supports displaying up to two options
            InstantiateFromPrefab("Test Dialog", "This is an example dialog", DialogButtonType.Yes | DialogButtonType.No, true);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            // near distances determined by the Dialog.Open() function
            dialogDistance = dialogGameObject.transform.position.magnitude;
            Assert.AreEqual(dialogComponent.Result.Buttons, DialogButtonType.Yes | DialogButtonType.No);
            Assert.IsTrue(dialogDistance > 0.5f && dialogDistance < 1.0f);

            GameObject.Destroy(dialogGameObject);
            GameObject.Destroy(dialogComponent);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            InstantiateFromPrefab("Test Dialog", "This is an example dialog", DialogButtonType.Yes | DialogButtonType.No, false);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            // near distances determined by the Dialog.Open() function
            dialogDistance = dialogGameObject.transform.position.magnitude;
            Assert.AreEqual(dialogComponent.Result.Buttons, DialogButtonType.Yes | DialogButtonType.No);
            Assert.IsTrue(dialogDistance > 1.0f && dialogDistance < 2.0f);

            GameObject.Destroy(dialogGameObject);
            GameObject.Destroy(dialogComponent);
        }
        public IEnumerator DisableObject()
        {
            float minScale = 0.5f;
            float maxScale = 2f;

            var bbox         = InstantiateSceneAndDefaultBbox();
            var scaleHandler = bbox.EnsureComponent <MinMaxScaleConstraint>();

            scaleHandler.ScaleMinimum = minScale;
            scaleHandler.ScaleMaximum = maxScale;
            yield return(null);

            Vector3 initialScale = bbox.transform.localScale;

            const int numHandSteps = 1;

            Vector3  initialHandPosition = new Vector3(0, 0, 0.5f);
            var      frontRightCornerPos = bbox.ScaleCorners[3].transform.position; // front right corner is corner 3
            TestHand hand = new TestHand(Handedness.Right);

            // Hands grab object at initial position
            yield return(hand.Show(initialHandPosition));

            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint));

            yield return(hand.MoveTo(frontRightCornerPos, numHandSteps));

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

            // Verify that scale works before deactivating
            yield return(hand.Move(Vector3.right * 0.2f, numHandSteps));

            Vector3 afterTransformScale = bbox.transform.localScale;

            Assert.AreNotEqual(initialScale, afterTransformScale);

            // Deactivate object and ensure that we don't scale
            bbox.gameObject.SetActive(false);
            yield return(null);

            bbox.gameObject.SetActive(true);
            yield return(hand.Move(Vector3.right * 0.2f, numHandSteps));

            Assert.AreEqual(afterTransformScale, bbox.transform.localScale);
        }
        public IEnumerator TestFocusEventConfiguration()
        {
            // Create an interactive cube
            InteractiveElement interactiveElement = CreateInteractiveCube();

            yield return(null);

            // The focus state is a state that is added by default
            InteractionState focusState = interactiveElement.GetState(focusStateName);

            yield return(null);

            // Get the event configuration for the focus state
            var eventConfiguration = interactiveElement.GetStateEvents <FocusEvents>(focusStateName);

            bool onFocusOn  = false;
            bool onFocusOff = false;

            eventConfiguration.OnFocusOn.AddListener((eventData) =>
            {
                onFocusOn = true;
            });

            eventConfiguration.OnFocusOff.AddListener((eventData) =>
            {
                onFocusOff = true;
            });

            // Create a new hand and initialize it with an object in focus
            var leftHand = new TestHand(Handedness.Left);

            yield return(ShowHandWithObjectInFocus(leftHand));

            // Check if OnFocusOn has fired
            Assert.True(onFocusOn);

            // Move the Hand out of focus
            yield return(MoveHandOutOfFocus(leftHand));

            // Check if OnFocusOn has fired
            Assert.True(onFocusOff);

            yield return(null);
        }
        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);
        }