/// <summary> /// Override base behavior to align the cursor with the finger, else perform normal cursor transformations. /// </summary> protected override void UpdateCursorTransform() { IMixedRealityNearPointer nearPointer = (IMixedRealityNearPointer)Pointer; // When the pointer has a IMixedRealityNearPointer interface we don't call base.UpdateCursorTransform because we handle // cursor transformation a bit differently. if (nearPointer != null) { float deltaTime = UseUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime; Vector3 indexFingerPosition; Quaternion indexFingerRotation; // If we are unable to get the hand joint default to the Near Pointer's position and rotation if (!TryGetJoint(TrackedHandJoint.IndexTip, out indexFingerPosition, out indexFingerRotation)) { indexFingerPosition = Pointer.Position; indexFingerRotation = Pointer.Rotation; } Vector3 indexKnucklePosition; // If we are unable to get the hand joint default to the Near Pointer's position if (!TryGetJoint(TrackedHandJoint.IndexKnuckle, out indexKnucklePosition, out _)) // knuckle rotation not used { indexKnucklePosition = Pointer.Position; } float distance = float.MaxValue; Vector3 surfaceNormal = Vector3.zero; bool surfaceNormalFound = false; bool showVisual = true; bool nearPokeable = nearPointer.IsNearObject; // Show the cursor if we are deemed to be near an object or if it is near a grabbable object if (nearPokeable) { // If the pointer is near an object translate the primary ring to the index finger tip and rotate to surface normal if close. // The secondary ring should be hidden. if (!nearPointer.TryGetDistanceToNearestSurface(out distance)) { distance = float.MaxValue; } surfaceNormalFound = nearPointer.TryGetNormalToNearestSurface(out surfaceNormal); } else { // If the pointer is near a grabbable object position and rotate the ring to the default, // else hide it. bool nearGrabbable = checkForGrabbables && IsNearGrabbableObject(); // There is no good way to get the distance of the nearest grabbable object at the moment, so we either return the MinVisibleRingDistance or 1 (invisible). distance = nearGrabbable ? MinVisibleRingDistance : 1.0f; // Only show the visual if we are near a grabbable showVisual = nearGrabbable; surfaceNormalFound = false; } if (indexFingerRingRenderer != null) { TranslateToFinger(indexFingerRingRenderer.transform, deltaTime, indexFingerPosition, indexKnucklePosition); if ((distance < alignWithSurfaceDistance) && surfaceNormalFound) { RotateToSurfaceNormal(indexFingerRingRenderer.transform, surfaceNormal, indexFingerRotation, distance); TranslateFromTipToPad(indexFingerRingRenderer.transform, indexFingerPosition, indexKnucklePosition, surfaceNormal, distance); } else { RotateToFinger(indexFingerRingRenderer.transform, deltaTime, indexFingerRotation); } UpdateVisuals(indexFingerRingRenderer, distance, showVisual); } } else { base.UpdateCursorTransform(); } }
/// <summary> /// Override base behavior to align the cursor with the finger, else perform normal cursor transformations. /// </summary> protected override void UpdateCursorTransform() { IMixedRealityNearPointer nearPointer = (IMixedRealityNearPointer)Pointer; // When the pointer has a IMixedRealityNearPointer interface we don't call base.UpdateCursorTransform because we handle // cursor transformation a bit differently. if (nearPointer != null) { float deltaTime = UseUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime; Vector3 indexFingerPosition; Quaternion indexFingerRotation; if (!TryGetJoint(TrackedHandJoint.IndexTip, out indexFingerPosition, out indexFingerRotation)) { indexFingerPosition = transform.position; indexFingerRotation = transform.rotation; } Vector3 indexKnucklePosition; if (!TryGetJoint(TrackedHandJoint.IndexKnuckle, out indexKnucklePosition, out _)) // knuckle rotation not used { indexKnucklePosition = transform.position; } if (nearPointer.IsNearObject) { // If the pointer is near an object translate the primary ring to the index finger tip and rotate to surface normal if close. // The secondary ring should be hidden. float distance; if (!nearPointer.TryGetDistanceToNearestSurface(out distance)) { distance = float.MaxValue; } if (indexFingerRingRenderer != null) { TranslateToFinger(indexFingerRingRenderer.transform, deltaTime, indexFingerPosition, indexKnucklePosition); Vector3 surfaceNormal; if ((distance < alignWithSurfaceDistance) && nearPointer.TryGetNormalToNearestSurface(out surfaceNormal)) { RotateToSurfaceNormal(indexFingerRingRenderer.transform, surfaceNormal, indexFingerRotation, distance); } else { RotateToFinger(indexFingerRingRenderer.transform, deltaTime, indexFingerRotation); } UpdateVisuals(indexFingerRingRenderer, distance, true); } } else { // If the pointer is near a grabbable object position and rotate the ring to the default, // else hide it. float distance = 0; bool nearGrabbable = checkForGrabbables && IsNearGrabbableObject(out distance); if (indexFingerRingRenderer != null) { TranslateToFinger(indexFingerRingRenderer.transform, deltaTime, indexFingerPosition, indexKnucklePosition); RotateToFinger(indexFingerRingRenderer.transform, deltaTime, indexFingerRotation); UpdateVisuals(indexFingerRingRenderer, distance, nearGrabbable); } } } else { base.UpdateCursorTransform(); } }