// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. using System.Collections; using System.Collections.Generic; using UnityEngine; namespace HoloToolkit.Unity.InputModule { /// <summary> /// A cursor that looks and acts more like the shell cursor. /// A two part cursor with visual feedback for all cursor states /// </summary> public class InteractiveMeshCursor : Cursor { [Tooltip("The ring or outer element")] public GameObject Ring; [Tooltip("Inner cursor element")] public GameObject Dot; [Tooltip("Point light")] public GameObject Light; [Tooltip("The scale factor to soften the distance scaling, we want the cursor to scale in the distance, but not disappear.")] public float DistanceScaleFactor = 0.3f; [Tooltip("The scale both elements will be at their default state")] public float DefaultScale = 0.75f; [Tooltip("The scale both elements will when pressed")] public float DownScale = 0.5f; [Tooltip("The scale both elements will a hand is visible")] public float UpScale = 1; [Tooltip("Time to scale between states")] public float ScaleTime = 0.5f; /// <summary> /// internal state and element management /// </summary> private float mTimer = 0; private bool mHasHover = false; private bool mHasHand = false; private bool mIsDown = false; private Vector3 mBaseScale = new Vector3(1, 1, 1); private Vector3 mTargetScale; private bool mIsVisible = true; private Vector3 mAwakeScale; private void Awake() { mAwakeScale = transform.localScale; } /// <summary> /// Decide which element (ring or dot) should be visible and at what scale /// </summary> /// <param name="state"></param> public override void OnCursorStateChange(CursorStateEnum state) { base.OnCursorStateChange(state); // the cursor state has changed, reset the animation timer if (mHasHand != this.IsHandVisible || mIsDown != this.IsInputSourceDown || mHasHover != (this.TargetedObject != null)) { mTimer = 0; } mHasHand = this.IsHandVisible; mIsDown = this.IsInputSourceDown; mHasHover = this.TargetedObject != null; mTargetScale = mBaseScale * DefaultScale; bool showRing = false; switch (state) { case CursorStateEnum.None: break; case CursorStateEnum.Observe: break; case CursorStateEnum.ObserveHover: showRing = true; break; case CursorStateEnum.Interact: showRing = true; mTargetScale = mBaseScale * DownScale; break; case CursorStateEnum.InteractHover: showRing = true; mTargetScale = mBaseScale * UpScale; break; case CursorStateEnum.Select: mTargetScale = mBaseScale * UpScale; break; case CursorStateEnum.Release: break; case CursorStateEnum.Contextual: break; default: break; } if (!mIsVisible) { return; } Ring.SetActive(showRing); Dot.SetActive(!showRing); // added observation of CursorModifier if (TargetedCursorModifier != null && mHasHover) { ElementVisibility(!TargetedCursorModifier.GetCursorVisibility()); } } /// <summary> /// scale the cursor elements /// </summary> protected override void UpdateCursorTransform() { base.UpdateCursorTransform(); // animate scale of ring and dot if (mTimer < ScaleTime) { mTimer += Time.deltaTime; if (mTimer > ScaleTime) { mTimer = ScaleTime; } Ring.transform.localScale = Vector3.Lerp(mBaseScale * DefaultScale, mTargetScale, mTimer/ScaleTime); Dot.transform.localScale = Vector3.Lerp(mBaseScale * DefaultScale, mTargetScale, mTimer / ScaleTime); } // handle scale of main cursor go float distance = Vector3.Distance(GazeManager.Instance.GazeOrigin, transform.position); float smoothscaling = 1 - DefaultCursorDistance * DistanceScaleFactor; transform.localScale = mAwakeScale * (distance * DistanceScaleFactor + smoothscaling); } /// <summary> /// override the base class for custom visibility /// </summary> /// <param name="visible"></param> public override void SetVisibility(bool visible) { base.SetVisibility(visible); mIsVisible = visible; ElementVisibility(visible); if (visible) { OnCursorStateChange(CursorState); } } /// <summary> /// controls the visibility of cursor elements in one place /// </summary> /// <param name="visible"></param> private void ElementVisibility(bool visible) { if (Ring != null) { Ring.SetActive(visible); } if (Dot != null) { Dot.SetActive(visible); } if (Light != null) { Light.SetActive(visible); } } } }