// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.GraphicsTools
{
///
/// Abstract component to encapsulate common functionality around outline components.
///
public abstract class BaseMeshOutline : MonoBehaviour
{
///
/// The material used to render the outline. Outline materials should normal have "Depth Write" set to Off and "Vertex Extrusion" enabled.
/// Most Graphics Tools/Standard features should work as an outline material, but it is recommended to keep the outline material as simple as possible.
/// Note, this material is not automatically instanced.
///
public Material OutlineMaterial
{
get { return outlineMaterial; }
set
{
if (outlineMaterial != value)
{
outlineMaterial = value;
ApplyOutlineMaterial();
}
}
}
[Tooltip("The material used to render the outline. Outline materials should normal have \"Depth Write\" set to Off and \"Vertex Extrusion\" enabled. Note, this material is not automatically instanced.")]
[SerializeField]
protected Material outlineMaterial = null;
///
/// How thick (in meters) should the outline be. Overrides the "Extrusion Value" in the Graphics Tools/Standard material.
///
public float OutlineWidth
{
get { return outlineWidth; }
set
{
if (outlineWidth != value)
{
outlineWidth = value;
ApplyOutlineWidth();
}
}
}
[Tooltip("How thick (in meters) should the outline be. Overrides the \"Extrusion Value\" in the Graphics Tools/Standard material.")]
[SerializeField]
[Range(0.0f, 1.0f)]
protected float outlineWidth = 0.01f;
///
/// Should the render queue be automatically calculated or based on the material properties?
///
public bool AutoAssignRenderQueue
{
get { return autoAssignRenderQueue; }
set
{
if (autoAssignRenderQueue != value)
{
autoAssignRenderQueue = value;
ApplyOutlineMaterial();
}
}
}
[Tooltip("Should the render queue be automatically calculated or based on the material properties?")]
[SerializeField]
protected bool autoAssignRenderQueue = true;
///
/// Should the stencil buffer be used to mask this outline rather than relying on depth? Required when a skybox is in use.
/// Note, it is up to the user to manage the stencil reference value.
///
public bool UseStencilOutline
{
get { return useStencilOutline; }
set
{
if (useStencilOutline != value)
{
useStencilOutline = value;
ApplyOutlineMaterial();
}
}
}
[Tooltip("Should the stencil buffer be used to mask this outline rather than relying on depth? Required when a skybox is in use. Note, it is up to the user to manage the stencil reference value.")]
[SerializeField]
protected bool useStencilOutline = false;
///
/// The material used write a value to the stencil buffer. This material should have \"Depth Write\" set to Off and a \"ColorMask\" set to Zero.
/// Note, this material is not automatically instanced.
///
public Material StencilWriteMaterial
{
get { return stencilWriteMaterial; }
set
{
if (stencilWriteMaterial != value)
{
stencilWriteMaterial = value;
ApplyOutlineMaterial();
}
}
}
[Tooltip("The material used write a value to the stencil buffer. This material should have \"Depth Write\" set to Off and a \"ColorMask\" set to Zero. Note, this material is not automatically instanced.")]
[SerializeField]
protected Material stencilWriteMaterial = null;
///
/// How far (in meters) should the outline be begin from the surface. Overrides the "Extrusion Value" in the Graphics Tools/Standard material.
///
public float OutlineOffset
{
get { return outlineOffset; }
set
{
if (outlineOffset != value)
{
outlineOffset = value;
ApplyOutlineWidth();
}
}
}
[Tooltip("How far (in meters) should the outline be begin from the surface. Overrides the \"Extrusion Value\" in the Graphics Tools/Standard material.")]
[SerializeField]
[Range(0.0f, 1.0f)]
protected float outlineOffset = 0.0f;
///
/// "The value written to and read from the stencil buffer. This should be unique per outlined object."
///
public int StencilReference
{
get { return stencilReference; }
set
{
if (stencilReference != value)
{
stencilReference = value;
ApplyStencilReference();
}
}
}
[Tooltip("The value written to and read from the stencil buffer. This should be unique per outlined object.")]
[SerializeField]
[Range(1, 255)]
protected int stencilReference = 1;
#region MonoBehaviour Implementation
///
/// Event for when the animation system updates any serialized properties.
///
protected virtual void OnDidApplyAnimationProperties()
{
ApplyOutlineWidth();
ApplyStencilReference();
}
#endregion MonoBehaviour Implementation
///
/// Interface to apply the outline material to the renderer(s).
///
public abstract void ApplyOutlineMaterial();
///
/// Interface to to update the outline width with the renderer(s).
///
public abstract void ApplyOutlineWidth();
///
/// Interface to to update the stencil ID with the renderer(s).
///
public abstract void ApplyStencilReference();
}
}