123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- 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;
- /// <summary>
- /// UI的位姿出现类型
- /// </summary>
- public enum UIPoseType
- {
- /// <summary>
- /// 不对UI的位姿做任何处理
- /// </summary>
- Free,
- /// <summary>
- /// 始终朝向头部,位置不变
- /// </summary>
- FaceToHead,
- /// <summary>
- /// 与视野平行对齐
- /// </summary>
- AlignWithView,
- /// <summary>
- /// 刚性固定到头部,随相机移动和旋转
- /// </summary>
- FixedToHead,
- /// <summary>
- /// 超出视野后重置到头部前方,在相机视野外的时候将自己重置到相机前面,且面向相机
- /// </summary>
- RecenterIfOutOfView,
- /// <summary>
- /// 绑定在左手小拇指外侧
- /// </summary>
- LeftPinkySide,
- /// <summary>
- /// 绑定在右手小拇指外侧
- /// </summary>
- RightPinkySide,
- /// <summary>
- /// 绑定在左手手腕上
- /// </summary>
- OnLeftWrist,
- /// <summary>
- /// 绑定在右手手腕上
- /// </summary>
- OnRightWrist,
- }
- /// <summary>
- /// UI的位姿出现类型
- /// </summary>
- [SerializeField]
- protected UIPoseType positionType;
- /// <summary>
- /// UI的位姿出现类型
- /// </summary>
- 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;
- ///// <summary>
- ///// SharedMaterial
- ///// </summary>
- //public Material sharedMaterial;
- /// <summary>
- /// 此实例的Material
- /// </summary>
- public Material material;
- [SerializeField]
- private string text = "UI";
- /// <summary>
- /// UI上显示的文字
- /// </summary>
- 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;
- /// <summary>
- /// Text的颜色
- /// </summary>
- public Color TextColor
- {
- get
- {
- return textColor;
- }
- set
- {
- _text.color = value;
- }
- }
- protected MaterialPropertyBlock materialPropertyBlock;
- [SerializeField]
- private Color color = Color.white;
- /// <summary>
- /// UI的颜色
- /// </summary>
- public Color MainColor
- {
- get
- {
- return color;
- }
- set
- {
- materialPropertyBlock.SetColor("_Color", value);
- _meshRenderer.SetPropertyBlock(materialPropertyBlock);
- }
- }
- Color lastColor;
- [SerializeField]
- private Texture2D texture;
- /// <summary>
- /// UI的图
- /// </summary>
- public Texture2D Texture
- {
- get
- {
- return texture;
- }
- set
- {
- texture = value;
- SetMainMaterial();
- }
- }
- /// <summary>
- /// UI的叠加顺序
- /// </summary>
- public int sortingOrder;
- /// <summary>
- /// UI当前所应用的SpatialUIController.Instance.unitsPerPixel
- /// </summary>
- 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<LayoutGroup>()?.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<TextMesh>();
- }
- if (curUnitsPerPixel == 0)
- {
- curUnitsPerPixel = 0.0001f;
- }
- Core.PrefabUtility.UnpackPrefabInstance(gameObject);
- if (SpatialUIController.Instance == null)
- {
- Core.PrefabUtility.InstantiatePrefabWithUndoAndSelection(ResourcesManager.Load<GameObject>("SpatialUIController"));
- }
- if (SpatialUIEventSystem.Instance == null)
- {
- Core.PrefabUtility.InstantiatePrefabWithUndoAndSelection(ResourcesManager.Load<GameObject>("SpatialUIEventSystem"));
- }
- SpatialUIController.Instance.ReCalculateAllSize += ReCalculateSize;
- materialPropertyBlock = new MaterialPropertyBlock();
- _meshRenderer.GetPropertyBlock(materialPropertyBlock);
- #endif
- }
- }
- protected virtual void OnEnable()
- {
- transform.parent?.GetComponent<LayoutGroup>()?.ReLayout();
- }
- protected virtual void OnDisable()
- {
- transform.parent?.GetComponent<LayoutGroup>()?.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<MeshRenderer>();
- }
- _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);
- }
- }
- }
|