commit 9d7d8f6a6635885da849f8987ffbec41ac24862d Author: mob-sakai Date: Sun Oct 14 16:51:54 2018 +0900 Impl unmask diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 120000 index 0000000..cd67e22 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +./../../../../CHANGELOG.md \ No newline at end of file diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta new file mode 100644 index 0000000..dd3698c --- /dev/null +++ b/CHANGELOG.md.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fbca627d531eb4ca9b5846c638709e4c +timeCreated: 1539214410 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/LICENSE.txt b/LICENSE.txt new file mode 120000 index 0000000..fff8277 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1 @@ +./../../../../LICENSE.txt \ No newline at end of file diff --git a/LICENSE.txt.meta b/LICENSE.txt.meta new file mode 100644 index 0000000..3d692a6 --- /dev/null +++ b/LICENSE.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cefd86cfe94614a08ac447d0a9ec6ad3 +timeCreated: 1539214411 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md new file mode 120000 index 0000000..7d6adfb --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +./../../../../README.md \ No newline at end of file diff --git a/README.md.meta b/README.md.meta new file mode 100644 index 0000000..7c24bcd --- /dev/null +++ b/README.md.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c5f8a1ac798e442eb3c77b05470878d +timeCreated: 1539214410 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts.meta b/Scripts.meta new file mode 100644 index 0000000..051a40b --- /dev/null +++ b/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 50a872063d2754fcd9d092eab7677003 +folderAsset: yes +timeCreated: 1539214485 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Unmask.cs b/Scripts/Unmask.cs new file mode 100644 index 0000000..6d4f53a --- /dev/null +++ b/Scripts/Unmask.cs @@ -0,0 +1,157 @@ +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(); + } + } + } +} \ No newline at end of file diff --git a/Scripts/Unmask.cs.meta b/Scripts/Unmask.cs.meta new file mode 100644 index 0000000..c90b296 --- /dev/null +++ b/Scripts/Unmask.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f752d3a51152f4e44a3ebe45ae24abcc +timeCreated: 1539214502 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/UnmaskRaycastFilter.cs b/Scripts/UnmaskRaycastFilter.cs new file mode 100644 index 0000000..5618ab7 --- /dev/null +++ b/Scripts/UnmaskRaycastFilter.cs @@ -0,0 +1,92 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + + +namespace Coffee.UIExtensions +{ + /// + /// Unmask Raycast Filter. + /// The ray passes through the unmasked rectangle. + /// + [AddComponentMenu("UI/Unmask/UnmaskRaycastFilter", 2)] + public class UnmaskRaycastFilter : MonoBehaviour, ICanvasRaycastFilter + { + //################################ + // Constant or Static Members. + //################################ + Vector3[] s_WorldCorners = new Vector3[4]; + + + //################################ + // Serialize Members. + //################################ + [Tooltip("Target unmask component. The ray passes through the unmasked rectangle.")] + [SerializeField] Unmask m_TargetUnmask; + + + //################################ + // Public Members. + //################################ + /// + /// Target unmask component. Ray through the unmasked rectangle. + /// + public Unmask targetUnmask{ get { return m_TargetUnmask; } set { m_TargetUnmask = value; } } + + /// + /// Given a point and a camera is the raycast valid. + /// + /// Valid. + /// Screen position. + /// Raycast camera. + public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) + { + // Skip if deactived. + if (!isActiveAndEnabled || !m_TargetUnmask || !m_TargetUnmask.isActiveAndEnabled) + { + return true; + } + + // Get world corners for the target. + (m_TargetUnmask.transform as RectTransform).GetWorldCorners(s_WorldCorners); + + // Convert to screen positions. + var cam = eventCamera ?? Camera.main; + var p = cam.WorldToScreenPoint(sp); + var a = cam.WorldToScreenPoint(s_WorldCorners[0]); + var b = cam.WorldToScreenPoint(s_WorldCorners[1]); + var c = cam.WorldToScreenPoint(s_WorldCorners[2]); + var d = cam.WorldToScreenPoint(s_WorldCorners[3]); + + // check left/right side + var ab = Cross(p - a, b - a) < 0.0; + var bc = Cross(p - b, c - b) < 0.0; + var cd = Cross(p - c, d - c) < 0.0; + var da = Cross(p - d, a - d) < 0.0; + + // check inside + return ab ^ bc ||bc ^ cd ||cd ^ da; + } + + + //################################ + // Private Members. + //################################ + + /// + /// This function is called when the object becomes enabled and active. + /// + void OnEnable() + { + } + + /// + /// Cross for Vector2. + /// + float Cross(Vector2 a, Vector2 b) + { + return a.x * b.y - a.y * b.x; + } + } +} \ No newline at end of file diff --git a/Scripts/UnmaskRaycastFilter.cs.meta b/Scripts/UnmaskRaycastFilter.cs.meta new file mode 100644 index 0000000..6c5c3a4 --- /dev/null +++ b/Scripts/UnmaskRaycastFilter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0bb9714b62a114d45b65f30fc946ea5c +timeCreated: 1539226167 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: