close #31; Mask interaction for each layer
parent
a135ea1a25
commit
4e533c22bf
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using Object = UnityEngine.Object;
|
||||
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||
using System.IO;
|
||||
|
||||
namespace Coffee.UIExtensions.Editors
|
||||
|
@ -17,6 +18,38 @@ namespace Coffee.UIExtensions.Editors
|
|||
[CanEditMultipleObjects]
|
||||
public class SoftMaskableEditor : Editor
|
||||
{
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
public enum MaskInteraction : int
|
||||
{
|
||||
VisibleInsideMask = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6),
|
||||
VisibleOutsideMask = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6),
|
||||
Custom = -1,
|
||||
}
|
||||
|
||||
MaskInteraction maskInteraction
|
||||
{
|
||||
get
|
||||
{
|
||||
int value = _spMaskInteraction.intValue;
|
||||
return _custom
|
||||
? MaskInteraction.Custom
|
||||
: System.Enum.IsDefined(typeof(MaskInteraction), value)
|
||||
? (MaskInteraction)value
|
||||
: MaskInteraction.Custom;
|
||||
}
|
||||
set
|
||||
{
|
||||
_custom = (value == MaskInteraction.Custom);
|
||||
if (!_custom)
|
||||
{
|
||||
_spMaskInteraction.intValue = (int)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool _custom = false;
|
||||
|
||||
static readonly Type s_TypeTMPro = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_Text");
|
||||
static readonly Type s_TypeTMP_SpriteAsset = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_SpriteAsset");
|
||||
static readonly Type s_TypeTMProSettings = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_Settings");
|
||||
|
@ -36,9 +69,13 @@ namespace Coffee.UIExtensions.Editors
|
|||
Shader _mobileShader;
|
||||
Shader _spriteShader;
|
||||
List<MaterialEditor> _materialEditors = new List<MaterialEditor> ();
|
||||
SerializedProperty _spMaskInteraction;
|
||||
|
||||
private void OnEnable ()
|
||||
{
|
||||
_spMaskInteraction = serializedObject.FindProperty("m_MaskInteraction");
|
||||
_custom = (maskInteraction == MaskInteraction.Custom);
|
||||
|
||||
ClearMaterialEditors ();
|
||||
|
||||
_shader = Shader.Find ("TextMeshPro/Distance Field (SoftMaskable)");
|
||||
|
@ -58,6 +95,8 @@ namespace Coffee.UIExtensions.Editors
|
|||
s_PiDefaultFontAssetPath = s_TypeTMProSettings.GetProperty ("defaultFontAssetPath", BindingFlags.Static | BindingFlags.Public);
|
||||
s_PiDefaultSpriteAssetPath = s_TypeTMProSettings.GetProperty ("defaultSpriteAssetPath", BindingFlags.Static | BindingFlags.Public);
|
||||
}
|
||||
|
||||
s_MaskWarning = new GUIContent(EditorGUIUtility.FindTexture("console.warnicon.sml"), "This component is not SoftMask. Use SoftMask instead of Mask.");
|
||||
}
|
||||
|
||||
private void OnDisable ()
|
||||
|
@ -65,10 +104,105 @@ namespace Coffee.UIExtensions.Editors
|
|||
ClearMaterialEditors ();
|
||||
}
|
||||
|
||||
List<Mask> tmpMasks = new List<Mask>();
|
||||
|
||||
void DrawMaskInteractions()
|
||||
{
|
||||
(target as SoftMaskable).GetComponentsInParent<Mask>(true, tmpMasks);
|
||||
tmpMasks.RemoveAll(x => !x.enabled);
|
||||
tmpMasks.Reverse();
|
||||
|
||||
maskInteraction = (MaskInteraction)EditorGUILayout.EnumPopup("Mask Interaction", maskInteraction);
|
||||
if (_custom)
|
||||
{
|
||||
var l = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 45;
|
||||
|
||||
using (var ccs = new EditorGUI.ChangeCheckScope())
|
||||
{
|
||||
int intr0 = DrawMaskInteraction(0);
|
||||
int intr1 = DrawMaskInteraction(1);
|
||||
int intr2 = DrawMaskInteraction(2);
|
||||
int intr3 = DrawMaskInteraction(3);
|
||||
|
||||
if (ccs.changed) {
|
||||
_spMaskInteraction.intValue = (intr0 << 0) + (intr1 << 2) + (intr2 << 4) + (intr3 << 6);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = l;
|
||||
}
|
||||
}
|
||||
|
||||
static GUIContent s_MaskWarning = new GUIContent();
|
||||
|
||||
int DrawMaskInteraction(int layer)
|
||||
{
|
||||
Mask mask = layer < tmpMasks.Count ? tmpMasks[layer] : null;
|
||||
MaskIntr intr = (MaskIntr)((_spMaskInteraction.intValue >> layer * 2) & 0x3);
|
||||
if (!mask)
|
||||
{
|
||||
return (int)intr;
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.LabelField(mask is SoftMask ? GUIContent.none : s_MaskWarning, GUILayout.Width(16));
|
||||
GUILayout.Space(-5);
|
||||
EditorGUILayout.ObjectField("Mask " + layer, mask, typeof(Mask), false);
|
||||
GUILayout.Space(-15);
|
||||
return (int)(MaskIntr)EditorGUILayout.EnumPopup(intr);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI ()
|
||||
{
|
||||
base.OnInspectorGUI ();
|
||||
|
||||
serializedObject.Update();
|
||||
DrawMaskInteractions();
|
||||
|
||||
// maskInteraction = (MaskInteraction)EditorGUILayout.EnumPopup("Mask Interaction", maskInteraction);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
/*
|
||||
EditorGUI.indentLevel++;
|
||||
var l = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 60;
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.ObjectField("Mask 0", null, typeof(Mask), false);
|
||||
EditorGUILayout.EnumPopup (MaskIntr.None);
|
||||
}
|
||||
EditorGUIUtility.labelWidth = l;
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
var spMaskInteraction = serializedObject.FindProperty ("m_MaskInteraction");
|
||||
MaskIntr intr0 = (MaskIntr)((spMaskInteraction.intValue >> 0) & 0x3);
|
||||
MaskIntr intr1 = (MaskIntr)((spMaskInteraction.intValue >> 2) & 0x3);
|
||||
MaskIntr intr2 = (MaskIntr)((spMaskInteraction.intValue >> 4) & 0x3);
|
||||
MaskIntr intr3 = (MaskIntr)((spMaskInteraction.intValue >> 6) & 0x3);
|
||||
|
||||
using (var ccs = new EditorGUI.ChangeCheckScope ()) {
|
||||
|
||||
intr0 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 0", intr0);
|
||||
intr1 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 1", intr1);
|
||||
intr2 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 2", intr2);
|
||||
intr3 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 3", intr3);
|
||||
|
||||
if (ccs.changed) {
|
||||
current.SetMaskInteractions (intr0,intr1,intr2,intr3);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// spMaskInteraction.intValue = (intr0 << 0) | (intr1 << 2) | (intr2 << 4) | (intr3 << 6);
|
||||
//
|
||||
// serializedObject.ApplyModifiedProperties ();
|
||||
|
||||
|
||||
|
||||
|
||||
// var current = target as SoftMaskable;
|
||||
var current = target as SoftMaskable;
|
||||
current.GetComponentsInChildren<Graphic> (true, s_Graphics);
|
||||
var fixTargets = s_Graphics.Where (x => x.gameObject != current.gameObject && !x.GetComponent<SoftMaskable> () && (!x.GetComponent<Mask> () || x.GetComponent<Mask> ().showMaskGraphic)).ToList ();
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Coffee.UIExtensions
|
|||
/// Soft mask.
|
||||
/// Use instead of Mask for smooth masking.
|
||||
/// </summary>
|
||||
public class SoftMask : Mask, IMeshModifier, ICanvasRaycastFilter
|
||||
public class SoftMask : Mask, IMeshModifier
|
||||
{
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
|
@ -106,7 +106,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
m_IgnoreParent = value;
|
||||
hasChanged = true;
|
||||
OnTransformParentChanged ();
|
||||
OnTransformParentChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,9 +132,9 @@ namespace Coffee.UIExtensions
|
|||
ReleaseRT(ref _softMaskBuffer);
|
||||
}
|
||||
|
||||
if(!_softMaskBuffer)
|
||||
if (!_softMaskBuffer)
|
||||
{
|
||||
_softMaskBuffer = RenderTexture.GetTemporary (w, h, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
|
||||
_softMaskBuffer = RenderTexture.GetTemporary(w, h, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
private set
|
||||
{
|
||||
if(_parent)
|
||||
if (_parent)
|
||||
{
|
||||
_parent.hasChanged = value;
|
||||
}
|
||||
|
@ -158,6 +158,15 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
public SoftMask parent
|
||||
{
|
||||
get
|
||||
{
|
||||
return _parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Perform material modification in this function.
|
||||
/// </summary>
|
||||
|
@ -203,34 +212,23 @@ namespace Coffee.UIExtensions
|
|||
/// <param name="sp">Screen position.</param>
|
||||
/// <param name="eventCamera">Raycast camera.</param>
|
||||
/// <param name="g">Target graphic.</param>
|
||||
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera, Graphic g)
|
||||
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera, Graphic g, int[] interactions)
|
||||
{
|
||||
if (!isActiveAndEnabled || (g == graphic && !g.raycastTarget))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = (int)(softMaskBuffer.width * sp.x / Screen.width);
|
||||
int y = (int)(softMaskBuffer.height * sp.y / Screen.height);
|
||||
return 0.5f < GetPixelValue(x, y);
|
||||
return 0.5f < GetPixelValue(x, y, interactions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a point and a camera is the raycast valid.
|
||||
/// </summary>
|
||||
/// <returns>Valid.</returns>
|
||||
/// <param name="sp">Screen position.</param>
|
||||
/// <param name="eventCamera">Raycast camera.</param>
|
||||
public override bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
|
||||
{
|
||||
return IsRaycastLocationValid(sp, eventCamera, graphic);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Protected Members.
|
||||
//################################
|
||||
|
@ -329,12 +327,12 @@ namespace Coffee.UIExtensions
|
|||
hasChanged = true;
|
||||
}
|
||||
|
||||
protected override void OnRectTransformDimensionsChange ()
|
||||
protected override void OnRectTransformDimensionsChange()
|
||||
{
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
|
||||
/// </summary>
|
||||
|
@ -382,13 +380,13 @@ namespace Coffee.UIExtensions
|
|||
continue;
|
||||
|
||||
var rt = sm.rectTransform;
|
||||
if(rt.hasChanged)
|
||||
if (rt.hasChanged)
|
||||
{
|
||||
rt.hasChanged = false;
|
||||
sm.hasChanged = true;
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
if(!Application.isPlaying)
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
sm.hasChanged = true;
|
||||
}
|
||||
|
@ -403,7 +401,7 @@ namespace Coffee.UIExtensions
|
|||
sm._hasChanged = false;
|
||||
if (!sm._parent)
|
||||
{
|
||||
sm.UpdateMaskTexture ();
|
||||
sm.UpdateMaskTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,13 +411,12 @@ namespace Coffee.UIExtensions
|
|||
/// </summary>
|
||||
void UpdateMaskTexture()
|
||||
{
|
||||
if(!graphic || !graphic.canvas)
|
||||
if (!graphic || !graphic.canvas)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transform stopAfter = MaskUtilities.FindRootSortOverrideCanvas(transform);
|
||||
_stencilDepth = MaskUtilities.GetStencilDepth(transform, stopAfter);
|
||||
_stencilDepth = MaskUtilities.GetStencilDepth(transform, MaskUtilities.FindRootSortOverrideCanvas(transform));
|
||||
|
||||
// Collect children soft masks.
|
||||
int depth = 0;
|
||||
|
@ -448,9 +445,9 @@ namespace Coffee.UIExtensions
|
|||
else
|
||||
{
|
||||
var pos = c.transform.localPosition;
|
||||
var vm = Matrix4x4.TRS (-pos, Quaternion.identity, new Vector3 (1, 1, -1f));
|
||||
var pm = Matrix4x4.TRS (new Vector3 (0, 0, -1), Quaternion.identity, new Vector3 (1 / pos.x, 1 / pos.y, -2 / 1000f));
|
||||
_cb.SetViewProjectionMatrices (vm, pm);
|
||||
var vm = Matrix4x4.TRS(-pos, Quaternion.identity, new Vector3(1, 1, -1f));
|
||||
var pm = Matrix4x4.TRS(new Vector3(0, 0, -1), Quaternion.identity, new Vector3(1 / pos.x, 1 / pos.y, -2 / 1000f));
|
||||
_cb.SetViewProjectionMatrices(vm, pm);
|
||||
}
|
||||
|
||||
// Draw soft masks.
|
||||
|
@ -461,6 +458,11 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
var sm = s_TmpSoftMasks[i][j];
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
sm._stencilDepth = MaskUtilities.GetStencilDepth(sm.transform, MaskUtilities.FindRootSortOverrideCanvas(sm.transform));
|
||||
}
|
||||
|
||||
// Set material property.
|
||||
sm.material.SetInt(s_ColorMaskId, (int)1 << (3 - _stencilDepth - i));
|
||||
sm._mpb.SetTexture(s_MainTexId, sm.graphic.mainTexture);
|
||||
|
@ -562,7 +564,7 @@ namespace Coffee.UIExtensions
|
|||
/// <summary>
|
||||
/// Gets the pixel value.
|
||||
/// </summary>
|
||||
float GetPixelValue(int x, int y)
|
||||
float GetPixelValue(int x, int y, int[] interactions)
|
||||
{
|
||||
if (!s_ReadTexture)
|
||||
{
|
||||
|
@ -576,18 +578,23 @@ namespace Coffee.UIExtensions
|
|||
RenderTexture.active = currentRT;
|
||||
|
||||
var colors = s_ReadTexture.GetRawTextureData();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
switch (interactions[(i + 3)%4])
|
||||
{
|
||||
case 0: colors[i] = 255; break;
|
||||
case 2: colors[i] = (byte)(255 - colors[i]); break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (_stencilDepth)
|
||||
{
|
||||
case 0:
|
||||
return (colors[1] / 255f);
|
||||
case 1:
|
||||
return (colors[1] / 255f) * (colors[2] / 255f);
|
||||
case 2:
|
||||
return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f);
|
||||
case 3:
|
||||
return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f) * (colors[0] / 255f);
|
||||
default:
|
||||
return 0;
|
||||
case 0: return (colors[1] / 255f);
|
||||
case 1: return (colors[1] / 255f) * (colors[2] / 255f);
|
||||
case 2: return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f);
|
||||
case 3: return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f) * (colors[0] / 255f);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
|
@ -11,20 +13,27 @@ namespace Coffee.UIExtensions
|
|||
/// Add this component to Graphic under SoftMask for smooth masking.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter
|
||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter, ISerializationCallbackReceiver
|
||||
{
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||
static Material defaultMaterial = null;
|
||||
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
||||
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
|
||||
|
||||
//################################
|
||||
// Serialize Members.
|
||||
//################################
|
||||
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
||||
[System.Obsolete]
|
||||
[HideInInspector]
|
||||
[SerializeField] bool m_Inverse = false;
|
||||
[Tooltip("The interaction for each masks.")]
|
||||
[HideInInspector]
|
||||
[SerializeField] int m_MaskInteraction = kVisibleInside;
|
||||
[Tooltip("Use stencil for masking.")]
|
||||
[SerializeField] bool m_UseStencil = true;
|
||||
|
||||
|
||||
//################################
|
||||
|
@ -62,17 +71,13 @@ namespace Coffee.UIExtensions
|
|||
result = new Material(baseMaterial);
|
||||
result.hideFlags = HideFlags.HideAndDontSave;
|
||||
result.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
||||
|
||||
if (m_Inverse)
|
||||
{
|
||||
result.SetFloat(s_SoftMaskInverseId, 1);
|
||||
result.SetInt(s_StencilCompId, (int)CompareFunction.Always);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SetFloat(s_SoftMaskInverseId, 0);
|
||||
result.SetInt(s_StencilCompId, (int)CompareFunction.Equal);
|
||||
}
|
||||
result.SetInt(s_StencilCompId, m_UseStencil ? (int)CompareFunction.Equal : (int)CompareFunction.Always);
|
||||
result.SetVector(s_MaskInteractionId, new Vector4(
|
||||
(m_MaskInteraction & 0x3),
|
||||
((m_MaskInteraction >> 2) & 0x3),
|
||||
((m_MaskInteraction >> 4) & 0x3),
|
||||
((m_MaskInteraction >> 6) & 0x3)
|
||||
));
|
||||
|
||||
StencilMaterial.Remove(baseMaterial);
|
||||
ReleaseMaterial(ref _maskMaterial);
|
||||
|
@ -103,22 +108,34 @@ namespace Coffee.UIExtensions
|
|||
return true;
|
||||
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic) != m_Inverse;
|
||||
var sm = _softMask;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
s_Interactions[i] = sm ? ((m_MaskInteraction >> i * 2) & 0x3) : 0;
|
||||
sm = sm ? sm.parent : null;
|
||||
}
|
||||
|
||||
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic, s_Interactions);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The graphic will be visible only in areas where no mask is present.
|
||||
/// </summary>
|
||||
[System.Obsolete("Use SetMaskInteractions method instead.")]
|
||||
public bool inverse
|
||||
{
|
||||
get { return m_Inverse; }
|
||||
get { return m_MaskInteraction == kVisibleOutside; }
|
||||
set
|
||||
{
|
||||
if (m_Inverse != value)
|
||||
int intValue = value ? kVisibleOutside : kVisibleInside;
|
||||
if (m_MaskInteraction != intValue)
|
||||
{
|
||||
m_Inverse = value;
|
||||
m_MaskInteraction = intValue;
|
||||
graphic.SetMaterialDirty();
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +146,25 @@ namespace Coffee.UIExtensions
|
|||
/// </summary>
|
||||
public Graphic graphic{ get { return _graphic ? _graphic : _graphic = GetComponent<Graphic>(); } }
|
||||
|
||||
/// <summary>
|
||||
/// Set the interaction for each mask.
|
||||
/// </summary>
|
||||
public void SetMaskInteraction(SpriteMaskInteraction intr)
|
||||
{
|
||||
SetMaskInteraction(intr, intr, intr, intr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the interaction for each mask.
|
||||
/// </summary>
|
||||
public void SetMaskInteraction(SpriteMaskInteraction layer0, SpriteMaskInteraction layer1, SpriteMaskInteraction layer2, SpriteMaskInteraction layer3)
|
||||
{
|
||||
m_MaskInteraction = (int)layer0 + ((int)layer1 << 2) + ((int)layer2 << 4) + ((int)layer3 << 6);
|
||||
if (graphic)
|
||||
{
|
||||
graphic.SetMaterialDirty();
|
||||
}
|
||||
}
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
|
@ -138,7 +174,10 @@ namespace Coffee.UIExtensions
|
|||
Material _maskMaterial = null;
|
||||
static int s_SoftMaskTexId;
|
||||
static int s_StencilCompId;
|
||||
static int s_SoftMaskInverseId;
|
||||
static int s_MaskInteractionId;
|
||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||
static int[] s_Interactions = new int[4];
|
||||
static Material s_DefaultMaterial;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
|
@ -158,13 +197,13 @@ namespace Coffee.UIExtensions
|
|||
|
||||
foreach (var sm in s_ActiveSoftMaskables)
|
||||
{
|
||||
if(sm)
|
||||
if (sm)
|
||||
{
|
||||
Material mat = sm._maskMaterial;
|
||||
if (mat)
|
||||
{
|
||||
mat.SetMatrix ("_SceneView", w2c);
|
||||
mat.SetMatrix ("_SceneProj", prj);
|
||||
mat.SetMatrix("_SceneView", w2c);
|
||||
mat.SetMatrix("_SceneProj", prj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +237,7 @@ namespace Coffee.UIExtensions
|
|||
|
||||
s_SoftMaskTexId = Shader.PropertyToID("_SoftMaskTex");
|
||||
s_StencilCompId = Shader.PropertyToID("_StencilComp");
|
||||
s_SoftMaskInverseId = Shader.PropertyToID("_SoftMaskInverse");
|
||||
s_MaskInteractionId = Shader.PropertyToID("_MaskInteraction");
|
||||
}
|
||||
s_ActiveSoftMaskables.Add(this);
|
||||
|
||||
|
@ -208,7 +247,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
if (!g.material || g.material == Graphic.defaultGraphicMaterial)
|
||||
{
|
||||
g.material = defaultMaterial ?? (defaultMaterial = new Material (Resources.Load<Shader> ("UI-Default-SoftMask")) { hideFlags = HideFlags.HideAndDontSave, });
|
||||
g.material = s_DefaultMaterial ?? (s_DefaultMaterial = new Material(Resources.Load<Shader>("UI-Default-SoftMask")) { hideFlags = HideFlags.HideAndDontSave, });
|
||||
}
|
||||
g.SetMaterialDirty();
|
||||
}
|
||||
|
@ -225,7 +264,7 @@ namespace Coffee.UIExtensions
|
|||
var g = graphic;
|
||||
if (g)
|
||||
{
|
||||
if (g.material == defaultMaterial)
|
||||
if (g.material == s_DefaultMaterial)
|
||||
{
|
||||
g.material = null;
|
||||
}
|
||||
|
@ -258,5 +297,19 @@ namespace Coffee.UIExtensions
|
|||
mat = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
if (m_Inverse)
|
||||
{
|
||||
m_Inverse = false;
|
||||
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,11 +2,10 @@
|
|||
#define UI_SOFTMASK_INCLUDED
|
||||
|
||||
sampler2D _SoftMaskTex;
|
||||
fixed _SoftMaskInverse;
|
||||
float _Stencil;
|
||||
float4x4 _SceneView;
|
||||
float4x4 _SceneProj;
|
||||
|
||||
half4 _MaskInteraction;
|
||||
|
||||
fixed Approximately(float4x4 a, float4x4 b)
|
||||
{
|
||||
|
@ -19,20 +18,25 @@ fixed Approximately(float4x4 a, float4x4 b)
|
|||
0.01);
|
||||
}
|
||||
|
||||
fixed GetMaskAlpha(fixed alpha, fixed stencilId, fixed interaction)
|
||||
{
|
||||
fixed onStencil = step(stencilId, _Stencil);
|
||||
alpha = lerp(1, alpha, onStencil * step(1, interaction));
|
||||
return lerp(alpha, 1 - alpha, onStencil * step(2, interaction));
|
||||
}
|
||||
|
||||
half SoftMask(float4 clipPos)
|
||||
{
|
||||
half2 view = clipPos.xy/_ScreenParams.xy;
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
view.y = 1.0 - view.y;
|
||||
#endif
|
||||
|
||||
half alpha =
|
||||
lerp(1, tex2D(_SoftMaskTex, view).a, step(15, _Stencil))
|
||||
* lerp(1, tex2D(_SoftMaskTex, view).b, step(7, _Stencil))
|
||||
* lerp(1, tex2D(_SoftMaskTex, view).g, step(3, _Stencil))
|
||||
* lerp(1, tex2D(_SoftMaskTex, view).r, step(1, _Stencil));
|
||||
|
||||
alpha = lerp(alpha, 1 - alpha, _SoftMaskInverse);
|
||||
fixed4 mask = tex2D(_SoftMaskTex, view);
|
||||
half alpha = GetMaskAlpha(mask.x, 1, _MaskInteraction.x)
|
||||
* GetMaskAlpha(mask.y, 3, _MaskInteraction.y)
|
||||
* GetMaskAlpha(mask.z, 7, _MaskInteraction.z)
|
||||
* GetMaskAlpha(mask.w, 15, _MaskInteraction.w);
|
||||
|
||||
#if SOFTMASK_EDITOR
|
||||
fixed isSceneView = max(Approximately(UNITY_MATRIX_V, _SceneView), Approximately(UNITY_MATRIX_P, _SceneProj));
|
||||
|
@ -42,5 +46,4 @@ half SoftMask(float4 clipPos)
|
|||
return alpha;
|
||||
}
|
||||
|
||||
|
||||
#endif // UI_SOFTMASK_INCLUDED
|
||||
#endif // UI_SOFTMASK_INCLUDED
|
Loading…
Reference in New Issue