Impl unmask

main
mob-sakai 2018-10-14 16:51:54 +09:00
commit 9d7d8f6a66
11 changed files with 309 additions and 0 deletions

1
CHANGELOG.md Symbolic link
View File

@ -0,0 +1 @@
./../../../../CHANGELOG.md

8
CHANGELOG.md.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fbca627d531eb4ca9b5846c638709e4c
timeCreated: 1539214410
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

1
LICENSE.txt Symbolic link
View File

@ -0,0 +1 @@
./../../../../LICENSE.txt

8
LICENSE.txt.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cefd86cfe94614a08ac447d0a9ec6ad3
timeCreated: 1539214411
licenseType: Pro
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

1
README.md Symbolic link
View File

@ -0,0 +1 @@
./../../../../README.md

8
README.md.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6c5f8a1ac798e442eb3c77b05470878d
timeCreated: 1539214410
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Scripts.meta Normal file
View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 50a872063d2754fcd9d092eab7677003
folderAsset: yes
timeCreated: 1539214485
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

157
Scripts/Unmask.cs Normal file
View File

@ -0,0 +1,157 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
/// <summary>
/// Reverse masking for parent Mask component.
/// </summary>
[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.
//################################
/// <summary>
/// The graphic associated with the unmask.
/// </summary>
public Graphic graphic{ get { return _graphic ?? (_graphic = GetComponent<Graphic>()); } }
/// <summary>
/// Fit graphic's transform to target transform on LateUpdate.
/// </summary>
public RectTransform autoFitTarget{ get { return m_AutoFitTarget; } set { m_AutoFitTarget = value; } }
/// <summary>
/// Show the graphic that is associated with the unmask render area.
/// </summary>
public bool showUnmaskGraphic
{
get { return m_ShowUnmaskGraphic; }
set
{
m_ShowUnmaskGraphic = value;
SetDirty();
}
}
/// <summary>
/// Perform material modification in this function.
/// </summary>
/// <returns>Modified material.</returns>
/// <param name="baseMaterial">Configured Material.</param>
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;
}
/// <summary>
/// Fit to target transform.
/// </summary>
/// <param name="target">Target transform.</param>
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;
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
void OnEnable()
{
if (m_AutoFitTarget)
{
FitTo(m_AutoFitTarget);
}
SetDirty();
}
/// <summary>
/// This function is called when the behaviour becomes disabled () or inactive.
/// </summary>
void OnDisable()
{
StencilMaterial.Remove(_unmaskMaterial);
_unmaskMaterial = null;
SetDirty();
}
/// <summary>
/// LateUpdate is called every frame, if the Behaviour is enabled.
/// </summary>
void LateUpdate()
{
if (m_AutoFitTarget)
{
FitTo(m_AutoFitTarget);
}
}
/// <summary>
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
/// </summary>
void OnValidate()
{
SetDirty();
}
/// <summary>
/// Mark the graphic as dirty.
/// </summary>
void SetDirty()
{
if (graphic)
{
graphic.SetMaterialDirty();
}
}
}
}

12
Scripts/Unmask.cs.meta Normal file
View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f752d3a51152f4e44a3ebe45ae24abcc
timeCreated: 1539214502
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,92 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
/// <summary>
/// Unmask Raycast Filter.
/// The ray passes through the unmasked rectangle.
/// </summary>
[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.
//################################
/// <summary>
/// Target unmask component. Ray through the unmasked rectangle.
/// </summary>
public Unmask targetUnmask{ get { return m_TargetUnmask; } set { m_TargetUnmask = value; } }
/// <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 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.
//################################
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
void OnEnable()
{
}
/// <summary>
/// Cross for Vector2.
/// </summary>
float Cross(Vector2 a, Vector2 b)
{
return a.x * b.y - a.y * b.x;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0bb9714b62a114d45b65f30fc946ea5c
timeCreated: 1539226167
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: