public IEnumerator SetTarget() { // create cube without control var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = boundingBoxStartCenter; MixedRealityPlayspace.PerformTransformation( p => { p.position = Vector3.zero; p.LookAt(cube.transform.position); }); cube.transform.localScale = boundingBoxStartScale; // create another gameobject with boundscontrol attached var emptyGameObject = new GameObject("empty"); BoundingBox bbox = emptyGameObject.AddComponent <BoundingBox>(); // set target to cube bbox.Target = cube; bbox.Active = true; // front right corner is corner 3 var frontRightCornerPos = cube.transform.Find("rigRoot/corner_3").position; // grab corner and scale object Vector3 initialHandPosition = new Vector3(0, 0, 0.5f); int numSteps = 30; var delta = new Vector3(0.1f, 0.1f, 0f); TestHand hand = new TestHand(Handedness.Right); yield return(hand.Show(initialHandPosition)); yield return(hand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint)); yield return(hand.MoveTo(frontRightCornerPos, numSteps)); yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(hand.MoveTo(frontRightCornerPos + delta, numSteps)); var endBounds = cube.GetComponent <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"); Object.Destroy(emptyGameObject); Object.Destroy(cube); // Wait for a frame to give Unity a change to actually destroy the object yield return(null); }
public IEnumerator ZoomRotatedSlate() { // Configuring camera and hands to interact with rotated slate InstantiateFromPrefab(Vector3.right, Quaternion.LookRotation(Vector3.right)); MixedRealityPlayspace.PerformTransformation(p => p.Rotate(Vector3.up, 90)); yield return(null); // Right hand pinches slate TestHand handRight = new TestHand(Handedness.Right); yield return(handRight.Show(panZoom.transform.position + Vector3.forward * -0.1f + Vector3.right * -0.3f)); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Left hand pinches slate TestHand handLeft = new TestHand(Handedness.Left); yield return(handLeft.Show(panZoom.transform.position + Vector3.forward * 0.1f + Vector3.right * -0.3f)); yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Use both hands to zoom in yield return(handRight.Move(new Vector3(0f, 0f, -0.1f), 5)); yield return(handLeft.Move(new Vector3(0f, 0f, 0.1f), 5)); Assert.AreEqual(0.6, panZoom.CurrentScale, 0.1, "Rotated slate did not zoom in using near interaction"); // Reset slate and hands configuration panZoom.Reset(); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Open)); yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Open)); yield return(null); // Both hands touch slate yield return(handRight.MoveTo(panZoom.transform.position + Vector3.forward * -0.1f)); yield return(handLeft.MoveTo(panZoom.transform.position + Vector3.forward * 0.1f)); yield return(null); // Use both hands to zoom in yield return(handRight.Move(new Vector3(0f, 0f, -0.1f), 5)); yield return(handLeft.Move(new Vector3(0f, 0f, 0.1f), 5)); Assert.AreEqual(0.6, panZoom.CurrentScale, 0.1, "Rotated slate did not zoom in using far interaction"); yield return(handRight.Hide()); yield return(handLeft.Hide()); }
public IEnumerator 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 PrefabGGVZoom() { InstantiateFromPrefab(); PlayModeTestUtilities.SetHandSimulationMode(HandSimulationMode.Gestures); TestHand handRight = new TestHand(Handedness.Right); yield return(handRight.Show(new Vector3(0.0f, 0.0f, 0.6f))); TestHand handLeft = new TestHand(Handedness.Left); yield return(handLeft.Show(new Vector3(-0.1f, 0.0f, 0.6f))); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(handRight.Move(new Vector3(0.005f, 0.0f, 0.0f), 10)); yield return(handLeft.Move(new Vector3(-0.005f, 0.0f, 0.0f), 10)); Assert.AreEqual(0.5, panZoom.CurrentScale, 0.1, "slate did not zoom in using two ggv hands"); yield return(handRight.Hide()); yield return(handLeft.Hide()); }
/// <summary> /// Scroll a slate using GGV and ensure that the slate scrolls /// expected amount. Assumes panZoom has already been created. /// </summary> /// <param name="expectedScroll">The amount panZoom is expected to scroll</param> private IEnumerator RunGGVScrollTest(float expectedScroll) { var iss = PlayModeTestUtilities.GetInputSimulationService(); var oldSimMode = iss.ControllerSimulationMode; iss.ControllerSimulationMode = ControllerSimulationMode.HandGestures; Vector2 totalPanDelta = Vector2.zero; panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta); TestHand handRight = new TestHand(Handedness.Right); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(handRight.Show(Vector3.zero)); // Move requires a slower action (i.e. higher numSteps) in order to // achieve a reliable pan. yield return(handRight.Move(new Vector3(0.0f, -0.1f, 0f), 30)); Assert.AreEqual(expectedScroll, totalPanDelta.y, 0.1, "pan delta is not correct"); yield return(handRight.Hide()); iss.ControllerSimulationMode = oldSimMode; yield return(null); }
public IEnumerator TestTouchEvents() { interactable.gameObject.AddComponent <NearInteractionTouchableVolume>(); var touchReceiver = interactable.AddReceiver <InteractableOnTouchReceiver>(); bool didTouch = false; bool didUntouch = false; touchReceiver.OnTouchStart.AddListener(() => didTouch = true); touchReceiver.OnTouchEnd.AddListener(() => didUntouch = true); var testHand = new TestHand(Handedness.Right); yield return(testHand.Show(Vector3.forward)); yield return(testHand.SetGesture(ArticulatedHandPose.GestureId.Open)); yield return(testHand.MoveTo(interactable.transform.position)); yield return(testHand.MoveTo(Vector3.forward)); yield return(testHand.Hide()); Assert.True(didTouch, "Did not receive touch event"); Assert.True(didUntouch, "Did not receive touch end event"); }
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 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 SpherePointerPullbackDistance() { // Approximate distance covered by the pullback distance; Vector3 pullbackDelta = new Vector3(0, 0, 0.08f); var rightHand = new TestHand(Handedness.Right); // Show hand far enough from the test collider Vector3 idlePos = new Vector3(0.05f, 0, 1.0f); yield return(rightHand.Show(idlePos)); yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint)); var pointer = rightHand.GetPointer <SpherePointer>(); pointer.NearObjectSectorAngle = 360.0f; pointer.PullbackDistance = 0.08f; pointer.TryGetNearGraspPoint(out Vector3 graspPoint); // Orient the right hand so the grab axis is approximately aligned with the z axis Vector3 margin = new Vector3(0, 0, 0.001f); Vector3 nearObjectMargin = new Vector3(0, 0, 0.001f + (pointer.NearObjectSmoothingFactor + 1) * pointer.NearObjectRadius); Assert.IsNotNull(pointer, "Expected to find SpherePointer in the hand controller"); Vector3 nearObjectPos = new Vector3(0.05f, 0, colliderSurfaceZ - (pointer.NearObjectRadius)); Vector3 interactionEnabledPos = new Vector3(0.05f, 0, colliderSurfaceZ - pointer.SphereCastRadius); Assert.False(pointer.IsNearObject); Assert.False(pointer.IsInteractionEnabled); // Move hand closer to the collider to enable IsNearObject yield return(rightHand.MoveTo(nearObjectPos - margin, numFramesPerMove)); Assert.False(pointer.IsNearObject); Assert.False(pointer.IsInteractionEnabled); yield return(rightHand.MoveTo(nearObjectPos + margin, numFramesPerMove)); Assert.False(pointer.IsNearObject); Assert.False(pointer.IsInteractionEnabled); yield return(rightHand.MoveTo(nearObjectPos + margin + pullbackDelta, numFramesPerMove)); Assert.True(pointer.IsNearObject); Assert.False(pointer.IsInteractionEnabled); // Move hand back out to disable IsNearObject yield return(rightHand.MoveTo(nearObjectPos - nearObjectMargin, numFramesPerMove)); Assert.False(pointer.IsNearObject); Assert.False(pointer.IsInteractionEnabled); yield return(rightHand.MoveTo(idlePos, numFramesPerMove)); Assert.False(pointer.IsNearObject); Assert.False(pointer.IsInteractionEnabled); }
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 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); }
public IEnumerator ManipulationHandlerRotateHeadGGV() { TestUtilities.PlayspaceToOriginLookingForward(); // Switch to Gestures var iss = PlayModeTestUtilities.GetInputSimulationService(); var oldIsp = iss.InputSimulationProfile; var isp = ScriptableObject.CreateInstance <MixedRealityInputSimulationProfile>(); isp.HandSimulationMode = HandSimulationMode.Gestures; iss.InputSimulationProfile = isp; // set up cube with manipulation handler var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube); testObject.transform.localScale = Vector3.one * 0.2f; Vector3 initialObjectPosition = new Vector3(0f, 0f, 1f); Quaternion initialObjectRotation = testObject.transform.rotation; testObject.transform.position = initialObjectPosition; var manipHandler = testObject.AddComponent <ManipulationHandler>(); manipHandler.HostTransform = testObject.transform; manipHandler.SmoothingActive = false; Vector3 originalHandPosition = new Vector3(0, 0, 0.5f); TestHand hand = new TestHand(Handedness.Right); const int numHandSteps = 1; // Grab cube yield return(hand.Show(originalHandPosition)); yield return(null); yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Rotate Head and readjust hand int numRotations = 10; for (int i = 0; i < numRotations; i++) { MixedRealityPlayspace.Transform.Rotate(Vector3.up, 180 / numRotations); yield return(hand.MoveTo(originalHandPosition, numHandSteps)); yield return(null); // Test Object hasn't moved TestUtilities.AssertAboutEqual(initialObjectPosition, testObject.transform.position, "Object moved while rotating head"); TestUtilities.AssertAboutEqual(initialObjectRotation, testObject.transform.rotation, "Object rotated while rotating head", 0.25f); } // Restore the input simulation profile iss.InputSimulationProfile = oldIsp; yield return(null); }
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"); // Switch to hand gestures var iss = PlayModeTestUtilities.GetInputSimulationService(); var oldSimMode = iss.ControllerSimulationMode; iss.ControllerSimulationMode = ControllerSimulationMode.HandGestures; 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", 0.02f); TestUtilities.AssertAboutEqual(endBounds.size, Vector3.one * .561f, "endBounds incorrect size", 0.02f); Object.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 iss.ControllerSimulationMode = oldSimMode; yield return(null); }
public IEnumerator ArticulatedCursorState() { var inputSystem = PlayModeTestUtilities.GetInputSystem(); // Show hand far enough from the test collider so the cursor is not on it var hand = new TestHand(Handedness.Right); Vector3 offObjectPos = TestUtilities.PositionRelativeToPlayspace(new Vector3(0.05f, 0, 1.0f)); yield return(hand.Show(offObjectPos)); VerifyCursorStateFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorStateEnum.Interact); // Move hand closer to the collider so the cursor is on it Vector3 onObjectPos = TestUtilities.PositionRelativeToPlayspace(new Vector3(0.05f, 0, 1.5f)); yield return(hand.MoveTo(onObjectPos, numFramesPerMove)); VerifyCursorStateFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorStateEnum.InteractHover); // Trigger pinch yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch)); VerifyCursorStateFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorStateEnum.Select); // Release pinch yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Open, false)); VerifyCursorStateFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorStateEnum.Release); // Wait to transition back to InteractHover yield return(null); VerifyCursorStateFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorStateEnum.InteractHover); // Move back so the cursor is no longer on the object yield return(hand.MoveTo(offObjectPos, numFramesPerMove)); VerifyCursorStateFromPointers(inputSystem.FocusProvider.GetPointers <ShellHandRayPointer>(), CursorStateEnum.Interact); yield return(null); }
public IEnumerator ConstrainScaleApparentSize() { 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)); testObject.transform.rotation = CameraCache.Main.transform.rotation; var manipHandler = testObject.AddComponent <ObjectManipulator>(); manipHandler.HostTransform = testObject.transform; manipHandler.SmoothingFar = false; manipHandler.ManipulationType = ManipulationHandFlags.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 = true; 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 = 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)); // Move and test that still same distance from head yield return(hand.Move(TestUtilities.DirectionRelativeToPlayspace(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 TestRiggedHand() { // Initialize hand var rightHand = new TestHand(Handedness.Right); yield return(rightHand.Show(Vector3.zero)); RiggedHandVisualizer handVisualizer = GameObject.FindObjectOfType <RiggedHandVisualizer>().GetComponent <RiggedHandVisualizer>(); yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open)); Assert.IsTrue(handVisualizer.HandRenderer.sharedMaterial.GetFloat(handVisualizer.PinchStrengthMaterialProperty) < 0.5f); yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Grab)); Assert.IsTrue(handVisualizer.HandRenderer.sharedMaterial.GetFloat(handVisualizer.PinchStrengthMaterialProperty) > 0.5f); yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint)); Assert.IsTrue(handVisualizer.HandRenderer.sharedMaterial.GetFloat(handVisualizer.PinchStrengthMaterialProperty) < 0.5f); }
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 Prefab_RayScroll() { InstantiateFromPrefab(Vector3.forward); Vector2 totalPanDelta = Vector2.zero; panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta); TestHand h = new TestHand(Handedness.Right); Vector3 screenPoint = CameraCache.Main.ViewportToScreenPoint(new Vector3(0.5f, 0.25f, 0.5f)); yield return(h.Show(CameraCache.Main.ScreenToWorldPoint(screenPoint))); yield return(h.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(h.Move(new Vector3(0, -0.05f, 0), 10)); yield return(h.SetGesture(ArticulatedHandPose.GestureId.Open)); Assert.AreEqual(0.1, totalPanDelta.y, 0.05, "pan delta is not correct"); yield return(h.Hide()); }
/// <summary> /// Scroll contents to the limit in the specified direction /// </summary> /// <param name="direction">Scroll direction</param> private IEnumerator ScrollToLimit(Vector3 direction) { TestHand handRight = new TestHand(Handedness.Right); yield return(handRight.Show(Vector3.zero)); Vector3 screenPoint = CameraCache.Main.ViewportToScreenPoint(new Vector3(0.5f, 0.0f, 0.5f)); var moveDelta = -0.5f * direction; for (var i = 0; i < 3; i++) { yield return(handRight.MoveTo(CameraCache.Main.ScreenToWorldPoint(screenPoint))); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(handRight.Move(moveDelta, 10)); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Open)); } yield return(handRight.Hide()); }
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); }
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); }
private IEnumerator DirectPinchAndMoveSlider(PinchSlider slider, float toSliderValue) { Debug.Log($"moving hand to value {toSliderValue}"); var rightHand = new TestHand(Handedness.Right); Vector3 initialPos = new Vector3(0.05f, 0, 1.0f); yield return(rightHand.Show(initialPos)); yield return(rightHand.MoveTo(slider.ThumbRoot.transform.position)); yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch)); if (!(toSliderValue >= 0 && toSliderValue <= 1)) { throw new System.ArgumentException("toSliderValue must be between 0 and 1"); } yield return(rightHand.MoveTo(Vector3.Lerp(slider.SliderStartPosition, slider.SliderEndPosition, toSliderValue))); yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open)); yield return(rightHand.Hide()); }
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 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 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); }
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 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 PrefabScrollUpZoomOutLimited() { var maxPanHorizontal = 4f; var maxPanVertical = 4f; InstantiatePanLimitedSlateFromPrefab(maxPanHorizontal: maxPanHorizontal, maxPanVertical: maxPanVertical); yield return(ScrollToLimit(new Vector3(1, 1, 0))); // Right hand pinches slate TestHand handRight = new TestHand(Handedness.Right); yield return(handRight.MoveTo(panZoom.transform.position + Vector3.forward * -0.5f + Vector3.right * 0.2f)); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Left hand pinches slate TestHand handLeft = new TestHand(Handedness.Left); yield return(handLeft.Show(panZoom.transform.position + Vector3.forward * -0.5f + Vector3.right * -0.2f)); yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Use both hands to zoom out yield return(handLeft.Move(new Vector3(0.1f, 0.1f, 0f), 10)); var uvs = new List <Vector2>(); meshFilter.mesh.GetUVs(0, uvs); #if UNITY_2019_1_OR_NEWER Assert.AreEqual(maxPanHorizontal * material.mainTextureScale.x, uvs[3].x, 0.05, "mesh uv is not correct"); Assert.AreEqual(maxPanVertical * material.mainTextureScale.y, uvs[3].y, 0.05, "mesh uv is not correct"); #else Assert.AreEqual(maxPanHorizontal * material.mainTextureScale.x, uvs[1].x, 0.05, "mesh uv is not correct"); Assert.AreEqual(maxPanVertical * material.mainTextureScale.y, uvs[1].y, 0.05, "mesh uv is not correct"); #endif yield return(handRight.Hide()); yield return(handLeft.Hide()); }
/// <summary> /// Scroll a slate using GGV and ensure that the slate scrolls /// expected amount. Assumes panZoom has already been created. /// </summary> /// <param name="expectedScroll">The amount panZoom is expected to scroll</param> private IEnumerator RunGGVScrollTest(float expectedScroll) { PlayModeTestUtilities.SetHandSimulationMode(HandSimulationMode.Gestures); Vector2 totalPanDelta = Vector2.zero; panZoom.PanUpdated.AddListener((hpd) => totalPanDelta += hpd.PanDelta); TestHand h = new TestHand(Handedness.Right); yield return(h.SetGesture(ArticulatedHandPose.GestureId.Pinch)); yield return(h.Show(Vector3.zero)); yield return(h.Move(new Vector3(0.0f, -0.1f, 0f))); Assert.AreEqual(expectedScroll, totalPanDelta.y, 0.05, "pan delta is not correct"); yield return(h.Hide()); }
public IEnumerator PrefabZoomOutWithoutJitter() { var maxPan = 1.2f; InstantiatePanLimitedSlateFromPrefab(maxPanHorizontal: maxPan, maxPanVertical: maxPan); yield return(ScrollToLimit(new Vector3(-1, -1, 0))); // Right hand pinches slate TestHand handRight = new TestHand(Handedness.Right); yield return(handRight.MoveTo(panZoom.transform.position + Vector3.forward * -0.5f + Vector3.right * 0.2f)); yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Left hand pinches slate TestHand handLeft = new TestHand(Handedness.Left); yield return(handLeft.Show(panZoom.transform.position + Vector3.forward * -0.5f + Vector3.right * -0.2f)); yield return(handLeft.SetGesture(ArticulatedHandPose.GestureId.Pinch)); // Use both hands to zoom out var previousUvs = new List <Vector2>(); meshFilter.mesh.GetUVs(0, previousUvs); for (var i = 0; i < 10; i++) { yield return(handLeft.Move(new Vector3(0f, 0.02f, 0f), 1)); var uvs = new List <Vector2>(); meshFilter.mesh.GetUVs(0, uvs); for (int j = 0; j < uvs.Count; j++) { Assert.AreEqual(previousUvs[j].x, uvs[j].x, 0.05, "mesh is jittering"); Assert.AreEqual(previousUvs[j].y, uvs[j].y, 0.05, "mesh is jittering"); } previousUvs = uvs; } }