Files
XRLib/Assets/Plugins/Easy performant outline/Scripts/OutlineTarget.cs
2025-08-11 18:30:13 +09:00

213 lines
6.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace EPOOutline
{
/// <summary>
/// The target to render outline for
/// </summary>
[System.Serializable]
public class OutlineTarget
{
private static List<Material> TempSharedMaterials = new List<Material>();
internal bool IsVisible = false;
/// <summary>
/// <see cref="EPOOutline.ColorMask"/> to use during the cutout process.
/// </summary>
[SerializeField]
public ColorMask CutoutMask = ColorMask.A;
[SerializeField]
internal Renderer renderer;
/// <summary>
/// Sub-mesh index of the renderer.
/// </summary>
[SerializeField]
public int SubmeshIndex;
/// <summary>
/// <see cref="EPOOutline.BoundsMode"/> to use for this target.
/// </summary>
[SerializeField]
public BoundsMode BoundsMode = BoundsMode.Default;
/// <summary>
/// Bounds of this target that will be used for rendering.
/// <br/>Only applicable if <see cref="EPOOutline.OutlineTarget.BoundsMode"/> is set to <see cref="EPOOutline.BoundsMode.Manual"/>
/// </summary>
[SerializeField]
public Bounds Bounds = new Bounds(Vector3.zero, Vector3.one);
/// <summary>
/// The threshold for the cutout to be used.
/// </summary>
[SerializeField]
[Range(0.0f, 1.0f)]
public float CutoutThreshold = 0.5f;
/// <summary>
/// The <see cref="UnityEngine.Rendering.CullMode"/> to be used for rendering of this target.
/// </summary>
[SerializeField]
public CullMode CullMode;
[SerializeField]
private string cutoutTextureName;
[SerializeField]
private int cutoutTextureIndex;
private int? cutoutTextureId;
/// <summary>
/// The renderer of this outline target.
/// </summary>
public Renderer Renderer => renderer;
internal bool UsesCutout => !string.IsNullOrEmpty(cutoutTextureName);
internal Material SharedMaterial
{
get
{
if (renderer == null)
return null;
TempSharedMaterials.Clear();
renderer.GetSharedMaterials(TempSharedMaterials);
return TempSharedMaterials.Count == 0 ?
null :
TempSharedMaterials[ShiftedSubmeshIndex % TempSharedMaterials.Count];
}
}
internal Texture CutoutTexture
{
get
{
var sharedMaterial = SharedMaterial;
return sharedMaterial == null ?
null :
sharedMaterial.GetTexture(CutoutTextureId);
}
}
internal bool IsValidForCutout
{
get
{
var materialToGetTextureFrom = SharedMaterial;
return UsesCutout &&
materialToGetTextureFrom != null &&
materialToGetTextureFrom.HasProperty(CutoutTextureId) &&
CutoutTexture != null;
}
}
/// <summary>
/// The cutout texture index. Only applicable if the texture is TexArray.
/// </summary>
public int CutoutTextureIndex
{
get => cutoutTextureIndex;
set
{
cutoutTextureIndex = value;
if (cutoutTextureIndex >= 0)
return;
Debug.LogError("Trying to set cutout texture index less than zero");
cutoutTextureIndex = 0;
}
}
internal int ShiftedSubmeshIndex => SubmeshIndex;
internal int CutoutTextureId
{
get
{
if (!cutoutTextureId.HasValue)
cutoutTextureId = Shader.PropertyToID(cutoutTextureName);
return cutoutTextureId.Value;
}
}
/// <summary>
/// The name of the texture that is going to be used while rendering as a cutout source.
/// </summary>
public string CutoutTextureName
{
get => cutoutTextureName;
set
{
cutoutTextureName = value;
cutoutTextureId = null;
}
}
public OutlineTarget()
{
}
/// <summary>
/// The constructor of the target.
/// </summary>
/// <param name="renderer">The renderer of the target.</param>
/// <param name="submesh">The sub-mesh of the target.</param>
public OutlineTarget(Renderer renderer, int submesh = 0)
{
SubmeshIndex = submesh;
this.renderer = renderer;
CutoutThreshold = 0.5f;
cutoutTextureId = null;
cutoutTextureName = string.Empty;
CullMode = renderer is SpriteRenderer ? CullMode.Off : CullMode.Back;
}
/// <summary>
/// The constructor of the target.
/// </summary>
/// <param name="renderer">The renderer of the target.</param>
/// <param name="cutoutTextureName">The name of the texture to be used to render the cutout.</param>
/// <param name="cutoutThreshold">The cutout threshold.</param>
public OutlineTarget(Renderer renderer, string cutoutTextureName, float cutoutThreshold = 0.5f)
{
SubmeshIndex = 0;
this.renderer = renderer;
cutoutTextureId = Shader.PropertyToID(cutoutTextureName);
CutoutThreshold = cutoutThreshold;
this.cutoutTextureName = cutoutTextureName;
CullMode = renderer is SpriteRenderer ? CullMode.Off : CullMode.Back;
}
/// <summary>
/// The constructor of the target.
/// </summary>
/// <param name="renderer">The renderer of the target.</param>
/// <param name="submeshIndex">The sub-mesh of the target.</param>
/// <param name="cutoutTextureName">The name of the texture to be used to render the cutout.</param>
/// <param name="cutoutThreshold">The cutout threshold.</param>
public OutlineTarget(Renderer renderer, int submeshIndex, string cutoutTextureName, float cutoutThreshold = 0.5f)
{
SubmeshIndex = submeshIndex;
this.renderer = renderer;
cutoutTextureId = Shader.PropertyToID(cutoutTextureName);
CutoutThreshold = cutoutThreshold;
this.cutoutTextureName = cutoutTextureName;
CullMode = renderer is SpriteRenderer ? CullMode.Off : CullMode.Back;
}
}
}