// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections.Generic;
using UnityEngine;
namespace Microsoft.MixedReality.GraphicsTools
{
///
/// Utility component to animate and visualize a light that can be used with the GraphicsTools/Standard and
/// GraphicsTools/Standard Canvas shaders that have the "_HOVER_LIGHT" keyword enabled.
///
[ExecuteInEditMode]
[AddComponentMenu("Scripts/GraphicsTools/HoverLight")]
public class HoverLight : BaseLight
{
// The Graphics Tools/Standard and Graphics Tools/Standard Canvas shaders supports up to four (4) hover lights.
private const int hoverLightCount = 4;
private const int hoverLightDataSize = 2;
private static List activeHoverLights = new List(hoverLightCount);
private static Vector4[] hoverLightData = new Vector4[hoverLightDataSize * hoverLightCount];
private static int _HoverLightDataID;
private static int lastHoverLightUpdate = -1;
[Tooltip("Specifies the radius of the HoverLight effect.")]
[SerializeField, Min(0.0f)]
private float radius = 0.15f;
///
/// Specifies the Radius of the HoverLight effect.
///
public float Radius
{
get => radius;
set => radius = Mathf.Max(0.0f, value);
}
[Tooltip("Specifies the highlight color.")]
[SerializeField]
private Color color = new Color(0.3f, 0.3f, 0.3f, 1.0f);
///
/// Specifies the highlight color.
///
public Color Color
{
get => color;
set => color = value;
}
#region BaseLight Implementation
///
protected override void Initialize()
{
_HoverLightDataID = Shader.PropertyToID("_HoverLightData");
}
///
protected override void AddLight()
{
if (activeHoverLights.Count == hoverLightCount)
{
Debug.LogWarningFormat("Max hover light count {0} exceeded. {1} will not be considered by the Graphics Tools/Standard shader until other lights are removed.", hoverLightCount, gameObject.name);
}
activeHoverLights.Add(this);
}
///
protected override void RemoveLight()
{
activeHoverLights.Remove(this);
}
///
protected override void UpdateLights(bool forceUpdate = false)
{
if (lastHoverLightUpdate == -1)
{
Initialize();
}
if (!forceUpdate && (Time.frameCount == lastHoverLightUpdate))
{
return;
}
for (int i = 0; i < hoverLightCount; ++i)
{
HoverLight light = (i >= activeHoverLights.Count) ? null : activeHoverLights[i];
int dataIndex = i * hoverLightDataSize;
if (light)
{
hoverLightData[dataIndex] = new Vector4(light.transform.position.x,
light.transform.position.y,
light.transform.position.z,
1.0f);
hoverLightData[dataIndex + 1] = new Vector4(light.Color.r,
light.Color.g,
light.Color.b,
1.0f / Mathf.Clamp(light.Radius, 0.001f, 1.0f));
}
else
{
hoverLightData[dataIndex] = Vector4.zero;
}
}
Shader.SetGlobalVectorArray(_HoverLightDataID, hoverLightData);
lastHoverLightUpdate = Time.frameCount;
}
#endregion BaseLight Implementation
}
}