// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.Utilities; using System; using Unity.Profiling; using UnityEngine; namespace Microsoft.MixedReality.Toolkit.Input { /// /// Implementation for default hand ray pointers shipped with MRTK. Primarily used with hands and motion controllers /// [AddComponentMenu("Scripts/MRTK/SDK/ShellHandRayPointer")] public class ShellHandRayPointer : LinePointer { [Header("Shell Pointer Settings")] [SerializeField] [Tooltip("Used when a focus target exists, or when select is pressed")] private Material lineMaterialSelected = null; [SerializeField] [Tooltip("Used when no focus target exists and select is not pressed")] private Material lineMaterialNoTarget = null; [Header("Inertia Settings")] [SerializeField] private BezierInertia inertia; [Tooltip("Where to place the first control point of the bezier curve")] [SerializeField] [Range(0f, 0.5f)] private float startPointLerp = 0.33f; [SerializeField] [Tooltip("Where to place the second control point of the bezier curve")] [Range(0.5f, 1f)] private float endPointLerp = 0.66f; private bool wasSelectPressed = false; private bool wasGrabPressed = false; [Header("Obsolete Settings")] [SerializeField] [Obsolete("Use lineMaterialSelected instead.")] private BaseMixedRealityLineRenderer lineRendererSelected = null; [SerializeField] [Obsolete("Use lineMaterialNoTarget instead.")] private BaseMixedRealityLineRenderer lineRendererNoTarget = null; /// protected override void Start() { #pragma warning disable 0618 if (lineRendererSelected != null && lineMaterialSelected == null) { Debug.LogWarning("Property lineRendererSelected is obsolete. Use lineMaterialSelected instead."); if (lineRendererSelected is MixedRealityLineRenderer lineRenderer) { lineMaterialSelected = lineRenderer.LineMaterial; } } if (lineRendererNoTarget != null && lineMaterialNoTarget == null) { Debug.LogWarning("Property lineRendererNoTarget is obsolete. Use lineMaterialNoTarget instead."); if (lineRendererNoTarget is MixedRealityLineRenderer lineRenderer) { lineMaterialNoTarget = lineRenderer.LineMaterial; } } #pragma warning restore 0618 base.Start(); } /// protected override void OnEnable() { base.OnEnable(); inertia = gameObject.EnsureComponent(); } private static readonly ProfilerMarker OnPostSceneQueryPerfMarker = new ProfilerMarker("[MRTK] ShellHandRayPointer.OnPostSceneQuery"); /// public override void OnPostSceneQuery() { using (OnPostSceneQueryPerfMarker.Auto()) { base.OnPostSceneQuery(); if (!LineBase.enabled) { return; } if (wasSelectPressed != IsSelectPressed || wasGrabPressed != IsGrabPressed) { wasSelectPressed = IsSelectPressed; wasGrabPressed = IsGrabPressed; var currentMaterial = IsSelectPressed || IsGrabPressed ? lineMaterialSelected : lineMaterialNoTarget; foreach (var lr in LineRenderers) { var lineRenderer = lr as MixedRealityLineRenderer; if (lineRenderer != null) { lineRenderer.LineMaterial = currentMaterial; } } } } } private static readonly ProfilerMarker PreUpdateLineRenderersPerfMarker = new ProfilerMarker("[MRTK] ShellHandRayPointer.PreUpdateLineRenderers"); protected override void PreUpdateLineRenderers() { using (PreUpdateLineRenderersPerfMarker.Auto()) { base.PreUpdateLineRenderers(); bool isFocusedLock = IsFocusLocked && IsTargetPositionLockedOnFocusLock; inertia.enabled = !isFocusedLock; if (isFocusedLock) { float distance = Result != null ? Result.Details.RayDistance : DefaultPointerExtent; Vector3 startPoint = LineBase.FirstPoint; // Project forward based on pointer direction to get an 'expected' position of the first control point Vector3 expectedPoint = startPoint + Rotation * Vector3.forward * distance; // Lerp between the expected position and the expected point LineBase.SetPoint(1, Vector3.Lerp(startPoint, expectedPoint, startPointLerp)); // Get our next 'expected' position by lerping between the expected point and the end point // The result will be a line that starts moving in the pointer's direction then bends towards the target expectedPoint = Vector3.Lerp(expectedPoint, LineBase.LastPoint, endPointLerp); LineBase.SetPoint(2, Vector3.Lerp(startPoint, expectedPoint, endPointLerp)); } } } } }