using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
///
/// Reverse masking for parent Mask component.
///
[ExecuteInEditMode]
[AddComponentMenu("UI/Unmask/Unmask", 1)]
public class Unmask : MonoBehaviour, IMaterialModifier
{
//################################
// Constant or Static Members.
//################################
static readonly Vector2 s_Center = new Vector2(0.5f, 0.5f);
//################################
// Serialize Members.
//################################
[Tooltip("Fit graphic's transform to target transform on LateUpdate.")]
[SerializeField] RectTransform m_AutoFitTarget;
[Tooltip("Show the graphic that is associated with the unmask render area.")]
[SerializeField] bool m_ShowUnmaskGraphic = false;
//################################
// Public Members.
//################################
///
/// The graphic associated with the unmask.
///
public Graphic graphic{ get { return _graphic ?? (_graphic = GetComponent()); } }
///
/// Fit graphic's transform to target transform on LateUpdate.
///
public RectTransform autoFitTarget{ get { return m_AutoFitTarget; } set { m_AutoFitTarget = value; } }
///
/// Show the graphic that is associated with the unmask render area.
///
public bool showUnmaskGraphic
{
get { return m_ShowUnmaskGraphic; }
set
{
m_ShowUnmaskGraphic = value;
SetDirty();
}
}
///
/// Perform material modification in this function.
///
/// Modified material.
/// Configured Material.
public Material GetModifiedMaterial(Material baseMaterial)
{
if (!isActiveAndEnabled)
{
return baseMaterial;
}
Transform stopAfter = MaskUtilities.FindRootSortOverrideCanvas(transform);
var stencilDepth = MaskUtilities.GetStencilDepth(transform, stopAfter);
StencilMaterial.Remove(_unmaskMaterial);
_unmaskMaterial = StencilMaterial.Add(baseMaterial, (1 << stencilDepth) - 1, StencilOp.Zero, CompareFunction.Always, m_ShowUnmaskGraphic ? ColorWriteMask.All : (ColorWriteMask)0, 0, (1 << stencilDepth) - 1);
//StencilMaterial.Remove (baseMaterial);
return _unmaskMaterial;
}
///
/// Fit to target transform.
///
/// Target transform.
public void FitTo(RectTransform target)
{
var rt = transform as RectTransform;
rt.position = target.position;
rt.rotation = target.rotation;
var s1 = target.lossyScale;
var s2 = rt.parent.lossyScale;
rt.localScale = new Vector3(s1.x / s2.x, s1.y / s2.y, s1.z / s2.z);
rt.sizeDelta = target.rect.size;
rt.anchorMax = rt.anchorMin = s_Center;
}
//################################
// Private Members.
//################################
Material _unmaskMaterial;
Graphic _graphic;
///
/// This function is called when the object becomes enabled and active.
///
void OnEnable()
{
if (m_AutoFitTarget)
{
FitTo(m_AutoFitTarget);
}
SetDirty();
}
///
/// This function is called when the behaviour becomes disabled () or inactive.
///
void OnDisable()
{
StencilMaterial.Remove(_unmaskMaterial);
_unmaskMaterial = null;
SetDirty();
}
///
/// LateUpdate is called every frame, if the Behaviour is enabled.
///
void LateUpdate()
{
if (m_AutoFitTarget)
{
FitTo(m_AutoFitTarget);
}
}
///
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
///
void OnValidate()
{
SetDirty();
}
///
/// Mark the graphic as dirty.
///
void SetDirty()
{
if (graphic)
{
graphic.SetMaterialDirty();
}
}
}
}