using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEditor; using XRLib; using XED.UI; namespace XED.UI { //TODO::areabox°¡ ¾Æ´Ï¶ó TwinObject¸¦ ´ë»óÀ¸·Î µ¿ÀÛÇϵµ·Ï ¼öÁ¤ public class ObjectDistanceLine : MonoBehaviour, ISingle { private Vector3 centerPoint = new(); private Vector3[] edges = new Vector3[4]; private LineRenderer[] lineRenderers = new LineRenderer[4]; private int[] distances = new int[4]; private Vector3[] hits = new Vector3[4]; [SerializeField] private float thickness; private int rot; private Dictionary dirTable = new(); TwinObject target; HashSet targets = new(); public event Action onTargetEvent; public event Action onTargetMissing; public event Action onLineUpdate; public void Initialize() { var lineMat = Resources.Load("Materials/Mat_LineRender"); for (int i = 0; i < lineRenderers.Length; i++) { lineRenderers[i] = new GameObject("DistanceLine").AddComponent(); lineRenderers[i].transform.SetParent(transform, true); lineRenderers[i].material = lineMat; lineRenderers[i].positionCount = 2; lineRenderers[i].startWidth = thickness; lineRenderers[i].endWidth = thickness; } } public void SetTarget(TwinObject target) { if (target is Wall || target is WallGroup) return; this.target = target; targets.Add(target); gameObject.SetActive(true); onTargetEvent?.Invoke(); } private void EdgePoints() { var size = target.physics.areabox.bounds.size; edges[0] = centerPoint + EdgePointCalculate(-size.x, -size.z, centerPoint); edges[1] = centerPoint + EdgePointCalculate(size.x, -size.z, centerPoint); edges[2] = centerPoint + EdgePointCalculate(size.x, size.z, centerPoint); edges[3] = centerPoint + EdgePointCalculate(-size.x, size.z, centerPoint); } private void CenterPoints() { var size = target.physics.areabox.bounds.size; edges[0] = centerPoint + EdgePointCalculate(-size.x, 0f, centerPoint); edges[1] = centerPoint + EdgePointCalculate(size.x, 0f, centerPoint); edges[2] = centerPoint + EdgePointCalculate(0f, -size.z, centerPoint); edges[3] = centerPoint + EdgePointCalculate(0f, size.z, centerPoint); } private Vector3 EdgePointCalculate(float xValue, float zValue, Vector3 center) { //´ë°¢¼±ÀÇ ±æÀÌ, //ÁßÁ¡±æÀÌ var point = center + (new Vector3(xValue, 0, zValue) * 0.5f); var length = Vector3.Distance(point, center); var dir = (point - center).normalized * length; //var pos = RotateVector3(dir, rot); var pos = Quaternion.AngleAxis(rot, Vector3.up) * dir; return pos; } public void Off() { targets.Clear(); onTargetMissing?.Invoke(); } void LineRenderSetActive(bool isActive) { foreach(var line in lineRenderers) { line.enabled = isActive; } } private void Update() { if (target == null || targets.Count >1) { Off(); LineRenderSetActive(false); return; } //if (areabox == null) // return; //Distance°¡ 4°³ ¸ðµÎ 0À̸é return? LineRenderSetActive(true); rot = Mathf.RoundToInt(target.physics.areabox.transform.localEulerAngles.y); centerPoint = new Vector3(target.physics.areabox.bounds.center.x, 0, target.physics.areabox.bounds.center.z); var angle = rot % 90f; if (Mathf.Approximately(angle, 0f)) CenterPoints(); else EdgePoints(); var xOrder = edges.OrderBy(l => l.x); var zOrder = edges.OrderBy(l => l.z); dirTable.Clear(); dirTable.TryAdd(xOrder.ElementAt(0), Vector3.left); dirTable.TryAdd(xOrder.ElementAt(3), Vector3.right); dirTable.TryAdd(zOrder.ElementAt(0), Vector3.back); dirTable.TryAdd(zOrder.ElementAt(3), Vector3.forward); for (int i = 0; i < edges.Length; i++) { //var dir = Dir(dirTable[edges[i]]); var dir = dirTable[edges[i]]; if (Physics.Raycast(edges[i], dir, out RaycastHit hit, Mathf.Infinity)) { hits[i] = hit.point; } else { hits[i] = edges[i]; } distances[i] = Mathf.RoundToInt(Vector3.Distance(hits[i], edges[i]) * 1000f); lineRenderers[i].SetPosition(0, edges[i]); lineRenderers[i].SetPosition(1, hits[i]); //3¹æÇâÁß Á¡Áß °¡Àå ªÀº°Å var pos = DistanceTextPos(edges[i], hits[i]); if (Mathf.Abs(pos.y) == Mathf.Infinity || float.IsNaN(pos.y)) continue; onLineUpdate?.Invoke(pos, i, distances[i]); } } private Vector3 DistanceTextPos(Vector3 edge, Vector3 hit) { var x = Screen.width; var y = Screen.height; var hitpoint = Camera.main.WorldToScreenPoint(hit); var edgePoint = Camera.main.WorldToScreenPoint(edge); //Ä«¸Þ¶ó ³¡Á¡ edge¿Í hit »çÀÌ; //±â¿ï±â °¡Á®¿Â´Ù var m = (hitpoint.y - edgePoint.y) / (hitpoint.x - edgePoint.x); if (hitpoint.y > y) { var yPos = y; var xPos = ((yPos - edgePoint.y) / m) + edgePoint.x; hitpoint = new Vector3(xPos, yPos); } else if (hitpoint.y < 0) { var yPos = 0; var xPos = ((yPos - edgePoint.y) / m) + edgePoint.x; hitpoint = new Vector3(xPos, yPos); } if (hitpoint.x > x) { var xPos = x; var yPos = (m * (xPos - edgePoint.x)) + edgePoint.y; hitpoint = new Vector3(xPos, yPos); } else if (hitpoint.x < 0) { var xPos = 0; var yPos = (m * (xPos - edgePoint.x)) + edgePoint.y; hitpoint = new Vector3(xPos, yPos); } var center = (hitpoint + edgePoint) * 0.5f; return center; } void Gizmo() { #if UNITY_EDITOR // for (int i = 0; i < edges.Length; ++i) // { // Gizmos.DrawSphere(edges[i].pos, 0.1f); // } // for (int i = 0; i < hits.Length; ++i) // { // var dir = Dir(dirTable[edges[i]]); // Handles.color = Color.yellow; // Handles.DrawLine(edges[i].pos, hits[i], 1); // Gizmos.DrawRay(edges[i].pos, dir * 10f); // } #endif } } }