369 lines
12 KiB
C#
369 lines
12 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Beyond
|
|
{
|
|
|
|
public class Compass : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
class CompassItem
|
|
{
|
|
public RectTransform m_Icon;
|
|
public Vector3 m_location;
|
|
public Transform m_transform;
|
|
public TextMeshProUGUI m_distanceTxt;
|
|
[Tooltip("Is true if location vector represents direction, false for position")]
|
|
public bool m_locationIsDirection;
|
|
public float m_range = float.PositiveInfinity;
|
|
public float m_minDistance = 0f;
|
|
public NavigationIndicator m_indicator;
|
|
}
|
|
public bool m_onlyIndicator = true;
|
|
public NavigationIndicator m_indicatorPrefab;
|
|
|
|
[Tooltip("Where is north on the game map? (angle from Z axis)")]
|
|
public float m_northAngle = 0f;
|
|
List<CompassItem> m_CompassItems;
|
|
public RectTransform m_NIcon;
|
|
public RectTransform m_SIcon;
|
|
public RectTransform m_WIcon;
|
|
public RectTransform m_EIcon;
|
|
public RectTransform m_NEIcon;
|
|
public RectTransform m_NWIcon;
|
|
public RectTransform m_SEIcon;
|
|
public RectTransform m_SWIcon;
|
|
public GameObject m_Divider;
|
|
public RectTransform m_QuestMarkers;
|
|
public float m_minPos = -600f;
|
|
public float m_maxPos = 600f;
|
|
public bool m_keepVisible = true;
|
|
public GameObject m_root;
|
|
|
|
public GameObject m_testObject;
|
|
//public Sprite m_defaultMarkerSprite;
|
|
|
|
Vector3 m_NVector;
|
|
Vector3 m_SVector;
|
|
Vector3 m_WVector;
|
|
Vector3 m_EVector;
|
|
|
|
|
|
|
|
Camera m_camera;
|
|
// Start is called before the first frame update
|
|
|
|
private static Compass s_instance = null;
|
|
|
|
public static Compass Instance
|
|
{
|
|
get
|
|
{
|
|
return s_instance;
|
|
}
|
|
}
|
|
private void Awake()
|
|
{
|
|
TryInitialize();
|
|
}
|
|
|
|
public void TryInitialize()
|
|
{
|
|
if (s_instance == null)
|
|
{
|
|
s_instance = this;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Compass intance already exists!");
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
m_CompassItems = new List<CompassItem>();
|
|
|
|
if (m_NIcon == null)
|
|
Debug.LogError("Compass: 'N' Icon not set");
|
|
if (m_SIcon == null)
|
|
Debug.LogError("Compass: 'S' Icon not set");
|
|
if (m_WIcon == null)
|
|
Debug.LogError("Compass: 'W' Icon not set");
|
|
if (m_EIcon == null)
|
|
Debug.LogError("Compass: 'E' Icon not set");
|
|
|
|
m_camera = Camera.main;
|
|
if (m_camera == null)
|
|
{
|
|
Debug.LogError("Compass: Camera not found!");
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
if (m_onlyIndicator)
|
|
{
|
|
/*
|
|
m_NIcon.enabled = false;
|
|
m_SIcon.enabled = false;
|
|
m_WIcon.enabled = false;
|
|
m_EIcon.enabled = false;
|
|
m_NEIcon.enabled = false;
|
|
m_NWIcon.enabled = false;
|
|
m_SEIcon.enabled = false;
|
|
m_SWIcon.enabled = false;
|
|
*/
|
|
//Show(false);
|
|
return;
|
|
}
|
|
//m_NVector = new Vector3(1f, 0f, 0f);
|
|
m_NVector = new Vector3(0f, 0f, 1f);
|
|
float angle;
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
Quaternion r = Quaternion.AngleAxis(i * -15f, Vector3.up);
|
|
CompassItem it = new CompassItem();
|
|
if (i % 3 > 0)
|
|
{
|
|
var go = Instantiate(m_Divider, m_Divider.transform.parent);
|
|
it.m_Icon = go.GetComponent<RectTransform>();
|
|
it.m_Icon.position = m_Divider.transform.position;
|
|
}
|
|
|
|
// it.m_Icon = m_NIcon;
|
|
angle = (m_northAngle + i * -15f) * Mathf.Deg2Rad;
|
|
it.m_location = r * m_NVector;
|
|
it.m_location.x = Mathf.Cos(angle);
|
|
it.m_location.z = -Mathf.Sin(angle);
|
|
it.m_locationIsDirection = true;
|
|
//if (m_)
|
|
m_CompassItems.Add(it);
|
|
}
|
|
m_CompassItems[0].m_Icon = m_NIcon;
|
|
m_CompassItems[3].m_Icon = m_NWIcon;
|
|
m_CompassItems[6].m_Icon = m_WIcon;
|
|
m_CompassItems[9].m_Icon = m_SWIcon;
|
|
m_CompassItems[12].m_Icon = m_SIcon;
|
|
m_CompassItems[15].m_Icon = m_SEIcon;
|
|
m_CompassItems[18].m_Icon = m_EIcon;
|
|
m_CompassItems[21].m_Icon = m_NEIcon;
|
|
|
|
m_Divider.SetActive(false);
|
|
}
|
|
void Start()
|
|
{
|
|
if (m_testObject != null)
|
|
AddQuestMarker(m_testObject.transform, null);
|
|
if (m_onlyIndicator)
|
|
{
|
|
Show(false);
|
|
}
|
|
}
|
|
|
|
public void AddQuestMarker(Transform q, Sprite icon, float minDistance = 0f)
|
|
{
|
|
CompassItem item = new CompassItem();
|
|
if (!m_onlyIndicator)
|
|
{
|
|
if (m_QuestMarkers == null)
|
|
{
|
|
Debug.LogError("Compass: Quest marker prefab is null");
|
|
return;
|
|
}
|
|
var qo = GameObject.Instantiate<RectTransform>(m_QuestMarkers, m_Divider.transform.parent);
|
|
if (icon != null)
|
|
{
|
|
var img = qo.GetComponent<Image>();
|
|
img.sprite = icon;
|
|
}
|
|
qo.gameObject.SetActive(true);
|
|
item.m_Icon = qo;
|
|
item.m_distanceTxt = qo.gameObject.FindComponentDownHierarchy<TextMeshProUGUI>();
|
|
}
|
|
//var ind = GameObject.Instantiate<NavigationIndicator>(m_indicatorPrefab, transform);
|
|
var ind = GameObject.Instantiate<NavigationIndicator>(m_indicatorPrefab, transform.parent);
|
|
ind.SetTargetTransform(q);
|
|
//if (icon == null)
|
|
// icon = m_defaultMarkerSprite;
|
|
|
|
item.m_transform = q;
|
|
item.m_location = q.position;
|
|
item.m_locationIsDirection = false;
|
|
item.m_minDistance = minDistance;
|
|
item.m_indicator = ind;
|
|
m_CompassItems.Add(item);
|
|
}
|
|
|
|
public Transform FindClosestIndicator(Transform t)
|
|
{
|
|
Transform result = null;
|
|
float dist = Single.MaxValue;
|
|
|
|
for (int i = 24; i < m_CompassItems.Count; i++)
|
|
{
|
|
var d = (m_CompassItems[i].m_transform.position - t.position).magnitude;
|
|
if (dist > d)
|
|
{
|
|
dist = d;
|
|
result = m_CompassItems[i].m_transform;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void SetQuestMarkerDistance(Transform q, float dist)
|
|
{
|
|
var ci = m_CompassItems.Find(quest => quest.m_transform == q);
|
|
if (ci != null)
|
|
{
|
|
ci.m_minDistance = dist;
|
|
}
|
|
}
|
|
|
|
public void RemoveQuestMarker(Transform q)
|
|
{
|
|
var ci = m_CompassItems.Find(quest => quest.m_transform == q);
|
|
if (ci != null)
|
|
{
|
|
if (ci.m_Icon && ci.m_Icon.gameObject)
|
|
Destroy(ci.m_Icon.gameObject);
|
|
if (ci.m_indicator && ci.m_indicator.gameObject)
|
|
Destroy(ci.m_indicator.gameObject);
|
|
m_CompassItems.Remove(ci);
|
|
}
|
|
}
|
|
|
|
public void Show(bool flag)
|
|
{
|
|
if (m_root)
|
|
m_root.SetActive(flag);
|
|
else
|
|
{
|
|
gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (m_onlyIndicator)
|
|
return;
|
|
|
|
Vector3 pos = Player.Instance != null ? Player.Instance.transform.position : m_camera.transform.position;
|
|
foreach (var ci in m_CompassItems)
|
|
{
|
|
|
|
|
|
Vector3 wordPos;
|
|
float distance = float.PositiveInfinity;
|
|
if (ci.m_locationIsDirection)
|
|
wordPos = ci.m_location * m_camera.farClipPlane + pos;
|
|
else
|
|
{
|
|
if (ci.m_transform != null)
|
|
ci.m_location = ci.m_transform.position;
|
|
wordPos = ci.m_location;
|
|
var diff = wordPos - pos;
|
|
diff.y = 0;
|
|
distance = diff.magnitude;
|
|
if (ci.m_distanceTxt != null)
|
|
{
|
|
ci.m_distanceTxt.text = distance.ToString("F0")+"m";
|
|
}
|
|
}
|
|
Vector3 screenPos;// = m_NIcon.position;
|
|
Vector3 viewPortPos = m_camera.WorldToViewportPoint(wordPos);
|
|
screenPos = m_camera.WorldToScreenPoint(wordPos);
|
|
|
|
//check conditions to skip/disable
|
|
if (ci.m_locationIsDirection)
|
|
{
|
|
if (screenPos.z < 0)
|
|
{
|
|
ci.m_Icon.gameObject.SetActive(false);
|
|
continue;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (ci.m_range < distance || distance < ci.m_minDistance)
|
|
{
|
|
ci.m_Icon.gameObject.SetActive(false);
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
ci.m_Icon.gameObject.SetActive(true);
|
|
|
|
if (!ci.m_locationIsDirection) //is it a point or direction?
|
|
{
|
|
//keep oryginal y position
|
|
/*
|
|
if (screenPos.z < 0)
|
|
{
|
|
screenPos.x *= -1f;
|
|
}
|
|
screenPos.y = ci.m_Icon.position.y;
|
|
screenPos.z = ci.m_Icon.position.z;
|
|
|
|
ci.m_Icon.position = screenPos;
|
|
|
|
var lpos = ci.m_Icon.localPosition;
|
|
lpos.x = Math.Min(lpos.x, m_maxPos);
|
|
lpos.x = Math.Max(lpos.x, m_minPos);
|
|
ci.m_Icon.localPosition = lpos;
|
|
*/
|
|
|
|
screenPos.y = ci.m_Icon.position.y;
|
|
screenPos.z = ci.m_Icon.position.z;
|
|
ci.m_Icon.position = screenPos;
|
|
|
|
|
|
var lpos = ci.m_Icon.localPosition;
|
|
//keep oryginal y position
|
|
if (viewPortPos.z >= 0)
|
|
{
|
|
// screenPos.x *= -1f;
|
|
lpos.x = Math.Min(lpos.x, m_maxPos);
|
|
lpos.x = Math.Max(lpos.x, m_minPos);
|
|
}
|
|
else
|
|
{
|
|
if (lpos.x > 0)
|
|
{
|
|
lpos.x = m_minPos;
|
|
}
|
|
else
|
|
{
|
|
lpos.x = m_maxPos;
|
|
// lpos.x = m_minPos;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// lpos.x = Math.Min(lpos.x, m_maxPos);
|
|
// lpos.x = Math.Max(lpos.x, m_minPos);
|
|
ci.m_Icon.localPosition = lpos;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
screenPos.y = ci.m_Icon.position.y;
|
|
screenPos.z = ci.m_Icon.position.z;
|
|
ci.m_Icon.position = screenPos;
|
|
ci.m_Icon.position = screenPos;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}; |