예제 #1
0
        public IEnumerator ScaleMinMax()
        {
            float minScale = 0.5f;
            float maxScale = 2f;

            BoundsControl boundsControl = InstantiateSceneAndDefaultBoundsControl();

            yield return(VerifyInitialBoundsCorrect(boundsControl));

            var scaleHandler = boundsControl.EnsureComponent <MinMaxScaleConstraint>();

            scaleHandler.ScaleMinimum = minScale;
            scaleHandler.ScaleMaximum = maxScale;
            boundsControl.RegisterTransformScaleHandler(scaleHandler);

            Vector3 initialScale = boundsControl.transform.localScale;

            const int numHandSteps = 1;

            Vector3  initialHandPosition = new Vector3(0, 0, 0.5f);
            var      frontRightCornerPos = boundsControl.gameObject.transform.Find("rigRoot/corner_3").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, boundsControl.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, boundsControl.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, boundsControl.transform.localScale);

            GameObject.Destroy(boundsControl.gameObject);
            // Wait for a frame to give Unity a change to actually destroy the object
            yield return(null);
        }
예제 #2
0
        public IEnumerator InputSimulationArticulatedHandNearGrabbable()
        {
            var iss = PlayModeTestUtilities.GetInputSimulationService();

            TestUtilities.PlayspaceToOriginLookingForward();
            yield return(null);

            // No hands, default cursor should be visible
            Assert.IsTrue(CoreServices.InputSystem.GazeProvider.GazeCursor.IsVisible, "Head gaze cursor should be visible");

            // Begin right hand manipulation
            KeyInputSystem.PressKey(iss.InputSimulationProfile.ToggleRightHandKey);
            yield return(null);

            KeyInputSystem.AdvanceSimulation();
            yield return(null);

            // Make sure right hand is tracked
            Assert.True(iss.HandDataRight.IsTracked);

            TestHand hand = new TestHand(Handedness.Right);

            // Head cursor invisible when hand is tracked
            Assert.IsFalse(CoreServices.InputSystem.GazeProvider.GazeCursor.IsVisible, "Eye gaze cursor should not be visible");
            // Hand ray visible
            var handRayPointer = hand.GetPointer <ShellHandRayPointer>();

            Assert.True(handRayPointer.IsActive, "Hand ray not active");

            // Create grabbable cube
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.AddComponent <NearInteractionGrabbable>();
            cube.transform.localScale = Vector3.one * 0.3f;
            cube.transform.position   = new Vector3(-0.2f, 0.2f, 0.6f);
            yield return(null);

            // Grab pointer is near grabbable
            var grabPointer = hand.GetPointer <SpherePointer>();

            Assert.IsTrue(grabPointer.isActiveAndEnabled, "grab pointer is enabled");
            Assert.IsTrue(grabPointer.IsNearObject, "Grab pointer should be near a grabbable");

            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            // Head cursor invisible when grab pointer is near grabbable
            Assert.IsFalse(CoreServices.InputSystem.GazeProvider.GazeCursor.IsVisible, "Eye gaze cursor should not be visible");
            // Hand ray invisible when grab pointer is near grabbable
            Assert.True(!handRayPointer.IsActive, "Hand ray not active");
        }
예제 #3
0
        public IEnumerator RotateViaHololens1Interaction()
        {
            BoundsControl control = InstantiateSceneAndDefaultBoundsControl();

            yield return(VerifyInitialBoundsCorrect(control));

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

            // move camera to look at rotation sphere
            CameraCache.Main.transform.LookAt(new Vector3(0.248f, 0.001f, 1.226f)); // rotation sphere front right

            var startHandPos = new Vector3(0.364f, -0.157f, 0.437f);
            var endPoint     = new Vector3(0.141f, -0.163f, 0.485f);

            // perform tab with hand and drag to left
            TestHand rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(startHandPos));

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

            yield return(rightHand.MoveTo(endPoint));

            // make sure only Y axis rotation was performed and no other transform values have changed
            Vector3 expectedPosition = new Vector3(0f, 0f, 1.5f);
            Vector3 expectedSize     = Vector3.one * 0.5f;
            float   angle;
            Vector3 axis = new Vector3();

            control.transform.rotation.ToAngleAxis(out angle, out axis);
            float   expectedAngle = 86f;
            float   angleDiff     = Mathf.Abs(expectedAngle - angle);
            Vector3 expectedAxis  = new Vector3(0f, 1f, 0f);

            TestUtilities.AssertAboutEqual(axis, expectedAxis, "Rotated around wrong axis");
            Assert.IsTrue(angleDiff <= 1f, "cube didn't rotate as expected");
            TestUtilities.AssertAboutEqual(control.transform.position, expectedPosition, "cube moved while rotating");
            TestUtilities.AssertAboutEqual(control.transform.localScale, expectedSize, "cube scaled while rotating");

            GameObject.Destroy(control.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);
        }
        /// <summary>
        /// This tests far, medium and close proximity scaling on scale handles by moving the test hand in the corresponding distance ranges
        /// </summary>
        /// <param name="bbox">Bounds Control to test on</param>
        /// <param name="hand">Test hand to use for testing proximity to handle</param>
        private IEnumerator TestCurrentProximityConfiguration(BoundsControl bbox, TestHand hand, string testDescription)
        {
            // get config and scaling handle
            ScaleHandlesConfiguration scaleHandleConfig = bbox.ScaleHandlesConfiguration;
            Vector3   defaultHandleSize     = Vector3.one * scaleHandleConfig.HandleSize;
            Transform scaleHandle           = bbox.gameObject.transform.Find("rigRoot/corner_3");
            Transform proximityScaledVisual = scaleHandle.GetChild(0)?.GetChild(0);
            var       frontRightCornerPos   = scaleHandle.position;
            // check far scale applied
            ProximityEffectConfiguration proximityConfig = bbox.HandleProximityEffectConfiguration;
            Vector3 expectedFarScale = defaultHandleSize * proximityConfig.FarScale;

            Assert.AreEqual(proximityScaledVisual.localScale, expectedFarScale, testDescription + " - Proximity far scale wasn't applied to handle");

            // move into medium range and check if scale was applied
            Vector3 mediumProximityTestDist = frontRightCornerPos;

            mediumProximityTestDist.x += proximityConfig.ObjectMediumProximity;
            yield return(hand.MoveTo(mediumProximityTestDist));

            Vector3 expectedMediumScale = defaultHandleSize * proximityConfig.MediumScale;

            Assert.AreEqual(proximityScaledVisual.localScale, expectedMediumScale, testDescription + " - Proximity medium scale wasn't applied to handle");

            // move into close scale range and check if scale was applied
            Vector3 closeProximityTestDir = frontRightCornerPos;

            closeProximityTestDir.x += proximityConfig.ObjectCloseProximity;
            yield return(hand.MoveTo(closeProximityTestDir));

            Vector3 expectedCloseScale = defaultHandleSize * proximityConfig.CloseScale;

            Assert.AreEqual(proximityScaledVisual.localScale, expectedCloseScale, testDescription + " - Proximity close scale wasn't applied to handle");

            // move out of close scale again - should fall back to medium proximity
            closeProximityTestDir = mediumProximityTestDist;
            yield return(hand.MoveTo(closeProximityTestDir));

            Assert.AreEqual(proximityScaledVisual.localScale, expectedMediumScale, testDescription + " - Proximity medium scale wasn't applied to handle");

            // move out of medium proximity and check if far scaling is applied
            mediumProximityTestDist = Vector3.zero;
            yield return(hand.MoveTo(mediumProximityTestDist));

            Assert.AreEqual(proximityScaledVisual.localScale, expectedFarScale, testDescription + " - Proximity far scale wasn't applied to handle");

            yield return(null);
        }
예제 #5
0
        public IEnumerator ScaleViaHoloLens1Interaction()
        {
            BoundsControl boundsControl = InstantiateSceneAndDefaultBoundsControl();

            yield return(VerifyInitialBoundsCorrect(boundsControl));

            BoxCollider boxCollider = boundsControl.GetComponent <BoxCollider>();

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

            CameraCache.Main.transform.LookAt(boundsControl.gameObject.transform.Find("rigRoot/corner_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 = boxCollider.bounds;

            TestUtilities.AssertAboutEqual(afterPinchbounds.center, boundsControlStartCenter, "boundsControl incorrect center after pinch");
            TestUtilities.AssertAboutEqual(afterPinchbounds.size, boundsControlStartScale, "boundsControl incorrect size after pinch");

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

            yield return(rightHand.Move(delta));

            var     endBounds      = boxCollider.bounds;
            Vector3 expectedCenter = new Vector3(0.033f, 0.033f, 1.467f);
            Vector3 expectedSize   = Vector3.one * .567f;

            TestUtilities.AssertAboutEqual(endBounds.center, expectedCenter, "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, expectedSize, "endBounds incorrect size", 0.02f);

            GameObject.Destroy(boundsControl.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 DisableEnableInputSystem()
        {
            yield return(null);

            TestContext.Out.WriteLine("Disable the input system");
            CoreServices.InputSystem.Disable();

            yield return(new WaitForSeconds(2));

            TestContext.Out.WriteLine("Enable the input system");
            CoreServices.InputSystem.Enable();

            TestContext.Out.WriteLine("Display a test hand");
            TestHand rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(new Vector3(-0.3f, -0.1f, 0.5f)));
        }
예제 #7
0
        public IEnumerator RotateViaNearInteraction()
        {
            BoundsControl boundsControl = InstantiateSceneAndDefaultBoundsControl();

            yield return(VerifyInitialBoundsCorrect(boundsControl));

            Vector3 pointOnCube = new Vector3(-0.033f, -0.129f, 0.499f);                 // position where hand ray points on center of the test cube
            Vector3 rightFrontRotationHandlePoint = new Vector3(0.248f, 0.001f, 1.226f); // position of hand for far interacting with front right rotation sphere
            Vector3 endRotation = new Vector3(-0.284f, -0.001f, 1.23f);                  // end position for far interaction scaling

            TestHand hand = new TestHand(Handedness.Left);

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

            yield return(hand.Show(pointOnCube));

            // grab front right rotation point
            yield return(hand.MoveTo(rightFrontRotationHandlePoint));

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

            // move to left side of cube
            yield return(hand.MoveTo(endRotation));

            // make sure rotation is as expected and no other transform values have been modified through this
            Vector3 expectedPosition = new Vector3(0f, 0f, 1.5f);
            Vector3 expectedSize     = Vector3.one * 0.5f;
            float   angle;
            Vector3 axis = new Vector3();

            boundsControl.transform.rotation.ToAngleAxis(out angle, out axis);
            float   expectedAngle = 92f;
            float   angleDiff     = Mathf.Abs(expectedAngle - angle);
            Vector3 expectedAxis  = new Vector3(0f, 1f, 0f);

            TestUtilities.AssertAboutEqual(axis, expectedAxis, "Rotated around wrong axis");
            Assert.IsTrue(angleDiff <= 1f, "cube didn't rotate as expected");
            TestUtilities.AssertAboutEqual(boundsControl.transform.position, expectedPosition, "cube moved while rotating");
            TestUtilities.AssertAboutEqual(boundsControl.transform.localScale, expectedSize, "cube scaled while rotating");

            GameObject.Destroy(boundsControl.gameObject);
            // Wait for a frame to give Unity a change to actually destroy the object
            yield return(null);
        }
예제 #8
0
        public IEnumerator DisableObject()
        {
            var boundsControl = InstantiateSceneAndDefaultBoundsControl();

            yield return(VerifyInitialBoundsCorrect(boundsControl));

            Vector3 initialScale = boundsControl.transform.localScale;

            const int numHandSteps = 1;

            Vector3  initialHandPosition = new Vector3(0, 0, 0.5f);
            var      frontRightCornerPos = boundsControl.gameObject.transform.Find("rigRoot/corner_3").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 = boundsControl.transform.localScale;

            Assert.AreNotEqual(initialScale, afterTransformScale);

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

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

            Assert.AreEqual(afterTransformScale, boundsControl.transform.localScale);
        }
예제 #9
0
        public IEnumerator ManipulateViaAppBarFarInteraction()
        {
            // create cube with bounds control and app bar
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.transform.position = boundsControlStartCenter;
            BoundsControl boundsControl = cube.AddComponent <BoundsControl>();

            TestUtilities.PlayspaceToOriginLookingForward();

            boundsControl.transform.localScale = boundsControlStartScale;
            Object appBarPrefab = AssetDatabase.LoadAssetAtPath(appBarPrefabLink, typeof(Object));

            Assert.IsNotNull(appBarPrefab, "Couldn't load app bar prefab from assetdatabase");
            GameObject appBarGameObject = Object.Instantiate(appBarPrefab) as GameObject;

            Assert.IsNotNull(appBarGameObject, "Couldn't instantiate appbar prefab");
            appBarGameObject.SetActive(false);
            AppBar appBar = appBarGameObject.GetComponent <AppBar>();

            Assert.IsNotNull(appBar, "Couldn't find AppBar component in prefab");

            appBarGameObject.transform.localScale = Vector3.one * 5.0f;
            appBar.Target = boundsControl;
            appBarGameObject.SetActive(true);

            // manipulation coords
            Vector3 rightCornerInteractionPoint = new Vector3(0.184f, 0.078f, 0.79f); // position of hand for far interacting with front right corner
            Vector3 pointOnCube            = new Vector3(-0.033f, -0.129f, 0.499f);   // position where hand ray points on center of the test cube
            Vector3 scalePoint             = new Vector3(0.165f, 0.267f, 0.794f);     // end position for far interaction scaling
            Vector3 appBarButtonStart      = new Vector3(-0.028f, -0.263f, 0.499f);   // location of hand for interaction with the app bar manipulation button after scene setup
            Vector3 appBarButtonAfterScale = new Vector3(0.009f, -0.255f, 0.499f);    // location of the hand for interaction with the app bar manipulation button after scaling

            // first test to interact with the cube without activating the app bar
            // this shouldn't scale the cube
            TestHand hand = new TestHand(Handedness.Left);

            yield return(hand.Show(pointOnCube)); //initially make sure that hand ray is pointed on cube surface so we won't go behind the cube with our ray

            yield return(hand.MoveTo(rightCornerInteractionPoint));

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

            yield return(hand.MoveTo(scalePoint));

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

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

            TestUtilities.AssertAboutEqual(endBounds.center, boundsControlStartCenter, "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, boundsControlStartScale, "endBounds incorrect size");

            // now activate the bounds control via app bar
            yield return(hand.MoveTo(appBarButtonStart));

            yield return(hand.Click());

            // check if we can scale the box now
            yield return(hand.MoveTo(pointOnCube));                 // make sure our hand ray is on the cube again before moving to the scale corner

            yield return(hand.MoveTo(rightCornerInteractionPoint)); // move to scale corner

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

            yield return(hand.MoveTo(scalePoint));

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

            endBounds = boundsControl.GetComponent <BoxCollider>().bounds;
            Vector3 expectedScaleCenter = new Vector3(0.0453f, 0.0453f, 1.455f);
            Vector3 expectedScaleSize   = Vector3.one * 0.59f;

            TestUtilities.AssertAboutEqual(endBounds.center, expectedScaleCenter, "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, expectedScaleSize, "endBounds incorrect size");

            // deactivate the bounds control via app bar
            yield return(hand.MoveTo(appBarButtonAfterScale));

            yield return(hand.Click());

            // check if we can scale the box - box shouldn't scale
            Vector3 startLocationScaleToOriginal = new Vector3(0.181f, 0.013f, 0.499f);
            Vector3 endLocationScaleToOriginal   = new Vector3(0.121f, -0.052f, 0.499f);

            yield return(hand.MoveTo(pointOnCube));                  // make sure our hand ray is on the cube again before moving to the scale corner

            yield return(hand.MoveTo(startLocationScaleToOriginal)); // move to scale corner

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

            yield return(hand.MoveTo(endLocationScaleToOriginal));

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

            endBounds = boundsControl.GetComponent <BoxCollider>().bounds;
            TestUtilities.AssertAboutEqual(endBounds.center, expectedScaleCenter, "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, expectedScaleSize, "endBounds incorrect size");

            // activate the bounds control via app bar
            yield return(hand.MoveTo(appBarButtonAfterScale));

            yield return(hand.Click());

            // try again to scale the box back
            yield return(hand.MoveTo(pointOnCube));                  // make sure our hand ray is on the cube again before moving to the scale corner

            yield return(hand.MoveTo(startLocationScaleToOriginal)); // move to scale corner

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

            yield return(hand.MoveTo(endLocationScaleToOriginal));

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

            endBounds = boundsControl.GetComponent <BoxCollider>().bounds;
            TestUtilities.AssertAboutEqual(endBounds.center, boundsControlStartCenter, "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, boundsControlStartScale, "endBounds incorrect size");

            yield return(null);
        }
예제 #10
0
        public IEnumerator ProximityOnScaleHandles()
        {
            var boundsControl = InstantiateSceneAndDefaultBoundsControl();

            yield return(VerifyInitialBoundsCorrect(boundsControl));

            // 1. test no proximity scaling active per default
            ScaleHandlesConfiguration scaleHandleConfig = boundsControl.ScaleHandlesConfiguration;
            Vector3 defaultHandleSize = Vector3.one * scaleHandleConfig.HandleSize;

            Vector3 initialHandPosition = new Vector3(0, 0, 0f);
            // this is specific to scale handles
            Transform scaleHandle           = boundsControl.gameObject.transform.Find("rigRoot/corner_3");
            Transform proximityScaledVisual = scaleHandle.GetChild(0)?.GetChild(0);
            var       frontRightCornerPos   = scaleHandle.position; // front right corner is corner

            Assert.IsNotNull(proximityScaledVisual, "Couldn't get visual gameobject for scale handle");
            Assert.IsTrue(proximityScaledVisual.name == "visuals", "scale visual has unexpected name");

            yield return(null);

            // verify no proximity scaling applied per default
            Assert.AreEqual(proximityScaledVisual.localScale, defaultHandleSize, "Handle was scaled even though proximity effect wasn't active");
            TestHand hand         = new TestHand(Handedness.Left);
            Vector3  initialScale = boundsControl.transform.localScale;

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

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

            yield return(hand.MoveTo(frontRightCornerPos));

            yield return(null);

            // we're in poximity scaling range - check if proximity scaling wasn't applied
            Assert.AreEqual(proximityScaledVisual.localScale, defaultHandleSize, "Handle was scaled even though proximity effect wasn't active");

            //// reset hand
            yield return(hand.MoveTo(initialHandPosition));

            // 2. enable proximity scaling and test defaults
            ProximityEffectConfiguration proximityConfig = boundsControl.HandleProximityEffectConfiguration;

            proximityConfig.ProximityEffectActive = true;
            proximityConfig.CloseGrowRate         = 1.0f;
            proximityConfig.MediumGrowRate        = 1.0f;
            proximityConfig.FarGrowRate           = 1.0f;
            boundsControl.CreateRig();
            yield return(null); // wait so rig gameobjects get recreated

            yield return(TestCurrentProximityConfiguration(boundsControl, hand, "Defaults"));

            // reset hand
            yield return(hand.MoveTo(initialHandPosition));

            // 3. now test custom configuration is applied during runtime
            proximityConfig.CloseScale  = 4.0f;
            proximityConfig.MediumScale = 3.0f;
            proximityConfig.FarScale    = 2.0f;

            proximityConfig.ObjectMediumProximity = 0.2f;
            proximityConfig.ObjectCloseProximity  = 0.1f;

            boundsControl.CreateRig();
            yield return(null); // wait so rig gameobjects get recreated

            yield return(TestCurrentProximityConfiguration(boundsControl, hand, "Custom runtime config max"));
        }