Impl unmask
commit
9d7d8f6a66
|
|
@ -0,0 +1 @@
|
||||||
|
./../../../../CHANGELOG.md
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fbca627d531eb4ca9b5846c638709e4c
|
||||||
|
timeCreated: 1539214410
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
./../../../../LICENSE.txt
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cefd86cfe94614a08ac447d0a9ec6ad3
|
||||||
|
timeCreated: 1539214411
|
||||||
|
licenseType: Pro
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6c5f8a1ac798e442eb3c77b05470878d
|
||||||
|
timeCreated: 1539214410
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 50a872063d2754fcd9d092eab7677003
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1539214485
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f752d3a51152f4e44a3ebe45ae24abcc
|
||||||
|
timeCreated: 1539214502
|
||||||
|
licenseType: Pro
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0bb9714b62a114d45b65f30fc946ea5c
|
||||||
|
timeCreated: 1539226167
|
||||||
|
licenseType: Pro
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Loading…
Reference in New Issue