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); }
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); }
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"); }
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); }
/// <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); }
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"); }
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))); }
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); }
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); }
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); }
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 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))); }
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); }