using EZXR.Glass.Inputs;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Wheels.Unity;
using EZXR.Glass.Core;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace EZXR.Glass.UI
{
[ExecuteInEditMode]
public class SpatialUIElement : MonoBehaviour
{
#region InternalUse
public Transform _visual;
public Transform _mesh;
public TextMesh _text;
public MeshRenderer _meshRenderer;
public MeshRenderer _textRenderer;
public Transform _subElements;
#endregion
public bool interactable = true;
///
/// UI的位姿出现类型
///
public enum UIPoseType
{
///
/// 不对UI的位姿做任何处理
///
Free,
///
/// 始终朝向头部,位置不变
///
FaceToHead,
///
/// 与视野平行对齐
///
AlignWithView,
///
/// 刚性固定到头部,随相机移动和旋转
///
FixedToHead,
///
/// 超出视野后重置到头部前方,在相机视野外的时候将自己重置到相机前面,且面向相机
///
RecenterIfOutOfView,
///
/// 绑定在左手小拇指外侧
///
LeftPinkySide,
///
/// 绑定在右手小拇指外侧
///
RightPinkySide,
///
/// 绑定在左手手腕上
///
OnLeftWrist,
///
/// 绑定在右手手腕上
///
OnRightWrist,
}
///
/// UI的位姿出现类型
///
[SerializeField]
protected UIPoseType positionType;
///
/// UI的位姿出现类型
///
public UIPoseType PositionType
{
get
{
return positionType;
}
set
{
if (positionType == UIPoseType.FixedToHead && value != UIPoseType.FixedToHead)
{
transform.CancelActAsChild();
}
positionType = value;
}
}
public Vector3 size = new Vector3(0.1f, 0.1f, 0.1f);
Vector3 prevSize = Vector3.zero;
/////
///// SharedMaterial
/////
//public Material sharedMaterial;
///
/// 此实例的Material
///
public Material material;
[SerializeField]
private string text = "UI";
///
/// UI上显示的文字
///
public string Text
{
get
{
return text;
}
set
{
if (string.IsNullOrEmpty(value))
{
_text.gameObject.SetActive(false);
}
else
{
_text.gameObject.SetActive(true);
}
text = value;
_text.text = text;
}
}
[SerializeField]
private Color textColor = Color.white;
///
/// Text的颜色
///
public Color TextColor
{
get
{
return textColor;
}
set
{
_text.color = value;
}
}
protected MaterialPropertyBlock materialPropertyBlock;
[SerializeField]
private Color color = Color.white;
///
/// UI的颜色
///
public Color MainColor
{
get
{
return color;
}
set
{
materialPropertyBlock.SetColor("_Color", value);
_meshRenderer.SetPropertyBlock(materialPropertyBlock);
}
}
Color lastColor;
[SerializeField]
private Texture2D texture;
///
/// UI的图
///
public Texture2D Texture
{
get
{
return texture;
}
set
{
texture = value;
SetMainMaterial();
}
}
///
/// UI的叠加顺序
///
public int sortingOrder;
///
/// UI当前所应用的SpatialUIController.Instance.unitsPerPixel
///
public float curUnitsPerPixel = 0.0001f;
public float ratio;
#if UNITY_EDITOR
protected virtual void ReCalculateSize(float newUnitsPerPixel, bool donotReCalSize = true)
{
ratio = newUnitsPerPixel / curUnitsPerPixel;
if (this != null)
{
if (donotReCalSize)
{
size *= (newUnitsPerPixel / curUnitsPerPixel);
}
else
{
if (Texture != null)
{
size = new Vector3(Texture.width * newUnitsPerPixel, Texture.height * newUnitsPerPixel, size.z);
}
}
////设置UI尺寸
//_mesh.localScale = size;
if (_text != null)
{
_text.transform.localPosition *= ratio;
_text.transform.localScale *= ratio;
}
curUnitsPerPixel = newUnitsPerPixel;
SceneView.RepaintAll();
}
}
#endif
protected virtual void OnValidate()
{
if (prevSize != size)
{
prevSize = size;
transform.parent?.GetComponent()?.ReLayout();
}
}
protected virtual void Awake()
{
gameObject.tag = interactable ? "SpatialUI" : "SpatialUI(NoInteractable)";
if (Application.isPlaying)
{
material = _meshRenderer.material;
materialPropertyBlock = new MaterialPropertyBlock();
_meshRenderer.GetPropertyBlock(materialPropertyBlock);
//设置Material(MaterialPropertyBlock)
SetMainMaterial();
}
else
{
#if UNITY_EDITOR
if (transform.Find("Visual/Text") != null)
{
_text = transform.Find("Visual/Text").GetComponentInChildren();
}
if (curUnitsPerPixel == 0)
{
curUnitsPerPixel = 0.0001f;
}
Core.PrefabUtility.UnpackPrefabInstance(gameObject);
if (SpatialUIController.Instance == null)
{
Core.PrefabUtility.InstantiatePrefabWithUndoAndSelection(ResourcesManager.Load("SpatialUIController"));
}
if (SpatialUIEventSystem.Instance == null)
{
Core.PrefabUtility.InstantiatePrefabWithUndoAndSelection(ResourcesManager.Load("SpatialUIEventSystem"));
}
SpatialUIController.Instance.ReCalculateAllSize += ReCalculateSize;
materialPropertyBlock = new MaterialPropertyBlock();
_meshRenderer.GetPropertyBlock(materialPropertyBlock);
#endif
}
}
protected virtual void OnEnable()
{
transform.parent?.GetComponent()?.ReLayout();
}
protected virtual void OnDisable()
{
transform.parent?.GetComponent()?.ReLayout();
}
protected virtual void Start()
{
switch (PositionType)
{
case UIPoseType.OnLeftWrist:
//OnWrist的UI初始化的时候应该在视野之外
transform.position = new Vector3(9999, 9999, 9999);
break;
case UIPoseType.FixedToHead:
transform.ActAsChild(SpatialUIController.Instance.leftCamera.transform);
break;
}
}
protected virtual void Update()
{
if (Application.isPlaying)
{
switch (PositionType)
{
case UIPoseType.FaceToHead:
transform.LookAt(SpatialUIController.Instance.leftCamera.transform);
break;
case UIPoseType.AlignWithView:
transform.LookAt(transform.position - SpatialUIController.Instance.leftCamera.transform.forward);
break;
case UIPoseType.RecenterIfOutOfView:
if (!SpatialUIController.Instance.leftCamera.rect.Contains(SpatialUIController.Instance.leftCamera.WorldToViewportPoint(transform.position)) && !SpatialUIController.Instance.rightCamera.rect.Contains(SpatialUIController.Instance.rightCamera.WorldToViewportPoint(transform.position)))
{
transform.position = SpatialUIController.Instance.leftCamera.transform.TransformPoint(new Vector3(0, 0, Vector3.Distance(transform.position, SpatialUIController.Instance.leftCamera.transform.position)));
transform.LookAt(transform.position + SpatialUIController.Instance.leftCamera.transform.forward);
}
break;
case UIPoseType.LeftPinkySide:
NativeSwapManager.Point3 temp = new NativeSwapManager.Point3(ARHandManager.leftHand.GetJointData(HandJointType.Pinky_1).position + ARHandManager.leftHand.GetJointData(HandJointType.Pinky_1).position - ARHandManager.leftHand.GetJointData(HandJointType.Index_1).position);
//NativeSwapManager.filterPoint(ref temp, transform.GetInstanceID());
transform.position = new Vector3(temp.x, temp.y, temp.z);
transform.LookAt(transform.position + ARHandManager.leftHand.palmDirection, ARHandManager.leftHand.palmNormal);
break;
case UIPoseType.OnLeftWrist:
if (ARHandManager.Instance.isActiveAndEnabled && ARHandManager.leftHand != null && ARHandManager.leftHand.Exist)
{
temp = new NativeSwapManager.Point3(ARHandManager.leftHand.GetJointData(HandJointType.Wrist_Middle).position);
//NativeSwapManager.filterPoint(ref temp, transform.GetInstanceID());
Vector3 newPos = new Vector3(temp.x, temp.y, temp.z);
if (Vector3.Distance(newPos, SpatialUIController.Instance.leftCamera.transform.position) > 0.1f)
{
transform.position = newPos + ARHandManager.leftHand.palmDirection.normalized * -0.03f;
transform.LookAt(transform.position + ARHandManager.leftHand.palmNormal, ARHandManager.leftHand.palmDirection.normalized);
}
}
else
{
transform.position = new Vector3(9999, 9999, 9999);
}
break;
}
}
else
{
#if UNITY_EDITOR
//if (SpatialUIController.Instance.unitsPerPixel != curUnitsPerPixel)
//{
// ReCalculateSize(SpatialUIController.Instance.unitsPerPixel, true);
//}
_meshRenderer.sortingOrder = sortingOrder;
if (Selection.activeGameObject != null && Selection.activeGameObject.hideFlags == HideFlags.NotEditable)
{
while (Selection.activeGameObject.transform.parent != null && (Selection.activeGameObject.hideFlags == HideFlags.NotEditable || Selection.activeGameObject.hideFlags == HideFlags.HideInHierarchy))
{
Selection.activeGameObject = Selection.activeGameObject.transform.parent.gameObject;
}
}
_visual = _mesh.parent;
//设置UI尺寸
_mesh.localScale = size;
//确保materialPropertyBlock不为空
if (materialPropertyBlock == null)
{
Awake();
}
//设置Material(MaterialPropertyBlock)
SetMainMaterial();
//_visual.gameObject.hideFlags = HideFlags.HideInHierarchy;
//_mesh.gameObject.hideFlags = HideFlags.NotEditable;
if (_text != null)
{
//_text.transform.hideFlags = HideFlags.HideInHierarchy;
_text.text = Text;
_text.color = textColor;
_text.gameObject.SetActive(!string.IsNullOrEmpty(Text));
if (_textRenderer == null)
{
_textRenderer = _text.GetComponent();
}
_textRenderer.sortingOrder = sortingOrder + 1;
}
#endif
}
}
protected virtual void OnDestroy()
{
if (!Application.isPlaying)
{
#if UNITY_EDITOR
if (SpatialUIController.Instance != null)
{
SpatialUIController.Instance.ReCalculateAllSize -= ReCalculateSize;
}
#endif
}
}
private void SetMainMaterial()
{
//设置UI的bgImage(确保Texture的设定相对于其他的materialPropertyBlock的Set是最前的,因为无法直接SetTexture为null)
//if (bgImage != lastBGImage)
{
if (Texture != null)
{
materialPropertyBlock.SetTexture("_MainTex", Texture);
}
else
{
//重置materialPropertyBlock,因为无法直接SetTexture为null
materialPropertyBlock.Clear();
}
}
//设置UI的颜色
//if (color != lastColor)
{
materialPropertyBlock.SetColor("_Color", color);
lastColor = color;
}
_meshRenderer.SetPropertyBlock(materialPropertyBlock);
}
}
}