using System;
using System.Linq;
using UnityEngine;
namespace TFramework
{
[DisallowMultipleComponent]
public class Outline : MonoBehaviour
{
public enum Mode
{
///
/// 描边所有轮廓
///
OutlineAll,
///
/// 仅描边可见部分
///
OutlineVisible,
///
/// 仅描边隐藏部分
///
OutlineHidden,
///
/// 描边且剪影
///
OutlineAndSilhouette,
///
/// 仅描边
///
SilhouetteOnly
}
///
/// 描边模式
///
public Mode OutlineMode
{
get { return outlineMode; }
set
{
outlineMode = value;
_isChange = true;
}
}
///
/// 描边颜色
///
public Color OutlineColor
{
get { return outlineColor; }
set
{
outlineColor = value;
_isChange = true;
}
}
///
/// 描边宽度
///
public float OutlineWidth
{
get { return outlineWidth; }
set
{
outlineWidth = value;
_isChange = true;
}
}
[SerializeField]
private Mode outlineMode;
[SerializeField]
private Color outlineColor;
[SerializeField, Range(0f, 10f)]
private float outlineWidth = 2f;
private Renderer[] renderers;
private Material outlineMaskMaterial;
private Material outlineFillMaterial;
private bool _isChange=false;
void Awake()
{
renderers = GetComponentsInChildren();
// Instantiate outline materials
outlineMaskMaterial = Instantiate(Main.GetMagr().m_outlineMaskMaterial);
outlineFillMaterial = Instantiate(Main.GetMagr().m_outlineFillMaterial);
outlineMaskMaterial.name = "OutlineMask (Instance)";
outlineFillMaterial.name = "OutlineFill (Instance)";
}
void OnEnable()
{
foreach (var renderer in renderers)
{
var materials = renderer.sharedMaterials.ToList();
materials.Add(outlineMaskMaterial);
materials.Add(outlineFillMaterial);
renderer.materials = materials.ToArray();
}
_isChange = true;
}
private void Update()
{
if(_isChange)
{
_isChange = false;
UpdateMaterialProperties();
}
}
void OnDisable()
{
foreach (var renderer in renderers)
{
// Remove outline shaders
var materials = renderer.sharedMaterials.ToList();
materials.Remove(outlineMaskMaterial);
materials.Remove(outlineFillMaterial);
renderer.materials = materials.ToArray();
}
}
void OnDestroy()
{
Destroy(outlineMaskMaterial);
Destroy(outlineFillMaterial);
}
void UpdateMaterialProperties()
{
// Apply properties according to mode
outlineFillMaterial.SetColor("_OutlineColor", outlineColor);
switch (outlineMode)
{
case Mode.OutlineAll:
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
break;
case Mode.OutlineVisible:
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
break;
case Mode.OutlineHidden:
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater);
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
break;
case Mode.OutlineAndSilhouette:
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
break;
case Mode.SilhouetteOnly:
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater);
outlineFillMaterial.SetFloat("_OutlineWidth", 0f);
break;
}
}
}
}