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); } } }