Newer
Older
HoloAnatomy / Assets / HoloToolkit-Examples / SpatialUnderstanding / Scripts / SpatialUnderstandingBasicCursor.cs
SURFACEBOOK2\jackwynne on 25 May 2018 3 KB v1
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using HoloToolkit.Unity.InputModule;
using UnityEngine;

namespace HoloToolkit.Examples.SpatialUnderstandingFeatureOverview
{
    /// <summary>
    /// 1. Decides when to show the cursor.
    /// 2. Positions the cursor at the gazed location.
    /// 3. Rotates the cursor to match hologram normals.
    /// </summary>
    public class SpatialUnderstandingBasicCursor : MonoBehaviour
    {
        public struct RaycastResult
        {
            public bool Hit;
            public Vector3 Position;
            public Vector3 Normal;
        }

        [Tooltip("Distance, in meters, to offset the cursor from the collision point.")]
        public float DistanceFromCollision = 0.01f;

        private Quaternion cursorDefaultRotation;

        private MeshRenderer meshRenderer;

        private GazeManager gazeManager;

        protected virtual void Awake()
        {
            meshRenderer = gameObject.GetComponent<MeshRenderer>();

            if (meshRenderer == null)
            {
                Debug.LogError("This script requires that your cursor asset has a MeshRenderer component on it.");
                return;
            }

            // Hide the Cursor to begin with.
            meshRenderer.enabled = false;

            // Cache the cursor default rotation so the cursor can be rotated with respect to the original rotation.
            cursorDefaultRotation = gameObject.transform.rotation;
        }

        protected virtual void Start()
        {
            gazeManager = GazeManager.Instance;

            if (gazeManager == null)
            {
                Debug.LogError("Must have a GazeManager somewhere in the scene.");
            }

            if ((GazeManager.Instance.RaycastLayerMasks[0] & (1 << gameObject.layer)) != 0)
            {
                Debug.LogError("The cursor has a layer that is checked in the GazeManager's Raycast Layer Mask.  Change the cursor layer (e.g.: to Ignore Raycast) or uncheck the layer in GazeManager: " +
                    LayerMask.LayerToName(gameObject.layer));
            }
        }

        protected virtual RaycastResult CalculateRayIntersect()
        {
            var result = new RaycastResult
            {
                Hit = (GazeManager.Instance.HitObject == null) ? false : true,
                Position = GazeManager.Instance.HitPosition,
                Normal = GazeManager.Instance.GazeNormal
            };

            return result;
        }

        protected virtual void LateUpdate()
        {
            if (meshRenderer == null || gazeManager == null)
            {
                return;
            }

            // Calculate the raycast result
            RaycastResult rayResult = CalculateRayIntersect();

            // Show or hide the Cursor based on if the user's gaze hit a hologram.
            meshRenderer.enabled = rayResult.Hit;

            // Place the cursor at the calculated position.
            gameObject.transform.position = rayResult.Position + rayResult.Normal * DistanceFromCollision;

            // Reorient the cursor to match the hit object normal.
            gameObject.transform.up = rayResult.Normal;
            gameObject.transform.rotation *= cursorDefaultRotation;
        }
    }
}