68 lines
2.9 KiB
C#
68 lines
2.9 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.Input.Utilities
|
|
{
|
|
/// <summary>
|
|
/// On Unity UI components the unity_ObjectToWorld matrix is not the transformation matrix of the local
|
|
/// transform the Graphic component lives on, but that of its parent Canvas. Many MRTK/Standard shader
|
|
/// effects require object scale to be known. To solve this issue the ScaleMeshEffect will store scaling
|
|
/// information into UV channel attributes during UI mesh construction. Ideally we would store the scale
|
|
/// in one attribute but UGUI only supports two scalers per attribute (even in the tangent attribute).
|
|
/// </summary>
|
|
[RequireComponent(typeof(RectTransform), typeof(Graphic))]
|
|
[HelpURL("https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/rendering/mrtk-standard-shader#ugui-support")]
|
|
[AddComponentMenu("Scripts/MRTK/Services/ScaleMeshEffect")]
|
|
public class ScaleMeshEffect : BaseMeshEffect
|
|
{
|
|
/// <summary>
|
|
/// Enforces the parent canvas uses UV channel attributes.
|
|
/// </summary>
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
|
|
// Make sure the parent canvas is configured to use UV channel attributes for scaling data.
|
|
var canvas = GetComponentInParent<Canvas>();
|
|
|
|
if (canvas != null)
|
|
{
|
|
canvas.additionalShaderChannels |= AdditionalCanvasShaderChannels.TexCoord2;
|
|
canvas.additionalShaderChannels |= AdditionalCanvasShaderChannels.TexCoord3;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stores scaling information into UV channel attributes during UI mesh construction.
|
|
/// </summary>
|
|
/// <param name="vh">The vertex helper to populate with new vertex data.</param>
|
|
public override void ModifyMesh(VertexHelper vh)
|
|
{
|
|
var rectTransform = transform as RectTransform;
|
|
|
|
// Pack the 2D xy scale into UV channel 2.
|
|
var scale = new Vector2(rectTransform.rect.width * rectTransform.localScale.x,
|
|
rectTransform.rect.height * rectTransform.localScale.y);
|
|
|
|
var canvas = GetComponentInParent<Canvas>();
|
|
|
|
// Pack the z scale into x and a flag indicating this value comes from a ScaleMeshEffect into y into UV channel 3.
|
|
var depth = new Vector2((canvas ? (1.0f / canvas.transform.lossyScale.z) : 1.0f) * rectTransform.localScale.z,
|
|
-1.0f);
|
|
|
|
var vertex = new UIVertex();
|
|
|
|
for (var i = 0; i < vh.currentVertCount; ++i)
|
|
{
|
|
vh.PopulateUIVertex(ref vertex, i);
|
|
vertex.uv2 = scale;
|
|
vertex.uv3 = depth;
|
|
vh.SetUIVertex(vertex, i);
|
|
}
|
|
}
|
|
}
|
|
}
|