refactor: refactor
parent
0347b04fb7
commit
e65bbb1cef
|
@ -5,55 +5,55 @@ using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Coffee.UISoftMask.Demos
|
namespace Coffee.UISoftMask.Demos
|
||||||
{
|
{
|
||||||
public class SoftMask_Demo : MonoBehaviour
|
public class SoftMask_Demo : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] RawImage[] softMaskBufferViewer;
|
[SerializeField] RawImage[] softMaskBufferViewer;
|
||||||
[SerializeField] SoftMask[] softMask;
|
[SerializeField] SoftMask[] softMask;
|
||||||
[SerializeField] Text text;
|
[SerializeField] Text text;
|
||||||
[SerializeField] GameObject title;
|
[SerializeField] GameObject title;
|
||||||
|
|
||||||
|
|
||||||
// Use this for initialization
|
// Use this for initialization
|
||||||
void OnEnable()
|
void OnEnable()
|
||||||
{
|
{
|
||||||
title.SetActive(true);
|
title.SetActive(true);
|
||||||
|
|
||||||
text.text = string.Format("GPU: {0}\nDeviceType: {1}\nShaderLevel: {2}\nUVStartsAtTop: {3}",
|
text.text = string.Format("GPU: {0}\nDeviceType: {1}\nShaderLevel: {2}\nUVStartsAtTop: {3}",
|
||||||
SystemInfo.graphicsDeviceName,
|
SystemInfo.graphicsDeviceName,
|
||||||
SystemInfo.graphicsDeviceType,
|
SystemInfo.graphicsDeviceType,
|
||||||
SystemInfo.graphicsShaderLevel,
|
SystemInfo.graphicsShaderLevel,
|
||||||
SystemInfo.graphicsUVStartsAtTop);
|
SystemInfo.graphicsUVStartsAtTop);
|
||||||
|
|
||||||
for (int i = 0; i < softMask.Length; i++)
|
for (int i = 0; i < softMask.Length; i++)
|
||||||
{
|
{
|
||||||
softMaskBufferViewer[i].texture = softMask[i].softMaskBuffer;
|
softMaskBufferViewer[i].texture = softMask[i].softMaskBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWorldSpase(bool flag)
|
public void SetWorldSpase(bool flag)
|
||||||
{
|
{
|
||||||
if(flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
GetComponent<Canvas> ().renderMode = RenderMode.ScreenSpaceCamera;
|
GetComponent<Canvas>().renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
GetComponent<Canvas> ().renderMode = RenderMode.WorldSpace;
|
GetComponent<Canvas>().renderMode = RenderMode.WorldSpace;
|
||||||
transform.rotation = Quaternion.Euler (new Vector3 (0, 6, 0));
|
transform.rotation = Quaternion.Euler(new Vector3(0, 6, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetScreenSpase (bool flag)
|
public void SetScreenSpase(bool flag)
|
||||||
{
|
{
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
GetComponent<Canvas> ().renderMode = RenderMode.ScreenSpaceCamera;
|
GetComponent<Canvas>().renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetOverlay (bool flag)
|
public void SetOverlay(bool flag)
|
||||||
{
|
{
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
GetComponent<Canvas> ().renderMode = RenderMode.ScreenSpaceOverlay;
|
GetComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,57 @@
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#if UNITY_2018_3_OR_NEWER
|
||||||
using UnityEditor.Experimental.SceneManagement;
|
using UnityEditor.Experimental.SceneManagement;
|
||||||
#endif
|
#endif
|
||||||
|
using UnityEditor;
|
||||||
using UnityEditor.SceneManagement;
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
namespace Coffee.UISoftMask
|
namespace Coffee.UISoftMask
|
||||||
{
|
{
|
||||||
public static class EditorUtils
|
internal static class EditorUtils
|
||||||
{
|
{
|
||||||
public static void MarkPrefabDirty ()
|
internal static void MarkPrefabDirty()
|
||||||
{
|
{
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#if UNITY_2018_3_OR_NEWER
|
||||||
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage ();
|
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||||
if (prefabStage != null)
|
if (prefabStage == null) return;
|
||||||
{
|
EditorSceneManager.MarkSceneDirty(prefabStage.scene);
|
||||||
EditorSceneManager.MarkSceneDirty (prefabStage.scene);
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify whether it can be converted to the specified component.
|
||||||
|
/// </summary>
|
||||||
|
internal static bool CanConvertTo<T>(Object context) where T : MonoBehaviour
|
||||||
|
{
|
||||||
|
return context && context.GetType() != typeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert to the specified component.
|
||||||
|
/// </summary>
|
||||||
|
internal static void ConvertTo<T>(Object context) where T : MonoBehaviour
|
||||||
|
{
|
||||||
|
var target = context as MonoBehaviour;
|
||||||
|
var so = new SerializedObject(target);
|
||||||
|
so.Update();
|
||||||
|
|
||||||
|
bool oldEnable = target.enabled;
|
||||||
|
target.enabled = false;
|
||||||
|
|
||||||
|
// Find MonoScript of the specified component.
|
||||||
|
foreach (var script in Resources.FindObjectsOfTypeAll<MonoScript>())
|
||||||
|
{
|
||||||
|
if (script.GetClass() != typeof(T))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Set 'm_Script' to convert.
|
||||||
|
so.FindProperty("m_Script").objectReferenceValue = script;
|
||||||
|
so.ApplyModifiedProperties();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
(so.targetObject as MonoBehaviour).enabled = oldEnable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,128 +7,101 @@ using System.Linq;
|
||||||
|
|
||||||
namespace Coffee.UISoftMask
|
namespace Coffee.UISoftMask
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SoftMask editor.
|
/// SoftMask editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[CustomEditor(typeof(SoftMask))]
|
[CustomEditor(typeof(SoftMask))]
|
||||||
[CanEditMultipleObjects]
|
[CanEditMultipleObjects]
|
||||||
public class SoftMaskEditor : Editor
|
public class SoftMaskEditor : Editor
|
||||||
{
|
{
|
||||||
const string k_PrefsPreview = "SoftMaskEditor_Preview";
|
const string k_PrefsPreview = "SoftMaskEditor_Preview";
|
||||||
static readonly List<Graphic> s_Graphics = new List<Graphic> ();
|
static readonly List<Graphic> s_Graphics = new List<Graphic>();
|
||||||
static bool s_Preview;
|
static bool s_Preview;
|
||||||
|
|
||||||
private void OnEnable ()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
s_Preview = EditorPrefs.GetBool (k_PrefsPreview, false);
|
s_Preview = EditorPrefs.GetBool(k_PrefsPreview, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI ()
|
public override void OnInspectorGUI()
|
||||||
{
|
{
|
||||||
base.OnInspectorGUI ();
|
base.OnInspectorGUI();
|
||||||
|
|
||||||
var current = target as SoftMask;
|
var current = target as SoftMask;
|
||||||
current.GetComponentsInChildren<Graphic> (true, s_Graphics);
|
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 ();
|
var fixTargets = s_Graphics.Where(x =>
|
||||||
if (0 < fixTargets.Count)
|
x.gameObject != current.gameObject && !x.GetComponent<SoftMaskable>() &&
|
||||||
{
|
(!x.GetComponent<Mask>() || x.GetComponent<Mask>().showMaskGraphic)).ToList();
|
||||||
GUILayout.BeginHorizontal ();
|
if (0 < fixTargets.Count)
|
||||||
EditorGUILayout.HelpBox ("There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.", MessageType.Warning);
|
{
|
||||||
GUILayout.BeginVertical ();
|
GUILayout.BeginHorizontal();
|
||||||
if (GUILayout.Button ("Fix"))
|
EditorGUILayout.HelpBox(
|
||||||
{
|
"There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.",
|
||||||
foreach (var p in fixTargets)
|
MessageType.Warning);
|
||||||
{
|
GUILayout.BeginVertical();
|
||||||
p.gameObject.AddComponent<SoftMaskable> ();
|
if (GUILayout.Button("Fix"))
|
||||||
}
|
{
|
||||||
|
foreach (var p in fixTargets)
|
||||||
|
{
|
||||||
|
p.gameObject.AddComponent<SoftMaskable>();
|
||||||
|
}
|
||||||
|
|
||||||
EditorUtils.MarkPrefabDirty ();
|
EditorUtils.MarkPrefabDirty();
|
||||||
}
|
}
|
||||||
if (GUILayout.Button ("Ping"))
|
|
||||||
{
|
|
||||||
EditorGUIUtility.PingObject (fixTargets[0]);
|
|
||||||
}
|
|
||||||
GUILayout.EndVertical ();
|
|
||||||
GUILayout.EndHorizontal ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preview buffer.
|
if (GUILayout.Button("Ping"))
|
||||||
GUILayout.BeginHorizontal (EditorStyles.helpBox);
|
{
|
||||||
if (s_Preview != (s_Preview = EditorGUILayout.ToggleLeft ("Preview Buffer", s_Preview, GUILayout.MaxWidth (EditorGUIUtility.labelWidth))))
|
EditorGUIUtility.PingObject(fixTargets[0]);
|
||||||
{
|
}
|
||||||
EditorPrefs.SetBool (k_PrefsPreview, s_Preview);
|
|
||||||
}
|
GUILayout.EndVertical();
|
||||||
if (s_Preview)
|
GUILayout.EndHorizontal();
|
||||||
{
|
}
|
||||||
var tex = current.softMaskBuffer;
|
|
||||||
var width = tex.width * 64 / tex.height;
|
// Preview buffer.
|
||||||
EditorGUI.DrawPreviewTexture (GUILayoutUtility.GetRect (width, 64), tex, null, ScaleMode.ScaleToFit);
|
GUILayout.BeginHorizontal(EditorStyles.helpBox);
|
||||||
Repaint ();
|
if (s_Preview != (s_Preview = EditorGUILayout.ToggleLeft("Preview Buffer", s_Preview,
|
||||||
}
|
GUILayout.MaxWidth(EditorGUIUtility.labelWidth))))
|
||||||
GUILayout.FlexibleSpace ();
|
{
|
||||||
GUILayout.EndHorizontal ();
|
EditorPrefs.SetBool(k_PrefsPreview, s_Preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_Preview)
|
||||||
|
{
|
||||||
|
var tex = current.softMaskBuffer;
|
||||||
|
var width = tex.width * 64 / tex.height;
|
||||||
|
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(width, 64), tex, null, ScaleMode.ScaleToFit);
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//%%%% Context menu for editor %%%%
|
//%%%% Context menu for editor %%%%
|
||||||
[MenuItem("CONTEXT/Mask/Convert To SoftMask", true)]
|
[MenuItem("CONTEXT/Mask/Convert To SoftMask", true)]
|
||||||
static bool _ConvertToSoftMask(MenuCommand command)
|
static bool _ConvertToSoftMask(MenuCommand command)
|
||||||
{
|
{
|
||||||
return CanConvertTo<SoftMask>(command.context);
|
return EditorUtils.CanConvertTo<SoftMask>(command.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("CONTEXT/Mask/Convert To SoftMask", false)]
|
[MenuItem("CONTEXT/Mask/Convert To SoftMask", false)]
|
||||||
static void ConvertToSoftMask(MenuCommand command)
|
static void ConvertToSoftMask(MenuCommand command)
|
||||||
{
|
{
|
||||||
ConvertTo<SoftMask>(command.context);
|
EditorUtils.ConvertTo<SoftMask>(command.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("CONTEXT/Mask/Convert To Mask", true)]
|
[MenuItem("CONTEXT/Mask/Convert To Mask", true)]
|
||||||
static bool _ConvertToMask(MenuCommand command)
|
static bool _ConvertToMask(MenuCommand command)
|
||||||
{
|
{
|
||||||
return CanConvertTo<Mask>(command.context);
|
return EditorUtils.CanConvertTo<Mask>(command.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("CONTEXT/Mask/Convert To Mask", false)]
|
[MenuItem("CONTEXT/Mask/Convert To Mask", false)]
|
||||||
static void ConvertToMask(MenuCommand command)
|
static void ConvertToMask(MenuCommand command)
|
||||||
{
|
{
|
||||||
ConvertTo<Mask>(command.context);
|
EditorUtils.ConvertTo<Mask>(command.context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// Verify whether it can be converted to the specified component.
|
|
||||||
/// </summary>
|
|
||||||
protected static bool CanConvertTo<T>(Object context)
|
|
||||||
where T : MonoBehaviour
|
|
||||||
{
|
|
||||||
return context && context.GetType() != typeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert to the specified component.
|
|
||||||
/// </summary>
|
|
||||||
protected static void ConvertTo<T>(Object context) where T : MonoBehaviour
|
|
||||||
{
|
|
||||||
var target = context as MonoBehaviour;
|
|
||||||
var so = new SerializedObject(target);
|
|
||||||
so.Update();
|
|
||||||
|
|
||||||
bool oldEnable = target.enabled;
|
|
||||||
target.enabled = false;
|
|
||||||
|
|
||||||
// Find MonoScript of the specified component.
|
|
||||||
foreach (var script in Resources.FindObjectsOfTypeAll<MonoScript>())
|
|
||||||
{
|
|
||||||
if (script.GetClass() != typeof(T))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Set 'm_Script' to convert.
|
|
||||||
so.FindProperty("m_Script").objectReferenceValue = script;
|
|
||||||
so.ApplyModifiedProperties();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
(so.targetObject as MonoBehaviour).enabled = oldEnable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,403 +11,174 @@ using System.IO;
|
||||||
|
|
||||||
namespace Coffee.UISoftMask
|
namespace Coffee.UISoftMask
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SoftMaskable editor.
|
/// SoftMaskable editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[CustomEditor (typeof (SoftMaskable))]
|
[CustomEditor(typeof(SoftMaskable))]
|
||||||
[CanEditMultipleObjects]
|
[CanEditMultipleObjects]
|
||||||
public class SoftMaskableEditor : Editor
|
public class SoftMaskableEditor : Editor
|
||||||
{
|
{
|
||||||
//################################
|
public enum MaskInteraction : int
|
||||||
// Constant or Static Members.
|
{
|
||||||
//################################
|
VisibleInsideMask = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6),
|
||||||
public enum MaskInteraction : int
|
VisibleOutsideMask = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6),
|
||||||
{
|
Custom = -1,
|
||||||
VisibleInsideMask = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6),
|
}
|
||||||
VisibleOutsideMask = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6),
|
|
||||||
Custom = -1,
|
|
||||||
}
|
|
||||||
|
|
||||||
MaskInteraction maskInteraction
|
MaskInteraction maskInteraction
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int value = _spMaskInteraction.intValue;
|
int value = _spMaskInteraction.intValue;
|
||||||
return _custom
|
return _custom
|
||||||
? MaskInteraction.Custom
|
? MaskInteraction.Custom
|
||||||
: System.Enum.IsDefined(typeof(MaskInteraction), value)
|
: System.Enum.IsDefined(typeof(MaskInteraction), value)
|
||||||
? (MaskInteraction)value
|
? (MaskInteraction) value
|
||||||
: MaskInteraction.Custom;
|
: MaskInteraction.Custom;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_custom = (value == MaskInteraction.Custom);
|
_custom = (value == MaskInteraction.Custom);
|
||||||
if (!_custom)
|
if (!_custom)
|
||||||
{
|
{
|
||||||
_spMaskInteraction.intValue = (int)value;
|
_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");
|
bool _custom = false;
|
||||||
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");
|
|
||||||
static readonly Type s_TypeTMP_SubMesh = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_SubMesh");
|
|
||||||
static readonly Type s_TypeTMP_SubMeshUI = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_SubMeshUI");
|
|
||||||
static PropertyInfo s_PiFontSharedMaterial;
|
|
||||||
static PropertyInfo s_PiFontSharedMaterials;
|
|
||||||
static PropertyInfo s_PiSpriteAsset;
|
|
||||||
static PropertyInfo s_PiRichText;
|
|
||||||
static PropertyInfo s_PiText;
|
|
||||||
static PropertyInfo s_PiDefaultFontAssetPath;
|
|
||||||
static PropertyInfo s_PiDefaultSpriteAssetPath;
|
|
||||||
static FieldInfo s_FiMaterial;
|
|
||||||
static MethodInfo s_miGetSpriteAsset;
|
|
||||||
static readonly List<Graphic> s_Graphics = new List<Graphic> ();
|
|
||||||
Shader _shader;
|
|
||||||
Shader _mobileShader;
|
|
||||||
Shader _spriteShader;
|
|
||||||
List<MaterialEditor> _materialEditors = new List<MaterialEditor> ();
|
|
||||||
SerializedProperty _spMaskInteraction;
|
|
||||||
|
|
||||||
void OnEnable ()
|
static readonly List<Graphic> s_Graphics = new List<Graphic>();
|
||||||
{
|
SerializedProperty _spMaskInteraction;
|
||||||
_spMaskInteraction = serializedObject.FindProperty("m_MaskInteraction");
|
List<Mask> tmpMasks = new List<Mask>();
|
||||||
_custom = (maskInteraction == MaskInteraction.Custom);
|
static GUIContent s_MaskWarning;
|
||||||
|
|
||||||
ClearMaterialEditors ();
|
|
||||||
|
|
||||||
_shader = Shader.Find ("TextMeshPro/Distance Field (SoftMaskable)");
|
|
||||||
_mobileShader = Shader.Find ("TextMeshPro/Mobile/Distance Field (SoftMaskable)");
|
|
||||||
_spriteShader = Shader.Find ("TextMeshPro/Sprite (SoftMaskable)");
|
|
||||||
|
|
||||||
if(s_TypeTMPro != null)
|
|
||||||
{
|
|
||||||
s_PiFontSharedMaterial = s_TypeTMPro.GetProperty ("fontSharedMaterial");
|
|
||||||
s_PiSpriteAsset = s_TypeTMPro.GetProperty ("spriteAsset");
|
|
||||||
s_PiRichText = s_TypeTMPro.GetProperty ("richText");
|
|
||||||
s_PiText = s_TypeTMPro.GetProperty ("text");
|
|
||||||
s_FiMaterial = s_TypeTMP_SpriteAsset.GetField ("material");
|
|
||||||
s_PiFontSharedMaterials = s_TypeTMPro.GetProperty ("fontSharedMaterials");
|
|
||||||
s_miGetSpriteAsset = s_TypeTMProSettings.GetMethod ("GetSpriteAsset", BindingFlags.Static | BindingFlags.Public);
|
|
||||||
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnDisable ()
|
|
||||||
{
|
|
||||||
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 ();
|
|
||||||
|
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
_spMaskInteraction = serializedObject.FindProperty("m_MaskInteraction");
|
||||||
|
_custom = (maskInteraction == MaskInteraction.Custom);
|
||||||
|
s_MaskWarning = new GUIContent(EditorGUIUtility.FindTexture("console.warnicon.sml"),
|
||||||
|
"This is not a SoftMask component.");
|
||||||
|
}
|
||||||
|
|
||||||
var current = target as SoftMaskable;
|
|
||||||
|
|
||||||
current.GetComponentsInChildren<Graphic> (true, s_Graphics);
|
private void DrawMaskInteractions()
|
||||||
var fixTargets = s_Graphics.Where (x => x.gameObject != current.gameObject && !x.GetComponent<SoftMaskable> () && (!x.GetComponent<Mask> () || x.GetComponent<Mask> ().showMaskGraphic)).ToList ();
|
{
|
||||||
if (0 < fixTargets.Count)
|
var softMaskable = target as SoftMaskable;
|
||||||
{
|
if (softMaskable == null) return;
|
||||||
GUILayout.BeginHorizontal ();
|
|
||||||
EditorGUILayout.HelpBox ("There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.", MessageType.Warning);
|
|
||||||
GUILayout.BeginVertical ();
|
|
||||||
if (GUILayout.Button ("Fix"))
|
|
||||||
{
|
|
||||||
foreach (var p in fixTargets)
|
|
||||||
{
|
|
||||||
p.gameObject.AddComponent<SoftMaskable> ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (GUILayout.Button ("Ping"))
|
|
||||||
{
|
|
||||||
EditorGUIUtility.PingObject (fixTargets [0]);
|
|
||||||
}
|
|
||||||
GUILayout.EndVertical ();
|
|
||||||
GUILayout.EndHorizontal ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s_TypeTMPro != null)
|
softMaskable.GetComponentsInParent<Mask>(true, tmpMasks);
|
||||||
{
|
tmpMasks.RemoveAll(x => !x.enabled);
|
||||||
ShowTMProWarning (_shader, _mobileShader, _spriteShader, m => { });
|
tmpMasks.Reverse();
|
||||||
var textMeshPro = current.GetComponent (s_TypeTMPro);
|
|
||||||
if (textMeshPro != null)
|
|
||||||
{
|
|
||||||
Material [] fontSharedMaterials = s_PiFontSharedMaterials.GetValue (textMeshPro, new object [0]) as Material [];
|
|
||||||
ShowMaterialEditors (fontSharedMaterials, 1, fontSharedMaterials.Length - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DetectMask (current.transform.parent))
|
maskInteraction = (MaskInteraction) EditorGUILayout.EnumPopup("Mask Interaction", maskInteraction);
|
||||||
{
|
if (!_custom) return;
|
||||||
GUILayout.BeginHorizontal ();
|
|
||||||
EditorGUILayout.HelpBox ("This is unnecessary SoftMaskable.\nCan't find any SoftMask components above.", MessageType.Warning);
|
|
||||||
if (GUILayout.Button ("Remove", GUILayout.Height (40)))
|
|
||||||
{
|
|
||||||
DestroyImmediate (current);
|
|
||||||
|
|
||||||
EditorUtils.MarkPrefabDirty ();
|
var l = EditorGUIUtility.labelWidth;
|
||||||
}
|
EditorGUIUtility.labelWidth = 45;
|
||||||
GUILayout.EndHorizontal ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool DetectMask (Transform transform)
|
using (var ccs = new EditorGUI.ChangeCheckScope())
|
||||||
{
|
{
|
||||||
if (transform == null)
|
int intr0 = DrawMaskInteraction(0);
|
||||||
{
|
int intr1 = DrawMaskInteraction(1);
|
||||||
return false;
|
int intr2 = DrawMaskInteraction(2);
|
||||||
}
|
int intr3 = DrawMaskInteraction(3);
|
||||||
|
|
||||||
if (transform.GetComponent<SoftMask> () != null)
|
if (ccs.changed)
|
||||||
{
|
{
|
||||||
return true;
|
_spMaskInteraction.intValue = (intr0 << 0) + (intr1 << 2) + (intr2 << 4) + (intr3 << 6);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return DetectMask (transform.parent);
|
EditorGUIUtility.labelWidth = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearMaterialEditors ()
|
|
||||||
{
|
|
||||||
foreach (var e in _materialEditors)
|
|
||||||
{
|
|
||||||
if (e)
|
|
||||||
{
|
|
||||||
DestroyImmediate (e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_materialEditors.Clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void ShowMaterialEditors (Material [] materials, int startIndex, int count)
|
private int DrawMaskInteraction(int layer)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
Mask mask = layer < tmpMasks.Count ? tmpMasks[layer] : null;
|
||||||
{
|
MaskIntr intr = (MaskIntr) ((_spMaskInteraction.intValue >> layer * 2) & 0x3);
|
||||||
if (_materialEditors.Count == i)
|
if (!mask)
|
||||||
{
|
{
|
||||||
_materialEditors.Add (null);
|
return (int) intr;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mat = materials [startIndex + i];
|
using (new EditorGUILayout.HorizontalScope())
|
||||||
var editor = _materialEditors [i];
|
{
|
||||||
if (editor && editor.target != mat)
|
EditorGUILayout.LabelField(mask is SoftMask ? GUIContent.none : s_MaskWarning, GUILayout.Width(16));
|
||||||
{
|
GUILayout.Space(-5);
|
||||||
DestroyImmediate (editor);
|
EditorGUILayout.ObjectField("Mask " + layer, mask, typeof(Mask), false);
|
||||||
editor = null;
|
GUILayout.Space(-15);
|
||||||
}
|
return (int) (MaskIntr) EditorGUILayout.EnumPopup(intr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!editor)
|
public override void OnInspectorGUI()
|
||||||
{
|
{
|
||||||
editor = _materialEditors [i] = Editor.CreateEditor (mat) as MaterialEditor;
|
base.OnInspectorGUI();
|
||||||
}
|
|
||||||
|
|
||||||
editor.DrawHeader ();
|
serializedObject.Update();
|
||||||
editor.OnInspectorGUI ();
|
DrawMaskInteractions();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowTMProWarning (Shader shader, Shader mobileShader, Shader spriteShader, System.Action<Material> onCreatedMaterial)
|
serializedObject.ApplyModifiedProperties();
|
||||||
{
|
|
||||||
var current = target as SoftMaskable;
|
|
||||||
var textMeshPro = current.GetComponent (s_TypeTMPro);
|
|
||||||
if (textMeshPro == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Material fontSharedMaterial = s_PiFontSharedMaterial.GetValue (textMeshPro, new object [0]) as Material;
|
var current = target as SoftMaskable;
|
||||||
if (fontSharedMaterial == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the material preset for dissolve?
|
current.GetComponentsInChildren<Graphic>(true, s_Graphics);
|
||||||
Material m = fontSharedMaterial;
|
var fixTargets = s_Graphics.Where(x =>
|
||||||
if (m.shader != shader && m.shader != mobileShader)
|
x.gameObject != current.gameObject && !x.GetComponent<SoftMaskable>() &&
|
||||||
{
|
(!x.GetComponent<Mask>() || x.GetComponent<Mask>().showMaskGraphic)).ToList();
|
||||||
EditorGUILayout.BeginHorizontal ();
|
if (0 < fixTargets.Count)
|
||||||
EditorGUILayout.HelpBox (string.Format ("{0} requires '{1}' or '{2}' as a shader for material preset.", current.GetType ().Name, shader.name, mobileShader.name), MessageType.Warning);
|
{
|
||||||
if (GUILayout.Button ("Fix"))
|
GUILayout.BeginHorizontal();
|
||||||
{
|
EditorGUILayout.HelpBox(
|
||||||
var correctShader = m.shader.name.Contains ("Mobile") ? mobileShader : shader;
|
"There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.",
|
||||||
m = ModifyTMProMaterialPreset (m, correctShader, onCreatedMaterial);
|
MessageType.Warning);
|
||||||
s_PiFontSharedMaterial.SetValue (textMeshPro, m, new object [0]);
|
GUILayout.BeginVertical();
|
||||||
}
|
if (GUILayout.Button("Fix"))
|
||||||
EditorGUILayout.EndHorizontal ();
|
{
|
||||||
return;
|
foreach (var p in fixTargets)
|
||||||
}
|
{
|
||||||
|
p.gameObject.AddComponent<SoftMaskable>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Is the sprite asset for dissolve?
|
if (GUILayout.Button("Ping"))
|
||||||
object spriteAsset = s_PiSpriteAsset.GetValue (textMeshPro, new object [0]) ?? s_miGetSpriteAsset.Invoke (null, new object [0]);
|
{
|
||||||
//TMP_SpriteAsset spriteAsset = textMeshPro.spriteAsset ?? TMP_Settings.GetSpriteAsset ();
|
EditorGUIUtility.PingObject(fixTargets[0]);
|
||||||
m = s_FiMaterial.GetValue (spriteAsset) as Material;
|
}
|
||||||
bool hasSprite = (bool)s_PiRichText.GetValue (textMeshPro, new object [0]) && (s_PiText.GetValue (textMeshPro, new object [0]) as string).Contains ("<sprite=");
|
|
||||||
if (m && m.shader != spriteShader && hasSprite)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal ();
|
|
||||||
EditorGUILayout.HelpBox (string.Format ("{0} requires '{1}' as a shader for sprite asset.", GetType ().Name, spriteShader.name), MessageType.Warning);
|
|
||||||
if (GUILayout.Button ("Fix"))
|
|
||||||
{
|
|
||||||
current.GetComponentsInChildren (s_TypeTMP_SubMesh).Select (x => x.gameObject).ToList ().ForEach (DestroyImmediate);
|
|
||||||
current.GetComponentsInChildren (s_TypeTMP_SubMeshUI).Select (x => x.gameObject).ToList ().ForEach (DestroyImmediate);
|
|
||||||
spriteAsset = ModifyTMProSpriteAsset (m, _spriteShader, mat => { });
|
|
||||||
s_PiSpriteAsset.SetValue (textMeshPro, spriteAsset, new object [0]);
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Material ModifyTMProMaterialPreset (Material baseMaterial, Shader shader, System.Action<Material> onCreatedMaterial)
|
GUILayout.EndVertical();
|
||||||
{
|
GUILayout.EndHorizontal();
|
||||||
string path = AssetDatabase.GetAssetPath (baseMaterial);
|
}
|
||||||
string filename = Path.GetFileNameWithoutExtension (path) + " (" + typeof (SoftMaskable).Name + ")";
|
|
||||||
string defaultAssetPath = s_PiDefaultFontAssetPath.GetValue (null, new object [0]) as string;
|
|
||||||
Material mat = Resources.Load<Material> (defaultAssetPath + filename);
|
|
||||||
if (!mat)
|
|
||||||
{
|
|
||||||
mat = new Material (baseMaterial)
|
|
||||||
{
|
|
||||||
shaderKeywords = baseMaterial.shaderKeywords,
|
|
||||||
shader = shader,
|
|
||||||
};
|
|
||||||
onCreatedMaterial (mat);
|
|
||||||
AssetDatabase.CreateAsset (mat, Path.GetDirectoryName (path) + "/" + filename + ".mat");
|
|
||||||
|
|
||||||
EditorUtility.FocusProjectWindow ();
|
if (!DetectMask(current.transform.parent))
|
||||||
EditorGUIUtility.PingObject (mat);
|
{
|
||||||
}
|
GUILayout.BeginHorizontal();
|
||||||
else
|
EditorGUILayout.HelpBox("This is unnecessary SoftMaskable.\nCan't find any SoftMask components above.",
|
||||||
{
|
MessageType.Warning);
|
||||||
mat.shader = shader;
|
if (GUILayout.Button("Remove", GUILayout.Height(40)))
|
||||||
}
|
{
|
||||||
EditorUtility.SetDirty (mat);
|
DestroyImmediate(current);
|
||||||
return mat;
|
|
||||||
}
|
|
||||||
|
|
||||||
object ModifyTMProSpriteAsset (Material baseMaterial, Shader shader, System.Action<Material> onCreatedMaterial)
|
EditorUtils.MarkPrefabDirty();
|
||||||
{
|
}
|
||||||
string path = AssetDatabase.GetAssetPath (baseMaterial);
|
|
||||||
string filename = Path.GetFileNameWithoutExtension (path) + " (" + typeof (SoftMaskable).Name + ")";
|
|
||||||
string defaultAssetPath = s_PiDefaultSpriteAssetPath.GetValue (null, new object [0]) as string;
|
|
||||||
Object spriteAsset = Resources.Load (defaultAssetPath + filename, s_TypeTMP_SpriteAsset);
|
|
||||||
if (spriteAsset == null)
|
|
||||||
{
|
|
||||||
AssetDatabase.CopyAsset (path, Path.GetDirectoryName (path) + "/" + filename + ".mat");
|
|
||||||
spriteAsset = Resources.Load (defaultAssetPath + filename, s_TypeTMP_SpriteAsset);
|
|
||||||
Material m = s_FiMaterial.GetValue (spriteAsset) as Material;
|
|
||||||
m.shader = shader;
|
|
||||||
m.name = shader.name;
|
|
||||||
onCreatedMaterial (m);
|
|
||||||
|
|
||||||
EditorUtility.FocusProjectWindow ();
|
GUILayout.EndHorizontal();
|
||||||
EditorGUIUtility.PingObject (spriteAsset);
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
static bool DetectMask(Transform transform)
|
||||||
Material m = s_FiMaterial.GetValue (spriteAsset) as Material;
|
{
|
||||||
m.shader = shader;
|
while (transform)
|
||||||
}
|
{
|
||||||
EditorUtility.SetDirty (spriteAsset);
|
if (transform.GetComponent<SoftMask>()) return true;
|
||||||
return spriteAsset;
|
|
||||||
}
|
transform = transform.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,11 @@ namespace Coffee.UISoftMask
|
||||||
|
|
||||||
public class GraphicConnector
|
public class GraphicConnector
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly List<GraphicConnector> s_Connectors = new List<GraphicConnector>();
|
private static readonly List<GraphicConnector> s_Connectors = new List<GraphicConnector>();
|
||||||
private static readonly Dictionary<Type, GraphicConnector> s_ConnectorMap = new Dictionary<Type, GraphicConnector>();
|
|
||||||
|
private static readonly Dictionary<Type, GraphicConnector> s_ConnectorMap =
|
||||||
|
new Dictionary<Type, GraphicConnector>();
|
||||||
|
|
||||||
private static readonly GraphicConnector s_EmptyConnector = new GraphicConnector();
|
private static readonly GraphicConnector s_EmptyConnector = new GraphicConnector();
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
|
@ -74,7 +76,6 @@ namespace Coffee.UISoftMask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find effect shader.
|
/// Find effect shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,290 +6,283 @@ using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||||
|
|
||||||
namespace Coffee.UISoftMask
|
namespace Coffee.UISoftMask
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Soft maskable.
|
/// Soft maskable.
|
||||||
/// Add this component to Graphic under SoftMask for smooth masking.
|
/// Add this component to Graphic under SoftMask for smooth masking.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#if UNITY_2018_3_OR_NEWER
|
||||||
[ExecuteAlways]
|
[ExecuteAlways]
|
||||||
#else
|
#else
|
||||||
[ExecuteInEditMode]
|
[ExecuteInEditMode]
|
||||||
# endif
|
# endif
|
||||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter
|
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
, ISerializationCallbackReceiver
|
, ISerializationCallbackReceiver
|
||||||
# endif
|
# endif
|
||||||
{
|
{
|
||||||
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
||||||
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||||
static readonly Hash128 k_InvalidHash = new Hash128();
|
static readonly Hash128 k_InvalidHash = new Hash128();
|
||||||
|
|
||||||
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
static int s_SoftMaskTexId;
|
||||||
[System.Obsolete]
|
static int s_StencilCompId;
|
||||||
[HideInInspector]
|
static int s_MaskInteractionId;
|
||||||
[SerializeField] bool m_Inverse = false;
|
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||||
[Tooltip("The interaction for each masks.")]
|
static int[] s_Interactions = new int[4];
|
||||||
[HideInInspector]
|
|
||||||
[SerializeField] int m_MaskInteraction = kVisibleInside;
|
|
||||||
[Tooltip("Use stencil to mask.")]
|
|
||||||
[SerializeField] bool m_UseStencil = false;
|
|
||||||
[Tooltip("Use soft-masked raycast target.\n\nNote: This option is expensive.")]
|
|
||||||
[SerializeField] bool m_RaycastFilter = false;
|
|
||||||
|
|
||||||
Graphic _graphic = null;
|
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
||||||
SoftMask _softMask = null;
|
[System.Obsolete]
|
||||||
Material _maskMaterial = null;
|
[HideInInspector]
|
||||||
static int s_SoftMaskTexId;
|
[SerializeField]
|
||||||
static int s_StencilCompId;
|
bool m_Inverse = false;
|
||||||
static int s_MaskInteractionId;
|
|
||||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
|
||||||
static int[] s_Interactions = new int[4];
|
|
||||||
Hash128 _effectMaterialHash;
|
|
||||||
|
|
||||||
/// <summary>
|
[Tooltip("The interaction for each masks.")] [HideInInspector] [SerializeField]
|
||||||
/// Perform material modification in this function.
|
int m_MaskInteraction = kVisibleInside;
|
||||||
/// </summary>
|
|
||||||
/// <returns>Modified material.</returns>
|
|
||||||
/// <param name="baseMaterial">Configured Material.</param>
|
|
||||||
public Material GetModifiedMaterial(Material baseMaterial)
|
|
||||||
{
|
|
||||||
_softMask = null;
|
|
||||||
if (!isActiveAndEnabled)
|
|
||||||
{
|
|
||||||
return baseMaterial;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the nearest parent softmask.
|
[Tooltip("Use stencil to mask.")] [SerializeField]
|
||||||
var parentTransform = transform.parent;
|
bool m_UseStencil = false;
|
||||||
while (parentTransform)
|
|
||||||
{
|
|
||||||
var sm = parentTransform.GetComponent<SoftMask>();
|
|
||||||
if (sm && sm.enabled)
|
|
||||||
{
|
|
||||||
_softMask = sm;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
parentTransform = parentTransform.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var oldHash = _effectMaterialHash;
|
[Tooltip("Use soft-masked raycast target.\n\nNote: This option is expensive.")] [SerializeField]
|
||||||
var modifiedMaterial = baseMaterial;
|
bool m_RaycastFilter = false;
|
||||||
if (_softMask)
|
|
||||||
{
|
Graphic _graphic = null;
|
||||||
_effectMaterialHash = GetMaterialHash(baseMaterial);
|
SoftMask _softMask = null;
|
||||||
modifiedMaterial = MaterialCache.Register(baseMaterial, _effectMaterialHash, mat =>
|
Material _maskMaterial = null;
|
||||||
{
|
Hash128 _effectMaterialHash;
|
||||||
Debug.Log(mat.shader.name);
|
|
||||||
mat.shader = Shader.Find(string.Format("Hidden/{0} (SoftMaskable)", mat.shader.name));
|
/// <summary>
|
||||||
|
/// The graphic will be visible only in areas where no mask is present.
|
||||||
|
/// </summary>
|
||||||
|
public bool inverse
|
||||||
|
{
|
||||||
|
get { return m_MaskInteraction == kVisibleOutside; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var intValue = value ? kVisibleOutside : kVisibleInside;
|
||||||
|
if (m_MaskInteraction == intValue) return;
|
||||||
|
m_MaskInteraction = intValue;
|
||||||
|
graphic.SetMaterialDirtyEx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use soft-masked raycast target. This option is expensive.
|
||||||
|
/// </summary>
|
||||||
|
public bool raycastFilter
|
||||||
|
{
|
||||||
|
get { return m_RaycastFilter; }
|
||||||
|
set { m_RaycastFilter = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The graphic associated with the soft mask.
|
||||||
|
/// </summary>
|
||||||
|
public Graphic graphic
|
||||||
|
{
|
||||||
|
get { return _graphic ? _graphic : _graphic = GetComponent<Graphic>(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perform material modification in this function.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Modified material.</returns>
|
||||||
|
/// <param name="baseMaterial">Configured Material.</param>
|
||||||
|
Material IMaterialModifier.GetModifiedMaterial(Material baseMaterial)
|
||||||
|
{
|
||||||
|
_softMask = null;
|
||||||
|
if (!isActiveAndEnabled)
|
||||||
|
{
|
||||||
|
return baseMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the nearest parent softmask.
|
||||||
|
var parentTransform = transform.parent;
|
||||||
|
while (parentTransform)
|
||||||
|
{
|
||||||
|
var sm = parentTransform.GetComponent<SoftMask>();
|
||||||
|
if (sm && sm.enabled)
|
||||||
|
{
|
||||||
|
_softMask = sm;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
parentTransform = parentTransform.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldHash = _effectMaterialHash;
|
||||||
|
var modifiedMaterial = baseMaterial;
|
||||||
|
if (_softMask)
|
||||||
|
{
|
||||||
|
_effectMaterialHash = GetMaterialHash(baseMaterial);
|
||||||
|
modifiedMaterial = MaterialCache.Register(baseMaterial, _effectMaterialHash, mat =>
|
||||||
|
{
|
||||||
|
mat.shader = Shader.Find(string.Format("Hidden/{0} (SoftMaskable)", mat.shader.name));
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
mat.EnableKeyword("SOFTMASK_EDITOR");
|
mat.EnableKeyword("SOFTMASK_EDITOR");
|
||||||
#endif
|
#endif
|
||||||
mat.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
mat.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
||||||
mat.SetInt(s_StencilCompId, m_UseStencil ? (int)CompareFunction.Equal : (int)CompareFunction.Always);
|
mat.SetInt(s_StencilCompId,
|
||||||
mat.SetVector(s_MaskInteractionId, new Vector4(
|
m_UseStencil ? (int) CompareFunction.Equal : (int) CompareFunction.Always);
|
||||||
(m_MaskInteraction & 0x3),
|
mat.SetVector(s_MaskInteractionId, new Vector4(
|
||||||
((m_MaskInteraction >> 2) & 0x3),
|
(m_MaskInteraction & 0x3),
|
||||||
((m_MaskInteraction >> 4) & 0x3),
|
((m_MaskInteraction >> 2) & 0x3),
|
||||||
((m_MaskInteraction >> 6) & 0x3)
|
((m_MaskInteraction >> 4) & 0x3),
|
||||||
));
|
((m_MaskInteraction >> 6) & 0x3)
|
||||||
});
|
));
|
||||||
ReleaseMaterial(ref _maskMaterial);
|
});
|
||||||
_maskMaterial = modifiedMaterial;
|
ReleaseMaterial(ref _maskMaterial);
|
||||||
}
|
_maskMaterial = modifiedMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
MaterialCache.Unregister(oldHash);
|
MaterialCache.Unregister(oldHash);
|
||||||
return modifiedMaterial;
|
return modifiedMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Hash128 GetMaterialHash(Material material)
|
private Hash128 GetMaterialHash(Material material)
|
||||||
{
|
{
|
||||||
if (!isActiveAndEnabled || !material || !material.shader)
|
if (!isActiveAndEnabled || !material || !material.shader)
|
||||||
return k_InvalidHash;
|
return k_InvalidHash;
|
||||||
|
|
||||||
return new Hash128(
|
return new Hash128(
|
||||||
(uint) material.GetInstanceID(),
|
(uint) material.GetInstanceID(),
|
||||||
(uint) m_MaskInteraction,
|
(uint) m_MaskInteraction,
|
||||||
(uint) (m_UseStencil ? 1 : 0),
|
(uint) (m_UseStencil ? 1 : 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Given a point and a camera is the raycast valid.
|
/// Given a point and a camera is the raycast valid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Valid.</returns>
|
/// <returns>Valid.</returns>
|
||||||
/// <param name="sp">Screen position.</param>
|
/// <param name="sp">Screen position.</param>
|
||||||
/// <param name="eventCamera">Raycast camera.</param>
|
/// <param name="eventCamera">Raycast camera.</param>
|
||||||
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
|
bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
|
||||||
{
|
{
|
||||||
if (!isActiveAndEnabled || !_softMask)
|
if (!isActiveAndEnabled || !_softMask)
|
||||||
return true;
|
return true;
|
||||||
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
||||||
return false;
|
return false;
|
||||||
if (!m_RaycastFilter)
|
if (!m_RaycastFilter)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var sm = _softMask;
|
var sm = _softMask;
|
||||||
for (int i = 0; i < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
s_Interactions[i] = sm ? ((m_MaskInteraction >> i * 2) & 0x3) : 0;
|
s_Interactions[i] = sm ? ((m_MaskInteraction >> i * 2) & 0x3) : 0;
|
||||||
sm = sm ? sm.parent : null;
|
sm = sm ? sm.parent : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic, s_Interactions);
|
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic, s_Interactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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);
|
||||||
|
graphic.SetMaterialDirtyEx();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The graphic will be visible only in areas where no mask is present.
|
/// This function is called when the object becomes enabled and active.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool inverse
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
get { return m_MaskInteraction == kVisibleOutside; }
|
// Register.
|
||||||
set
|
if (s_ActiveSoftMaskables == null)
|
||||||
{
|
{
|
||||||
int intValue = value ? kVisibleOutside : kVisibleInside;
|
s_ActiveSoftMaskables = new List<SoftMaskable>();
|
||||||
if (m_MaskInteraction != intValue)
|
|
||||||
{
|
|
||||||
m_MaskInteraction = intValue;
|
|
||||||
graphic.SetMaterialDirtyEx();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
s_SoftMaskTexId = Shader.PropertyToID("_SoftMaskTex");
|
||||||
/// Use soft-masked raycast target. This option is expensive.
|
s_StencilCompId = Shader.PropertyToID("_StencilComp");
|
||||||
/// </summary>
|
s_MaskInteractionId = Shader.PropertyToID("_MaskInteraction");
|
||||||
public bool raycastFilter
|
}
|
||||||
{
|
|
||||||
get { return m_RaycastFilter; }
|
|
||||||
set { m_RaycastFilter = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
s_ActiveSoftMaskables.Add(this);
|
||||||
/// The graphic associated with the soft mask.
|
|
||||||
/// </summary>
|
|
||||||
public Graphic graphic{ get { return _graphic ? _graphic : _graphic = GetComponent<Graphic>(); } }
|
|
||||||
|
|
||||||
/// <summary>
|
graphic.SetMaterialDirtyEx();
|
||||||
/// Set the interaction for each mask.
|
_softMask = null;
|
||||||
/// </summary>
|
}
|
||||||
public void SetMaskInteraction(SpriteMaskInteraction intr)
|
|
||||||
{
|
|
||||||
SetMaskInteraction(intr, intr, intr, intr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the interaction for each mask.
|
/// This function is called when the behaviour becomes disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetMaskInteraction(SpriteMaskInteraction layer0, SpriteMaskInteraction layer1, SpriteMaskInteraction layer2, SpriteMaskInteraction layer3)
|
private void OnDisable()
|
||||||
{
|
{
|
||||||
m_MaskInteraction = (int)layer0 + ((int)layer1 << 2) + ((int)layer2 << 4) + ((int)layer3 << 6);
|
s_ActiveSoftMaskables.Remove(this);
|
||||||
graphic.SetMaterialDirtyEx();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
graphic.SetMaterialDirtyEx();
|
||||||
|
_softMask = null;
|
||||||
|
ReleaseMaterial(ref _maskMaterial);
|
||||||
|
|
||||||
/// <summary>
|
MaterialCache.Unregister(_effectMaterialHash);
|
||||||
/// This function is called when the object becomes enabled and active.
|
_effectMaterialHash = k_InvalidHash;
|
||||||
/// </summary>
|
}
|
||||||
void OnEnable()
|
|
||||||
{
|
|
||||||
// Register.
|
|
||||||
if (s_ActiveSoftMaskables == null)
|
|
||||||
{
|
|
||||||
s_ActiveSoftMaskables = new List<SoftMaskable>();
|
|
||||||
|
|
||||||
s_SoftMaskTexId = Shader.PropertyToID("_SoftMaskTex");
|
/// <summary>
|
||||||
s_StencilCompId = Shader.PropertyToID("_StencilComp");
|
/// Release the material.
|
||||||
s_MaskInteractionId = Shader.PropertyToID("_MaskInteraction");
|
/// </summary>
|
||||||
}
|
static void ReleaseMaterial(ref Material mat)
|
||||||
s_ActiveSoftMaskables.Add(this);
|
{
|
||||||
|
if (!mat) return;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
DestroyImmediate(mat);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
Destroy(mat);
|
||||||
|
|
||||||
var g = graphic;
|
mat = null;
|
||||||
if (g)
|
}
|
||||||
{
|
|
||||||
g.SetMaterialDirty();
|
|
||||||
}
|
|
||||||
_softMask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This function is called when the behaviour becomes disabled.
|
|
||||||
/// </summary>
|
|
||||||
void OnDisable()
|
|
||||||
{
|
|
||||||
s_ActiveSoftMaskables.Remove(this);
|
|
||||||
|
|
||||||
var g = graphic;
|
|
||||||
if (g)
|
|
||||||
{
|
|
||||||
g.SetMaterialDirty();
|
|
||||||
}
|
|
||||||
ReleaseMaterial(ref _maskMaterial);
|
|
||||||
|
|
||||||
_softMask = null;
|
|
||||||
|
|
||||||
MaterialCache.Unregister(_effectMaterialHash);
|
|
||||||
_effectMaterialHash = k_InvalidHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Release the material.
|
|
||||||
/// </summary>
|
|
||||||
void ReleaseMaterial(ref Material mat)
|
|
||||||
{
|
|
||||||
if (mat)
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
if (!Application.isPlaying)
|
|
||||||
{
|
|
||||||
DestroyImmediate(mat);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
Destroy(mat);
|
|
||||||
}
|
|
||||||
mat = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
|
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
graphic.SetMaterialDirtyEx();
|
graphic.SetMaterialDirtyEx();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
{
|
{
|
||||||
#pragma warning disable 0612
|
#pragma warning disable 0612
|
||||||
if (m_Inverse)
|
if (m_Inverse)
|
||||||
{
|
{
|
||||||
m_Inverse = false;
|
m_Inverse = false;
|
||||||
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||||
}
|
}
|
||||||
#pragma warning restore 0612
|
#pragma warning restore 0612
|
||||||
|
|
||||||
var current = this;
|
var current = this;
|
||||||
UnityEditor.EditorApplication.delayCall += () =>
|
UnityEditor.EditorApplication.delayCall += () =>
|
||||||
{
|
{
|
||||||
if (current && graphic && graphic.material && graphic.material.shader && graphic.material.shader.name == "Hidden/UI/Default (SoftMaskable)")
|
if (current && graphic && graphic.material && graphic.material.shader &&
|
||||||
{
|
graphic.material.shader.name == "Hidden/UI/Default (SoftMaskable)")
|
||||||
Debug.LogFormat("OnAfterDeserialize: reset material {0}",current);
|
{
|
||||||
graphic.material = null;
|
graphic.material = null;
|
||||||
graphic.SetMaterialDirtyEx();
|
graphic.SetMaterialDirtyEx();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue