using UnityEngine; using UnityEngine.UI; using QFramework; using ChivaXR; using ChivaXR.Op; using Google.Protobuf.WellKnownTypes; using System.Collections.Generic; namespace QFramework { public class ArrowTipsPanelData : UIPanelData { } public partial class ArrowTipsPanel : UIPanel { private Transform targetPoint; private Camera viewCamera; private OpTrigger_ToolPack opTrigger_ToolPack; //多区域提示功能 private List opTrigger_ToolPacks = new List(); private Dictionary dic_TipsFreeIconItems = new Dictionary(); private List tipsFreeIconItemsPool = new List(); public Camera ViewCamera { get { if (viewCamera == null) { viewCamera = RoamCameraController.Instance.GetComponent(); } return viewCamera; } } protected override void ProcessMsg(int eventId, QMsg msg) { throw new System.NotImplementedException(); } private Canvas m_Canvas; private CanvasScaler m_CanvasScaler; protected override void OnInit(IUIData uiData = null) { mData = uiData as ArrowTipsPanelData ?? new ArrowTipsPanelData(); TipsIcon.gameObject.SetActive(false); OutViewIcon.gameObject.SetActive(false); // please add init code here if (viewCamera == null) { Debug.Log("请使用RoamCameraController控制脚本"); } m_Canvas = UIRoot.Instance.GetComponent(); m_CanvasScaler = m_Canvas.GetComponent(); if (OperateSetting.Instance.m_CurrentOperationMode == OperationMode.Practice || OperateSetting.Instance.m_CurrentOperationMode == OperationMode.Exam) { ProcessManagement.Instance.preprocessFnishedEvent += PreProcessFinished; ProcessManagement.Instance.processFinishEvent += FinishedProcess; } } public void LateUpdate() { if (OperateSetting.Instance.m_CurrentOperationMode == OperationMode.Practice || OperateSetting.Instance.m_CurrentOperationMode == OperationMode.Exam) { CheckOperationHint(); } if (OperateSetting.Instance.m_CurrentOperationMode == OperationMode.FreeParctice || OperateSetting.Instance.m_CurrentOperationMode == OperationMode.FreeParctice) { CheckFreeOperationHint(); } } public void AddProcessElement(ProcessElement process, string processName = null) { PB_OpData pbOpData = process.GetComponent(); if (OperationManager.Instance.GetOpData(pbOpData.opData.operationDataName) == null) { return; } OpTrigger_ToolPack opTrigger_ToolPack = OperationManager.Instance.GetOpData(pbOpData.opData.operationDataName).gameObject.GetComponent(); if (opTrigger_ToolPack == null) { return; }; if (!dic_TipsFreeIconItems.ContainsKey(opTrigger_ToolPack)) { dic_TipsFreeIconItems.Add(opTrigger_ToolPack, GetTipsFreeIconItem()); dic_TipsFreeIconItems[opTrigger_ToolPack].TipsFreeInfo.text = processName; } } public void RemoveProcessElement(ProcessElement process) { PB_OpData pbOpData = process.GetComponent(); if (OperationManager.Instance.GetOpData(pbOpData.opData.operationDataName) == null) { return; } OpTrigger_ToolPack opTrigger_ToolPack = OperationManager.Instance.GetOpData(pbOpData.opData.operationDataName).gameObject.GetComponent(); if (opTrigger_ToolPack == null) { return; }; if (dic_TipsFreeIconItems.ContainsKey(opTrigger_ToolPack)) { ReleaseTipsFreeIconItem(dic_TipsFreeIconItems[opTrigger_ToolPack]); dic_TipsFreeIconItems.Remove(opTrigger_ToolPack); } } public TipsFreeIconItem GetTipsFreeIconItem() { if (tipsFreeIconItemsPool.Count == 0) { TipsFreeIconItem tip = GameObject.Instantiate(TipsFreeIconItem).GetComponent(); tip.transform.parent = TipsGroup.transform; tip.transform.localScale = Vector3.one; tip.gameObject.SetActive(true); return tip; } else { TipsFreeIconItem tip = tipsFreeIconItemsPool[0]; tipsFreeIconItemsPool.Remove(tip); tip.gameObject.SetActive(true); return tip; } } public void ReleaseTipsFreeIconItem(TipsFreeIconItem tip) { tip.gameObject.SetActive(false); tip.TipsFreeInfo.text = ""; tipsFreeIconItemsPool.Add(tip); } private void CheckFreeOperationHint() { if (dic_TipsFreeIconItems.Count == 0) return; foreach (var item in dic_TipsFreeIconItems) { Vector3 viewPos = ViewCamera.WorldToScreenPoint(item.Key.targetObjs[0].transform.position); item.Value.GetRectTransform().anchoredPosition = new Vector3(GetFixed(viewPos.x), GetFixed(viewPos.y)); float distance = Vector3.Distance(item.Key.targetObjs[0].transform.position, ViewCamera.transform.position); item.Value.TipsFreeDistanceInfo.text = distance.ToString("0.00") + "m"; } } /// /// 检测执行线性流程提示 /// private void CheckOperationHint() { if (targetPoint == null || opTrigger_ToolPack == null) return; if (opTrigger_ToolPack.OperationStatus != OperationDataStatus.Listening) { opTrigger_ToolPack = null; Clear(); return; } if (!OperateSetting.Instance.ToolPackUILogic.GetHint() || !opTrigger_ToolPack.IsGetRightTool()) { TipsIcon.gameObject.SetActive(false); OutViewIcon.gameObject.SetActive(false); return; } Vector3 viewPos = ViewCamera.WorldToScreenPoint(targetPoint.position); TipsIcon.rectTransform.anchoredPosition = new Vector3(GetFixed(viewPos.x), GetFixed(viewPos.y)); ArrowController(); float distance = Vector3.Distance(targetPoint.position, ViewCamera.transform.position); DistanceInfo.text = distance.ToString("0.00") + "m"; if (distance < 1) { TipsIcon.gameObject.SetActive(false); } else if (!OutViewIcon.gameObject.activeSelf) { TipsIcon.gameObject.SetActive(true); } } /// /// 前置步骤结束 /// /// public void PreProcessFinished(ProcessElement processElement) { if (processElement.GetComponent() != null) { PB_OpData pbOpData = processElement.GetComponent(); if (OperationManager.Instance.GetOpData(pbOpData.opData.operationDataName) == null) { return; } opTrigger_ToolPack = OperationManager.Instance.GetOpData(pbOpData.opData.operationDataName).gameObject.GetComponent(); } else { PB_OpDataGroup pbOpData = processElement.GetComponent(); opTrigger_ToolPack = OperationManager.Instance.GetOpData(pbOpData.opDataInfos[0].operationDataName).gameObject.GetComponent(); } if (opTrigger_ToolPack != null) { if (opTrigger_ToolPack.targetObjs.Count > 0) { InitTarget(opTrigger_ToolPack.targetObjs[0].transform); } } else { Clear(); } } public void FinishedProcess() { Clear(); } //Screen坐标值适配Canvas画布 public float GetFixed(float value) { if (m_CanvasScaler.matchWidthOrHeight == 0) //匹配宽度时仅按照宽度计算 return value * m_CanvasScaler.referenceResolution.x / Screen.width; else //匹配高度时仅按照高度计算 return value * m_CanvasScaler.referenceResolution.y / Screen.height; } /// /// 初始化提示目标 /// /// public void InitTarget(Transform target) { targetPoint = target; if (targetPoint.Find("HintPoint") != null) { targetPoint = targetPoint.Find("HintPoint"); }; Debug.Log(targetPoint.name); } public void Clear() { targetPoint = null; TipsIcon.gameObject.SetActive(false); OutViewIcon.gameObject.SetActive(false); //Hide(); } protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } private float targetAngle; /// /// 箭头控制提示控制 /// public void ArrowController() { if (targetPoint == null) return; //物体转化为摄像机屏幕坐标 Vector3 screenPointInV3 = ViewCamera.WorldToScreenPoint(targetPoint.position); Vector2 screenPoint = new Vector2(screenPointInV3.x, screenPointInV3.y); float r = 350; float R = 500; Vector3 center = Vector3.zero; float hudu = (targetAngle / 180) * Mathf.PI; float xx = center.x + r * Mathf.Cos(hudu); float yy = center.y + R * Mathf.Sin(hudu); Vector3 pos = new Vector3(-yy, xx, 0); if (screenPointInV3.z <= 0) //物体在摄像机后方 { Vector3 screenCenterPos = new Vector3(ViewCamera.pixelWidth / 2, ViewCamera.pixelHeight / 2, 0); float angle = 90; if (Vector3.Cross(Vector3.up, (screenPointInV3 - screenCenterPos)).z < 0) { angle = -angle; } targetAngle = -angle; TipsIcon.gameObject.SetActive(false); if (!OutViewIcon.gameObject.activeSelf) { OutViewIcon.gameObject.SetActive(true); } OutViewIcon.rectTransform.anchoredPosition = pos; DirRoot.rotation = Quaternion.Euler(0, 0, targetAngle); } else if (!ViewCamera.pixelRect.Contains(screenPoint)) //摄像机正面且不在画面中 { Vector3 screenCenterPos = new Vector3(ViewCamera.pixelWidth / 2, ViewCamera.pixelHeight / 2, 0); float angle = Vector3.Angle(Vector3.up, (screenPointInV3 - screenCenterPos)); if (Vector3.Cross(Vector3.up, (screenPointInV3 - screenCenterPos)).z > 0) { angle = -angle; } targetAngle = -angle; if (!OutViewIcon.gameObject.activeSelf) { OutViewIcon.gameObject.SetActive(true); OutViewIcon.rectTransform.anchoredPosition = pos; DirRoot.rotation = Quaternion.Euler(0, 0, targetAngle); } //不同侧不做插值移动 if (OutViewIcon.rectTransform.anchoredPosition.x * pos.x < 0 || OutViewIcon.rectTransform.anchoredPosition.y * pos.y < 0) { OutViewIcon.rectTransform.anchoredPosition = pos; DirRoot.rotation = Quaternion.Euler(0, 0, targetAngle); } OutViewIcon.rectTransform.anchoredPosition = Vector3.Lerp(OutViewIcon.rectTransform.anchoredPosition, pos, 0.2f); } else { OutViewIcon.gameObject.SetActive(false); TipsIcon.gameObject.SetActive(true); } DirRoot.rotation = Quaternion.Lerp(DirRoot.rotation, Quaternion.Euler(0, 0, targetAngle), 0.2f); } } }