214 lines
7.3 KiB
C#
214 lines
7.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using WI;
|
|
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<Vector3, Vector3> dirTable = new();
|
|
|
|
TwinObject target;
|
|
HashSet<TwinObject> targets = new();
|
|
public event Action onTargetEvent;
|
|
public event Action onTargetMissing;
|
|
public event Action<Vector3, int, int> onLineUpdate;
|
|
|
|
public void Initialize()
|
|
{
|
|
var lineMat = Resources.Load<Material>("Materials/Mat_LineRender");
|
|
for (int i = 0; i < lineRenderers.Length; i++)
|
|
{
|
|
lineRenderers[i] = new GameObject("DistanceLine").AddComponent<LineRenderer>();
|
|
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
|
|
}
|
|
}
|
|
}
|