TaiZhouChangChu/Assets/HighlightingSystemDemo/Scripts/Service/ScreenSpaceCanvas.cs

134 lines
3.1 KiB
C#

using UnityEngine;
using UnityEngine.VR;
using UnityEngine.UI;
using System.Collections;
[RequireComponent(typeof(Canvas))]
public class ScreenSpaceCanvas : MonoBehaviour
{
#region Constants
// The log base doesn't have any influence on the results whatsoever, as long as the same base is used everywhere.
private const float logBase = 2f;
#endregion
#region Inspector Fields
[Range(0f, 1f)]
public float matchWidthOrHeight = 0f;
public float distance = 1f;
#endregion
#region Private Fields
private Canvas canvas;
private RectTransform rt;
private Vector2 referenceResolution;
private float _scaleX = -1f;
private float _scaleY = -1f;
private float _width = -1f;
private float _height = -1f;
private bool _vr = false;
private float _scaleFactor = 1f;
#endregion
#region MonoBehaviour
//
void Awake()
{
canvas = GetComponent<Canvas>();
rt = GetComponent<RectTransform>();
}
//
void LateUpdate()
{
bool vr = false;// (UnityEngine.XR.XRSettings.loadedDevice != VRDeviceType.None);
if (_vr != vr)
{
_vr = vr;
if (_vr)
{
canvas.renderMode = RenderMode.WorldSpace;
}
else
{
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
_scaleX = -1f;
_scaleY = -1f;
_width = -1f;
_height = -1f;
}
}
if (_vr)
{
Rect pixelRect = canvas.pixelRect;
referenceResolution = new Vector2(pixelRect.width, pixelRect.height);
UpdateTransform(Camera.main);
}
}
#endregion
#region Private Methods
//
void UpdateTransform(Camera cam)
{
if (cam == null) { return; }
Transform camTr = cam.GetComponent<Transform>();
float width = Screen.width;
float height = Screen.height;
float frustumHeight = distance * Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
float frustumWidth = frustumHeight * 2f * cam.aspect;
float scaleX = (frustumWidth / width);
float scaleY = (frustumHeight / height) * 2f;
rt.position = camTr.TransformPoint(new Vector3(0f, 0f, distance));
rt.rotation = camTr.rotation;
// Same approach as in Unity built-in CanvasScaler component
float logWidth = Mathf.Log(width / referenceResolution.x, logBase);
float logHeight = Mathf.Log(height / referenceResolution.y, logBase);
float logWeightedAverage = Mathf.Lerp(logWidth, logHeight, matchWidthOrHeight);
float scaleFactor = Mathf.Pow(logBase, logWeightedAverage);
float scaleFactorInv = 1f / scaleFactor;
float canvasWidth = width * scaleFactorInv;
float canvasHeight = height * scaleFactorInv;
float canvasScaleX = scaleX * scaleFactor;
float canvasScaleY = scaleY * scaleFactor;
if (_width != canvasWidth)
{
_width = canvasWidth;
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _width);
}
if (_height != canvasHeight)
{
_height = canvasHeight;
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _height);
}
if (_scaleX != canvasScaleX || _scaleY != canvasScaleY)
{
_scaleX = canvasScaleX;
_scaleY = canvasScaleY;
rt.localScale = new Vector3(_scaleX, _scaleY, 1f);
}
if (scaleFactor != _scaleFactor)
{
_scaleFactor = scaleFactor;
canvas.scaleFactor = scaleFactor;
}
}
#endregion
}