157 lines
4.8 KiB
C#
157 lines
4.8 KiB
C#
using Coffee.UISoftMaskInternal;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Profiling;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Coffee.UISoftMask
|
|
{
|
|
[ExecuteAlways]
|
|
[RequireComponent(typeof(RectTransform))]
|
|
[RequireComponent(typeof(CanvasRenderer))]
|
|
[DisallowMultipleComponent]
|
|
[AddComponentMenu("")]
|
|
[Icon("Packages/com.coffee.softmask-for-ugui/Icons/SoftMaskIcon.png")]
|
|
public class TerminalMaskingShape : MaskableGraphic, ILayoutElement, ILayoutIgnorer, IMaskable
|
|
{
|
|
private static Material s_SharedTerminalMaterial;
|
|
private Mask _mask;
|
|
private Mask _parentMask;
|
|
private bool _shouldRecalculateStencil;
|
|
private int _stencilBits;
|
|
|
|
public override bool raycastTarget
|
|
{
|
|
get => false;
|
|
set { }
|
|
}
|
|
|
|
protected override void OnEnable()
|
|
{
|
|
if (!s_SharedTerminalMaterial)
|
|
{
|
|
s_SharedTerminalMaterial = new Material(Shader.Find("Hidden/UI/TerminalMaskingShape"))
|
|
{
|
|
hideFlags = HideFlags.DontSave | HideFlags.NotEditable
|
|
};
|
|
}
|
|
|
|
material = s_SharedTerminalMaterial;
|
|
transform.parent.TryGetComponent(out _parentMask);
|
|
_shouldRecalculateStencil = true;
|
|
hideFlags = UISoftMaskProjectSettings.hideFlagsForTemp;
|
|
|
|
#if UNITY_EDITOR
|
|
UISoftMaskProjectSettings.shaderRegistry.RegisterVariant(s_SharedTerminalMaterial, "UI > Soft Mask");
|
|
#endif
|
|
base.OnEnable();
|
|
}
|
|
|
|
protected override void OnDisable()
|
|
{
|
|
base.OnDisable();
|
|
if (_parentMask && _parentMask.MaskEnabled())
|
|
{
|
|
_parentMask.graphic.SetMaterialDirty();
|
|
}
|
|
}
|
|
|
|
void ILayoutElement.CalculateLayoutInputHorizontal()
|
|
{
|
|
}
|
|
|
|
void ILayoutElement.CalculateLayoutInputVertical()
|
|
{
|
|
}
|
|
|
|
float ILayoutElement.minWidth => 0;
|
|
|
|
float ILayoutElement.preferredWidth => 0;
|
|
|
|
float ILayoutElement.flexibleWidth => 0;
|
|
|
|
float ILayoutElement.minHeight => 0;
|
|
|
|
float ILayoutElement.preferredHeight => 0;
|
|
|
|
float ILayoutElement.flexibleHeight => 0;
|
|
|
|
int ILayoutElement.layoutPriority => 0;
|
|
|
|
bool ILayoutIgnorer.ignoreLayout => true;
|
|
|
|
void IMaskable.RecalculateMasking()
|
|
{
|
|
_shouldRecalculateStencil = true;
|
|
}
|
|
|
|
public override Material GetModifiedMaterial(Material baseMaterial)
|
|
{
|
|
if (!IsActive())
|
|
{
|
|
StencilMaterial.Remove(m_MaskMaterial);
|
|
m_MaskMaterial = null;
|
|
return null;
|
|
}
|
|
|
|
RecalculateStencilIfNeeded();
|
|
if ((_stencilBits == 0 && !_mask) || _parentMask != _mask)
|
|
{
|
|
StencilMaterial.Remove(m_MaskMaterial);
|
|
m_MaskMaterial = null;
|
|
return null;
|
|
}
|
|
|
|
var maskMat = StencilMaterial.Add(baseMaterial, _stencilBits, StencilOp.Zero, CompareFunction.Equal, 0,
|
|
_stencilBits, Utils.GetHighestBit(_stencilBits));
|
|
|
|
StencilMaterial.Remove(m_MaskMaterial);
|
|
m_MaskMaterial = maskMat;
|
|
return maskMat;
|
|
}
|
|
|
|
protected override void OnPopulateMesh(VertexHelper vh)
|
|
{
|
|
vh.Clear();
|
|
if (!IsActive()) return;
|
|
|
|
// Full-screen rendering.
|
|
Profiler.BeginSample("(SM4UI)[TerminalMaskingShape)] OnPopulateMesh");
|
|
vh.AddVert(new Vector3(-999999, -999999), new Color32(255, 255, 255, 255), new Vector2(0, 0));
|
|
vh.AddVert(new Vector3(-999999, +999999), new Color32(255, 255, 255, 255), new Vector2(0, 1));
|
|
vh.AddVert(new Vector3(+999999, +999999), new Color32(255, 255, 255, 255), new Vector2(1, 1));
|
|
vh.AddVert(new Vector3(+999999, -999999), new Color32(255, 255, 255, 255), new Vector2(1, 0));
|
|
|
|
vh.AddTriangle(0, 1, 2);
|
|
vh.AddTriangle(2, 3, 0);
|
|
Profiler.EndSample();
|
|
}
|
|
|
|
private void RecalculateStencilIfNeeded()
|
|
{
|
|
if (!isActiveAndEnabled)
|
|
{
|
|
_mask = null;
|
|
_stencilBits = 0;
|
|
return;
|
|
}
|
|
|
|
if (!_shouldRecalculateStencil) return;
|
|
_shouldRecalculateStencil = false;
|
|
var useStencil = UISoftMaskProjectSettings.useStencilOutsideScreen;
|
|
_stencilBits = Utils.GetStencilBits(transform, false, useStencil, out _mask, out var _);
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
[CustomEditor(typeof(TerminalMaskingShape))]
|
|
internal class TerminalMaskingShapeEditor : Editor
|
|
{
|
|
public override void OnInspectorGUI()
|
|
{
|
|
}
|
|
}
|
|
#endif
|
|
}
|