871 lines
37 KiB
C#
871 lines
37 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Exoa.Utils
|
|
{
|
|
[ExecuteInEditMode]
|
|
[AddComponentMenu("Alpha Mask")]
|
|
public class Mask : MonoBehaviour
|
|
{
|
|
public enum MappingAxis
|
|
{
|
|
X,
|
|
Y,
|
|
Z
|
|
};
|
|
|
|
[SerializeField]
|
|
private MappingAxis _maskMappingWorldAxis = MappingAxis.Z;
|
|
public MappingAxis maskMappingWorldAxis
|
|
{
|
|
get
|
|
{
|
|
return _maskMappingWorldAxis;
|
|
}
|
|
set
|
|
{
|
|
ChangeMappingAxis(value, _maskMappingWorldAxis, _invertAxis);
|
|
_maskMappingWorldAxis = value;
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
private bool _invertAxis = false;
|
|
public bool invertAxis
|
|
{
|
|
get
|
|
{
|
|
return _invertAxis;
|
|
}
|
|
set
|
|
{
|
|
ChangeMappingAxis(_maskMappingWorldAxis, _maskMappingWorldAxis, value);
|
|
_invertAxis = value;
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
private bool _clampAlphaHorizontally = false;
|
|
public bool clampAlphaHorizontally
|
|
{
|
|
get
|
|
{
|
|
return _clampAlphaHorizontally;
|
|
}
|
|
set
|
|
{
|
|
SetMaskBoolValueInMaterials("_ClampHoriz", value);
|
|
_clampAlphaHorizontally = value;
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
private bool _clampAlphaVertically = false;
|
|
public bool clampAlphaVertically
|
|
{
|
|
get
|
|
{
|
|
return _clampAlphaVertically;
|
|
}
|
|
set
|
|
{
|
|
SetMaskBoolValueInMaterials("_ClampVert", value);
|
|
_clampAlphaVertically = value;
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
private float _clampingBorder = 0.01f;
|
|
public float clampingBorder
|
|
{
|
|
get
|
|
{
|
|
return _clampingBorder;
|
|
}
|
|
set
|
|
{
|
|
SetMaskFloatValueInMaterials("_ClampBorder", value);
|
|
_clampingBorder = value;
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
private bool _useMaskAlphaChannel = false;
|
|
public bool useMaskAlphaChannel
|
|
{
|
|
get
|
|
{
|
|
return _useMaskAlphaChannel;
|
|
}
|
|
set
|
|
{
|
|
SetMaskBoolValueInMaterials("_UseAlphaChannel", value);
|
|
_useMaskAlphaChannel = value;
|
|
}
|
|
}
|
|
|
|
|
|
private Shader _maskedSpriteWorldCoordsShader;
|
|
private Shader _maskedUnlitWorldCoordsShader;
|
|
|
|
|
|
void Start()
|
|
{
|
|
_maskedSpriteWorldCoordsShader = Shader.Find("Alpha Masked/Sprites Alpha Masked - World Coords");
|
|
_maskedUnlitWorldCoordsShader = Shader.Find("Alpha Masked/Unlit Alpha Masked - World Coords");
|
|
|
|
MeshRenderer maskMeshRenderer = GetComponent<MeshRenderer>();
|
|
MeshFilter maskMeshFilter = GetComponent<MeshFilter>();
|
|
if (Application.isPlaying)
|
|
{
|
|
if (maskMeshRenderer != null)
|
|
{
|
|
maskMeshRenderer.enabled = false;
|
|
}
|
|
}
|
|
#if UNITY_EDITOR
|
|
else
|
|
{
|
|
if (maskMeshFilter == null)
|
|
{
|
|
maskMeshFilter = gameObject.AddComponent<MeshFilter>() as MeshFilter;
|
|
maskMeshFilter.sharedMesh = new Mesh();
|
|
CreateAndAssignQuad(maskMeshFilter.sharedMesh);
|
|
maskMeshFilter.sharedMesh.name = "Mask Quad";
|
|
}
|
|
if (maskMeshRenderer == null)
|
|
{
|
|
maskMeshRenderer = gameObject.AddComponent<MeshRenderer>() as MeshRenderer;
|
|
maskMeshRenderer.sharedMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
|
maskMeshRenderer.sharedMaterial.name = "Mask Material";
|
|
}
|
|
|
|
maskMappingWorldAxis = _maskMappingWorldAxis;
|
|
invertAxis = _invertAxis;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
public void ApplyMaskToChildren()
|
|
{
|
|
Mask maskTarget = (Mask)this;
|
|
Shader maskedSpriteWorldCoordsShader = Shader.Find("Alpha Masked/Sprites Alpha Masked - World Coords");
|
|
Shader maskedUnlitWorldCoordsShader = Shader.Find("Alpha Masked/Unlit Alpha Masked - World Coords");
|
|
Shader spriteDefaultShader = Shader.Find("Sprites/Default");
|
|
Shader unlitTransparentShader = Shader.Find("Unlit/Transparent");
|
|
Shader UIDefaultShader = Shader.Find("UI/Default");
|
|
Shader UIDefaultFontShader = Shader.Find("UI/Default Font");
|
|
|
|
if ((maskedSpriteWorldCoordsShader == null) || (maskedUnlitWorldCoordsShader == null))
|
|
{
|
|
Debug.Log("Shaders necessary for masking don't seem to be present in the project.");
|
|
return;
|
|
}
|
|
|
|
Texture maskTexture = maskTarget.GetComponent<Renderer>().sharedMaterial.mainTexture;
|
|
|
|
List<Component> components = new List<Component>();
|
|
components.AddRange(maskTarget.transform.parent.gameObject.GetComponentsInChildren<Renderer>());
|
|
components.AddRange(maskTarget.transform.parent.gameObject.GetComponentsInChildren<Graphic>());
|
|
List<Material> differentOriginalMaterials = new List<Material>();
|
|
List<Material> differentNewMaterials = new List<Material>();
|
|
|
|
List<Material> differentReusableMaterials = GetAllReusableMaterials(components, maskedSpriteWorldCoordsShader, maskedUnlitWorldCoordsShader);// new List<Material>();
|
|
|
|
foreach (Component component in components)
|
|
{
|
|
if (component.gameObject != maskTarget.gameObject)
|
|
{
|
|
List<Material> currSharedMaterials = new List<Material>();
|
|
List<bool> areCurrSharedMaterialsTexts = new List<bool>();
|
|
if (component is Renderer)
|
|
{
|
|
currSharedMaterials.AddRange(((Renderer)component).sharedMaterials);
|
|
for (int i = 0; i < ((Renderer)component).sharedMaterials.Length; i++)
|
|
{
|
|
areCurrSharedMaterialsTexts.Add(false);
|
|
}
|
|
}
|
|
else if (component is Graphic)
|
|
{
|
|
currSharedMaterials.Add(((Graphic)component).material);
|
|
areCurrSharedMaterialsTexts.Add(component is Text);
|
|
}
|
|
|
|
bool materialsChanged = false;
|
|
|
|
for (int i = 0; i < currSharedMaterials.Count; i++)
|
|
{
|
|
Material material = currSharedMaterials[i];
|
|
|
|
if (!differentOriginalMaterials.Contains(material))
|
|
{
|
|
Material materialToBeUsed = null;
|
|
|
|
if ((material.shader == spriteDefaultShader) ||
|
|
(material.shader == unlitTransparentShader) ||
|
|
(material.shader == UIDefaultShader) ||
|
|
(material.shader == UIDefaultFontShader))
|
|
{
|
|
Material reusableMaterial = FindSuitableMaskedMaterial(material, differentReusableMaterials,
|
|
maskedSpriteWorldCoordsShader, maskedUnlitWorldCoordsShader,
|
|
spriteDefaultShader, unlitTransparentShader, UIDefaultShader, UIDefaultFontShader);
|
|
|
|
if (reusableMaterial == null)
|
|
{
|
|
differentOriginalMaterials.Add(material);
|
|
|
|
Material newMaterial = new Material(material);
|
|
if (material.shader == spriteDefaultShader)
|
|
{
|
|
newMaterial.shader = maskedSpriteWorldCoordsShader;
|
|
}
|
|
else if (material.shader == unlitTransparentShader)
|
|
{
|
|
newMaterial.shader = maskedUnlitWorldCoordsShader;
|
|
}
|
|
else if (material.shader == UIDefaultShader)
|
|
{
|
|
newMaterial.shader = maskedSpriteWorldCoordsShader;
|
|
}
|
|
else if (material.shader == UIDefaultFontShader)
|
|
{
|
|
newMaterial.shader = maskedSpriteWorldCoordsShader;
|
|
}
|
|
if (areCurrSharedMaterialsTexts[i] == true)
|
|
{
|
|
newMaterial.SetFloat("_IsThisText", 1);
|
|
}
|
|
newMaterial.name = material.name + " Masked";
|
|
newMaterial.SetTexture("_AlphaTex", maskTexture);
|
|
|
|
materialToBeUsed = newMaterial;
|
|
differentNewMaterials.Add(newMaterial);
|
|
currSharedMaterials[i] = newMaterial;
|
|
materialsChanged = true;
|
|
}
|
|
else
|
|
{
|
|
currSharedMaterials[i] = reusableMaterial;
|
|
materialsChanged = true;
|
|
|
|
reusableMaterial.SetTexture("_AlphaTex", maskTexture);
|
|
materialToBeUsed = reusableMaterial;
|
|
}
|
|
}
|
|
else if ((material.shader == maskedSpriteWorldCoordsShader) ||
|
|
(material.shader == maskedUnlitWorldCoordsShader))
|
|
{
|
|
if (material.GetTexture("_AlphaTex") != maskTexture)
|
|
{
|
|
material.SetTexture("_AlphaTex", maskTexture);
|
|
}
|
|
if (areCurrSharedMaterialsTexts[i] == true)
|
|
{
|
|
material.SetFloat("_IsThisText", 1);
|
|
}
|
|
materialToBeUsed = material;
|
|
}
|
|
|
|
if (materialToBeUsed != null)
|
|
{
|
|
maskTarget.SetMaskMappingAxisInMaterial(maskTarget.maskMappingWorldAxis, materialToBeUsed);
|
|
maskTarget.SetMaskBoolValueInMaterial("_ClampHoriz", maskTarget.clampAlphaHorizontally, materialToBeUsed);
|
|
maskTarget.SetMaskBoolValueInMaterial("_ClampVert", maskTarget.clampAlphaVertically, materialToBeUsed);
|
|
maskTarget.SetMaskBoolValueInMaterial("_UseAlphaChannel", maskTarget.useMaskAlphaChannel, materialToBeUsed);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int index = differentOriginalMaterials.IndexOf(material);
|
|
|
|
currSharedMaterials[i] = differentNewMaterials[index];
|
|
materialsChanged = true;
|
|
}
|
|
}
|
|
|
|
if (materialsChanged == true)
|
|
{
|
|
if (component is Renderer)
|
|
{
|
|
((Renderer)component).sharedMaterials = currSharedMaterials.ToArray();
|
|
}
|
|
else if (component is Graphic)
|
|
{
|
|
((Graphic)component).material = currSharedMaterials[0];
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Debug.Log("Mask applied.");
|
|
}
|
|
|
|
private Material FindSuitableMaskedMaterial(Material nonMaskedMaterial, List<Material> differentReusableMaterials,
|
|
Shader maskedSpriteWorldCoordsShader, Shader maskedUnlitWorldCoordsShader,
|
|
Shader spriteDefaultShader, Shader unlitTransparentShader, Shader UIDefaultShader, Shader UIDefaultFontShader)
|
|
{
|
|
foreach (Material material in differentReusableMaterials)
|
|
{
|
|
if ((nonMaskedMaterial.shader == spriteDefaultShader) &&
|
|
(material.shader == maskedSpriteWorldCoordsShader))
|
|
{
|
|
if ((material.name == nonMaskedMaterial.name + " Masked") &&
|
|
(material.GetColor("_Color") == nonMaskedMaterial.GetColor("_Color")) &&
|
|
(material.GetFloat("PixelSnap") == nonMaskedMaterial.GetFloat("PixelSnap")))
|
|
{
|
|
return material;
|
|
}
|
|
}
|
|
else if ((nonMaskedMaterial.shader == unlitTransparentShader) &&
|
|
(material.shader == maskedUnlitWorldCoordsShader))
|
|
{
|
|
if ((material.name == nonMaskedMaterial.name + " Masked") &&
|
|
(material.mainTexture == nonMaskedMaterial.mainTexture))
|
|
{
|
|
return material;
|
|
}
|
|
}
|
|
else if ((nonMaskedMaterial.shader == UIDefaultFontShader) &&
|
|
(material.shader == maskedSpriteWorldCoordsShader))
|
|
{
|
|
if ((material.name == nonMaskedMaterial.name + " Masked") &&
|
|
(material.GetColor("_Color") == nonMaskedMaterial.GetColor("_Color")))
|
|
{
|
|
return material;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
private List<Material> GetAllReusableMaterials(List<Component> components, Shader maskedSpriteWorldCoordsShader, Shader maskedUnlitWorldCoordsShader)
|
|
{
|
|
List<Material> differentReusableMaterials = new List<Material>();
|
|
Mask maskTarget = (Mask)this;
|
|
|
|
foreach (Component component in components)
|
|
{
|
|
if (component.gameObject != maskTarget.gameObject)
|
|
{
|
|
List<Material> currSharedMaterials = new List<Material>();
|
|
if (component is Renderer)
|
|
{
|
|
currSharedMaterials.AddRange(((Renderer)component).sharedMaterials);
|
|
}
|
|
else if (component is Graphic)
|
|
{
|
|
currSharedMaterials.Add(((Graphic)component).material);
|
|
}
|
|
//Material[] currSharedMaterials = renderer.sharedMaterials;
|
|
|
|
for (int i = 0; i < currSharedMaterials.Count; i++)
|
|
{
|
|
Material material = currSharedMaterials[i];
|
|
|
|
if ((material.shader == maskedSpriteWorldCoordsShader) ||
|
|
(material.shader == maskedUnlitWorldCoordsShader))
|
|
{
|
|
differentReusableMaterials.Add(material);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return differentReusableMaterials;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (_maskedSpriteWorldCoordsShader == null)
|
|
{
|
|
_maskedSpriteWorldCoordsShader = Shader.Find("Alpha Masked/Sprites Alpha Masked - World Coords");
|
|
}
|
|
if (_maskedUnlitWorldCoordsShader == null)
|
|
{
|
|
_maskedUnlitWorldCoordsShader = Shader.Find("Alpha Masked/Unlit Alpha Masked - World Coords");
|
|
}
|
|
|
|
if ((_maskedSpriteWorldCoordsShader == null) || (_maskedUnlitWorldCoordsShader == null))
|
|
{
|
|
Debug.Log("Shaders necessary for masking don't seem to be present in the project.");
|
|
return;
|
|
}
|
|
|
|
if (transform.hasChanged == true)
|
|
{
|
|
if ((maskMappingWorldAxis == MappingAxis.X) && ((Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.x, 0)) > 0.01f) || (Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.y, invertAxis ? -90 : 90)) > 0.01f)))
|
|
{
|
|
Debug.Log("You cannot edit X and Y values of the Mask transform rotation!");
|
|
transform.eulerAngles = new Vector3(0, invertAxis ? 270 : 90, transform.eulerAngles.z);
|
|
}
|
|
else if ((maskMappingWorldAxis == MappingAxis.Y) && ((Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.x, invertAxis ? -90 : 90)) > 0.01f) || (Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.z, 0)) > 0.01f)))
|
|
{
|
|
Debug.Log("You cannot edit X and Z values of the Mask transform rotation!");
|
|
transform.eulerAngles = new Vector3(invertAxis ? -90 : 90, transform.eulerAngles.y, 0);
|
|
}
|
|
else if ((maskMappingWorldAxis == MappingAxis.Z) && ((Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.x, 0)) > 0.01f) || (Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.y, (invertAxis ? -180 : 0))) > 0.01f)))
|
|
{
|
|
Debug.Log("You cannot edit X and Y values of the Mask transform rotation!");
|
|
transform.eulerAngles = new Vector3(0, invertAxis ? -180 : 0, transform.eulerAngles.z);
|
|
}
|
|
|
|
if (transform.parent != null)
|
|
{
|
|
Renderer[] renderers = transform.parent.gameObject.GetComponentsInChildren<Renderer>();
|
|
Graphic[] UIComponents = transform.parent.gameObject.GetComponentsInChildren<Graphic>();
|
|
List<Material> differentMaterials = new List<Material>();
|
|
|
|
// Needed for UI Screen Space - Overlay support
|
|
Dictionary<Material, Graphic> UIMaterialToGraphic = new Dictionary<Material, Graphic>();
|
|
|
|
foreach (Renderer renderer in renderers)
|
|
{
|
|
if (renderer.gameObject != gameObject)
|
|
{
|
|
foreach (Material material in renderer.sharedMaterials)
|
|
{
|
|
if (!differentMaterials.Contains(material))
|
|
{
|
|
differentMaterials.Add(material);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (Graphic UIComponent in UIComponents)
|
|
{
|
|
if (UIComponent.gameObject != gameObject)
|
|
{
|
|
if (!differentMaterials.Contains(UIComponent.material))
|
|
{
|
|
differentMaterials.Add(UIComponent.material);
|
|
|
|
// Needed for UI "Screen Space - Overlay" support
|
|
Canvas currCanvas = UIComponent.canvas;
|
|
if ((currCanvas.renderMode == RenderMode.ScreenSpaceOverlay) ||
|
|
(currCanvas.renderMode == RenderMode.ScreenSpaceCamera) && (currCanvas.worldCamera == null))
|
|
{
|
|
UIMaterialToGraphic.Add(differentMaterials[differentMaterials.Count - 1], UIComponent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (Material material in differentMaterials)
|
|
{
|
|
if ((material.shader.ToString() == _maskedSpriteWorldCoordsShader.ToString()) &&
|
|
(material.shader.GetInstanceID() != _maskedSpriteWorldCoordsShader.GetInstanceID()))
|
|
{
|
|
Debug.Log("There seems to be more than one masked shader in the project with the same display name, and it's preventing the mask from being properly applied.");
|
|
_maskedSpriteWorldCoordsShader = null;
|
|
}
|
|
if ((material.shader.ToString() == _maskedUnlitWorldCoordsShader.ToString()) &&
|
|
(material.shader.GetInstanceID() != _maskedUnlitWorldCoordsShader.GetInstanceID()))
|
|
{
|
|
Debug.Log("There seems to be more than one masked shader in the project with the same display name, and it's preventing the mask from being properly applied.");
|
|
_maskedUnlitWorldCoordsShader = null;
|
|
}
|
|
|
|
|
|
if ((material.shader == _maskedSpriteWorldCoordsShader) ||
|
|
(material.shader == _maskedUnlitWorldCoordsShader))
|
|
{
|
|
material.DisableKeyword("_SCREEN_SPACE_UI");
|
|
|
|
Vector2 scale = new Vector2(1f / transform.lossyScale.x, 1f / transform.lossyScale.y);
|
|
Vector2 offset = Vector2.zero;
|
|
float rotationAngle = 0;
|
|
int sign = 1;
|
|
if (maskMappingWorldAxis == MappingAxis.X)
|
|
{
|
|
sign = (invertAxis ? 1 : -1);
|
|
offset = new Vector2(-transform.position.z, -transform.position.y);
|
|
rotationAngle = sign * transform.eulerAngles.z;
|
|
}
|
|
else if (maskMappingWorldAxis == MappingAxis.Y)
|
|
{
|
|
offset = new Vector2(-transform.position.x, -transform.position.z);
|
|
rotationAngle = -transform.eulerAngles.y;
|
|
}
|
|
else if (maskMappingWorldAxis == MappingAxis.Z)
|
|
{
|
|
sign = (invertAxis ? -1 : 1);
|
|
offset = new Vector2(-transform.position.x, -transform.position.y);
|
|
rotationAngle = sign * transform.eulerAngles.z;
|
|
}
|
|
|
|
// Needed for UI anchor support
|
|
RectTransform maskRectTransform = GetComponent<RectTransform>();
|
|
if (maskRectTransform != null)
|
|
{
|
|
Rect rect = maskRectTransform.rect;
|
|
|
|
offset += (Vector2)(transform.right * (maskRectTransform.pivot.x - 0.5f) * rect.width * transform.lossyScale.x +
|
|
transform.up * (maskRectTransform.pivot.y - 0.5f) * rect.height * transform.lossyScale.y);
|
|
scale.x /= rect.width;
|
|
scale.y /= rect.height;
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
MeshFilter maskMeshFilter = GetComponent<MeshFilter>();
|
|
if (maskMeshFilter != null)
|
|
{
|
|
CreateAndAssignQuad(maskMeshFilter.sharedMesh, rect.xMin, rect.xMax, rect.yMin, rect.yMax);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
#if UNITY_EDITOR
|
|
else
|
|
{
|
|
if (!Application.isPlaying)
|
|
{
|
|
MeshFilter maskMeshFilter = GetComponent<MeshFilter>();
|
|
if (maskMeshFilter != null)
|
|
{
|
|
CreateAndAssignQuad(maskMeshFilter.sharedMesh);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// UI "Screen Space - Overlay mode" or "Screen Space - Camera", where the camera is null (actually, falls back to "Overlay")
|
|
if (UIMaterialToGraphic.ContainsKey(material))
|
|
{
|
|
offset = UIMaterialToGraphic[material].transform.InverseTransformVector(offset);
|
|
|
|
switch (maskMappingWorldAxis)
|
|
{
|
|
case MappingAxis.X:
|
|
offset.x *= UIMaterialToGraphic[material].transform.lossyScale.z;
|
|
offset.y *= UIMaterialToGraphic[material].transform.lossyScale.y;
|
|
break;
|
|
case MappingAxis.Y:
|
|
offset.x *= UIMaterialToGraphic[material].transform.lossyScale.x;
|
|
offset.y *= UIMaterialToGraphic[material].transform.lossyScale.z;
|
|
break;
|
|
case MappingAxis.Z:
|
|
offset.x *= UIMaterialToGraphic[material].transform.lossyScale.x;
|
|
offset.y *= UIMaterialToGraphic[material].transform.lossyScale.y;
|
|
break;
|
|
}
|
|
Canvas currUIElementCanvas = UIMaterialToGraphic[material].canvas;
|
|
offset /= currUIElementCanvas.scaleFactor;
|
|
|
|
offset = RotateVector(offset, UIMaterialToGraphic[material].transform.eulerAngles);
|
|
offset += currUIElementCanvas.GetComponent<RectTransform>().sizeDelta * 0.5f;
|
|
scale *= currUIElementCanvas.scaleFactor;
|
|
|
|
material.EnableKeyword("_SCREEN_SPACE_UI");
|
|
}
|
|
|
|
|
|
Vector2 scaleTexture = gameObject.GetComponent<Renderer>().sharedMaterial.mainTextureScale;
|
|
scale.x *= scaleTexture.x;
|
|
scale.y *= scaleTexture.y;
|
|
|
|
scale.x *= sign;
|
|
|
|
Vector2 offsetTemporary = offset;
|
|
float s = Mathf.Sin(-rotationAngle * Mathf.Deg2Rad);
|
|
float c = Mathf.Cos(-rotationAngle * Mathf.Deg2Rad);
|
|
|
|
offset.x = (c * offsetTemporary.x - s * offsetTemporary.y) * scale.x + 0.5f * scaleTexture.x;
|
|
offset.y = (s * offsetTemporary.x + c * offsetTemporary.y) * scale.y + 0.5f * scaleTexture.y;
|
|
|
|
|
|
offset += gameObject.GetComponent<Renderer>().sharedMaterial.mainTextureOffset;
|
|
|
|
material.SetTextureOffset("_AlphaTex", offset);
|
|
material.SetTextureScale("_AlphaTex", scale);
|
|
material.SetFloat("_MaskRotation", rotationAngle * Mathf.Deg2Rad);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private Vector3 RotateVector(Vector3 point, Vector3 angles)
|
|
{
|
|
return Quaternion.Euler(angles) * point;
|
|
}
|
|
|
|
private void SetMaskMappingAxisInMaterials(MappingAxis mappingAxis)
|
|
{
|
|
if (transform.parent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Renderer[] renderers = transform.parent.gameObject.GetComponentsInChildren<Renderer>();
|
|
Graphic[] UIComponents = transform.parent.gameObject.GetComponentsInChildren<Graphic>();
|
|
List<Material> differentMaterials = new List<Material>();
|
|
|
|
foreach (Renderer renderer in renderers)
|
|
{
|
|
if (renderer.gameObject != gameObject)
|
|
{
|
|
foreach (Material material in renderer.sharedMaterials)
|
|
{
|
|
if (!differentMaterials.Contains(material))
|
|
{
|
|
differentMaterials.Add(material);
|
|
|
|
SetMaskMappingAxisInMaterial(mappingAxis, material);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (Graphic UIComponent in UIComponents)
|
|
{
|
|
if (UIComponent.gameObject != gameObject)
|
|
{
|
|
if (!differentMaterials.Contains(UIComponent.material))
|
|
{
|
|
differentMaterials.Add(UIComponent.material);
|
|
|
|
SetMaskMappingAxisInMaterial(mappingAxis, UIComponent.material);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetMaskMappingAxisInMaterial(MappingAxis mappingAxis, Material material)
|
|
{
|
|
if ((material.shader == _maskedSpriteWorldCoordsShader) ||
|
|
(material.shader == _maskedUnlitWorldCoordsShader))
|
|
{
|
|
switch (mappingAxis)
|
|
{
|
|
case MappingAxis.X:
|
|
material.SetFloat("_Axis", 0);
|
|
material.EnableKeyword("_AXIS_X");
|
|
material.DisableKeyword("_AXIS_Y");
|
|
material.DisableKeyword("_AXIS_Z");
|
|
break;
|
|
case MappingAxis.Y:
|
|
material.SetFloat("_Axis", 1);
|
|
material.DisableKeyword("_AXIS_X");
|
|
material.EnableKeyword("_AXIS_Y");
|
|
material.DisableKeyword("_AXIS_Z");
|
|
break;
|
|
case MappingAxis.Z:
|
|
material.SetFloat("_Axis", 2);
|
|
material.DisableKeyword("_AXIS_X");
|
|
material.DisableKeyword("_AXIS_Y");
|
|
material.EnableKeyword("_AXIS_Z");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetMaskFloatValueInMaterials(string variable, float value)
|
|
{
|
|
if (transform.parent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Renderer[] renderers = transform.parent.gameObject.GetComponentsInChildren<Renderer>();
|
|
Graphic[] UIComponents = transform.parent.gameObject.GetComponentsInChildren<Graphic>();
|
|
List<Material> differentMaterials = new List<Material>();
|
|
|
|
foreach (Renderer renderer in renderers)
|
|
{
|
|
if (renderer.gameObject != gameObject)
|
|
{
|
|
foreach (Material material in renderer.sharedMaterials)
|
|
{
|
|
if (!differentMaterials.Contains(material))
|
|
{
|
|
differentMaterials.Add(material);
|
|
|
|
material.SetFloat(variable, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (Graphic UIComponent in UIComponents)
|
|
{
|
|
if (UIComponent.gameObject != gameObject)
|
|
{
|
|
if (!differentMaterials.Contains(UIComponent.material))
|
|
{
|
|
differentMaterials.Add(UIComponent.material);
|
|
|
|
UIComponent.material.SetFloat(variable, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetMaskBoolValueInMaterials(string variable, bool value)
|
|
{
|
|
if (transform.parent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Renderer[] renderers = transform.parent.gameObject.GetComponentsInChildren<Renderer>();
|
|
Graphic[] UIComponents = transform.parent.gameObject.GetComponentsInChildren<Graphic>();
|
|
List<Material> differentMaterials = new List<Material>();
|
|
|
|
foreach (Renderer renderer in renderers)
|
|
{
|
|
if (renderer.gameObject != gameObject)
|
|
{
|
|
foreach (Material material in renderer.sharedMaterials)
|
|
{
|
|
if (!differentMaterials.Contains(material))
|
|
{
|
|
differentMaterials.Add(material);
|
|
|
|
SetMaskBoolValueInMaterial(variable, value, material);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (Graphic UIComponent in UIComponents)
|
|
{
|
|
if (UIComponent.gameObject != gameObject)
|
|
{
|
|
if (!differentMaterials.Contains(UIComponent.material))
|
|
{
|
|
differentMaterials.Add(UIComponent.material);
|
|
|
|
SetMaskBoolValueInMaterial(variable, value, UIComponent.material);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetMaskBoolValueInMaterial(string variable, bool value, Material material)
|
|
{
|
|
if ((material.shader == _maskedSpriteWorldCoordsShader) ||
|
|
(material.shader == _maskedUnlitWorldCoordsShader))
|
|
{
|
|
material.SetFloat(variable, (value ? 1 : 0));
|
|
if (value == true)
|
|
{
|
|
material.EnableKeyword(variable.ToUpper() + "_ON");
|
|
}
|
|
else
|
|
{
|
|
material.DisableKeyword(variable.ToUpper() + "_ON");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateAndAssignQuad(Mesh mesh, float minX = -0.5f, float maxX = 0.5f, float minY = -0.5f, float maxY = 0.5f)
|
|
{
|
|
// assign vertices
|
|
Vector3[] vertices = new Vector3[4];
|
|
|
|
vertices[0] = new Vector3(minX, minY, 0);
|
|
vertices[1] = new Vector3(maxX, minY, 0);
|
|
vertices[2] = new Vector3(minX, maxY, 0);
|
|
vertices[3] = new Vector3(maxX, maxY, 0);
|
|
|
|
mesh.vertices = vertices;
|
|
|
|
// assign triangles
|
|
int[] tri = new int[6];
|
|
|
|
// Lower left triangle.
|
|
tri[0] = 0;
|
|
tri[1] = 2;
|
|
tri[2] = 1;
|
|
|
|
// Upper right triangle.
|
|
tri[3] = 2;
|
|
tri[4] = 3;
|
|
tri[5] = 1;
|
|
|
|
mesh.triangles = tri;
|
|
|
|
// assign normals
|
|
Vector3[] normals = new Vector3[4];
|
|
|
|
normals[0] = -Vector3.forward;
|
|
normals[1] = -Vector3.forward;
|
|
normals[2] = -Vector3.forward;
|
|
normals[3] = -Vector3.forward;
|
|
|
|
mesh.normals = normals;
|
|
|
|
// assign UVs
|
|
Vector2[] uv = new Vector2[4];
|
|
|
|
uv[0] = new Vector2(0, 0);
|
|
uv[1] = new Vector2(1, 0);
|
|
uv[2] = new Vector2(0, 1);
|
|
uv[3] = new Vector2(1, 1);
|
|
|
|
mesh.uv = uv;
|
|
}
|
|
|
|
public void SetMaskRendererActive(bool value)
|
|
{
|
|
if (GetComponent<Renderer>() != null)
|
|
{
|
|
if (value == true)
|
|
{
|
|
GetComponent<Renderer>().enabled = true;
|
|
}
|
|
else
|
|
{
|
|
GetComponent<Renderer>().enabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ChangeMappingAxis(MappingAxis currMaskMappingWorldAxis, MappingAxis prevMaskMappingWorldAxis, bool currInvertAxis)
|
|
{
|
|
if (currMaskMappingWorldAxis == MappingAxis.X)
|
|
{
|
|
if (prevMaskMappingWorldAxis == MappingAxis.Y)
|
|
{
|
|
transform.eulerAngles = new Vector3(0, currInvertAxis ? -90 : 90, transform.eulerAngles.y);
|
|
}
|
|
else
|
|
{
|
|
transform.eulerAngles = new Vector3(0, currInvertAxis ? -90 : 90, transform.eulerAngles.z);
|
|
}
|
|
}
|
|
else if (currMaskMappingWorldAxis == MappingAxis.Y)
|
|
{
|
|
if (prevMaskMappingWorldAxis == MappingAxis.Y)
|
|
{
|
|
transform.eulerAngles = new Vector3(currInvertAxis ? -90 : 90, transform.eulerAngles.y, 0);
|
|
}
|
|
else
|
|
{
|
|
transform.eulerAngles = new Vector3(currInvertAxis ? -90 : 90, transform.eulerAngles.z, 0);
|
|
}
|
|
}
|
|
else if (currMaskMappingWorldAxis == MappingAxis.Z)
|
|
{
|
|
if (prevMaskMappingWorldAxis == MappingAxis.Y)
|
|
{
|
|
transform.eulerAngles = new Vector3(0, currInvertAxis ? -180 : 0, transform.eulerAngles.y);
|
|
}
|
|
else
|
|
{
|
|
transform.eulerAngles = new Vector3(0, currInvertAxis ? -180 : 0, transform.eulerAngles.z);
|
|
}
|
|
}
|
|
|
|
SetMaskMappingAxisInMaterials(currMaskMappingWorldAxis);
|
|
}
|
|
}
|
|
} |