418 lines
14 KiB
C#
418 lines
14 KiB
C#
#define Graph_And_Chart_PRO
|
|
using ChartAndGraph;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
/// <summary>
|
|
/// posistions world space text on a special canvas used for billboarding.
|
|
/// </summary>
|
|
[RequireComponent(typeof(ChartItem))]
|
|
[ExecuteInEditMode]
|
|
public class TextController : MonoBehaviour
|
|
{
|
|
public Camera Camera = null;
|
|
Canvas mCanvas;
|
|
RectTransform mRect;
|
|
List<BillboardText> mText = new List<BillboardText>();
|
|
public float PlaneDistance = 4;
|
|
Vector3[] mPlaneCorners = new Vector3[4];
|
|
bool mInvalidated = false;
|
|
private AnyChart mPrivateParent;
|
|
float mPrevScale = -1f;
|
|
bool OwnsCanvas = false;
|
|
//private bool mUnderCanvas = false;
|
|
internal List<BillboardText> Text { get { return mText; } }
|
|
GameObject mAddCanvasUnder = null;
|
|
float mInnerScale = 1.0f;
|
|
|
|
public float GlobalRotation
|
|
{
|
|
get; set;
|
|
}
|
|
internal void SetInnerScale(float scale)
|
|
{
|
|
mInnerScale = scale;
|
|
}
|
|
|
|
internal AnyChart mParent
|
|
{
|
|
get { return mPrivateParent; }
|
|
set
|
|
{
|
|
mPrivateParent = value;
|
|
if (mPrivateParent != null)
|
|
{
|
|
Camera = ((IInternalUse)mPrivateParent).InternalTextCamera;
|
|
PlaneDistance = ((IInternalUse)mPrivateParent).InternalTextIdleDistance;
|
|
if (OwnsCanvas)
|
|
SafeCanvas.planeDistance = PlaneDistance;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
EnsureCanvas();
|
|
Canvas.willRenderCanvases += Canvas_willRenderCanvases;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
Canvas.willRenderCanvases -= Canvas_willRenderCanvases;
|
|
}
|
|
|
|
private void Canvas_willRenderCanvases()
|
|
{
|
|
|
|
if (this == null)
|
|
{
|
|
Canvas.willRenderCanvases -= Canvas_willRenderCanvases;
|
|
return;
|
|
}
|
|
ApplyTextPosition();
|
|
}
|
|
|
|
void EnsureCanvas()
|
|
{
|
|
|
|
if (mCanvas == null)
|
|
{
|
|
mCanvas = GetComponentInParent<Canvas>();
|
|
if (mCanvas == null)
|
|
{
|
|
OwnsCanvas = true;
|
|
mAddCanvasUnder = new GameObject();
|
|
ChartCommon.HideObject(mAddCanvasUnder, true);
|
|
mAddCanvasUnder.AddComponent<ChartItemNoDelete>();
|
|
mAddCanvasUnder.AddComponent<RectTransform>();
|
|
mAddCanvasUnder.transform.SetParent(gameObject.transform, false);
|
|
mAddCanvasUnder.transform.localPosition = Vector3.zero;
|
|
mAddCanvasUnder.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
mAddCanvasUnder.transform.localRotation = Quaternion.identity;
|
|
|
|
mCanvas = mAddCanvasUnder.AddComponent<Canvas>();
|
|
mAddCanvasUnder.AddComponent<CanvasScaler>();
|
|
mAddCanvasUnder.AddComponent<GraphicRaycaster>();
|
|
|
|
if (mParent != null && (mParent.VRSpaceText || mParent.PaperEffectText))
|
|
{
|
|
mCanvas.renderMode = RenderMode.WorldSpace;
|
|
}
|
|
else
|
|
{
|
|
mCanvas.renderMode = RenderMode.ScreenSpaceCamera;
|
|
}
|
|
mCanvas.planeDistance = PlaneDistance;
|
|
Camera = EnsureCamera();
|
|
mRect = mCanvas.GetComponent<RectTransform>();
|
|
// mCanvas.pixelPerfect = true;
|
|
CanvasScaler scaler = mCanvas.GetComponent<CanvasScaler>();
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize;
|
|
}
|
|
else
|
|
{
|
|
//mUnderCanvas = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Canvas SafeCanvas
|
|
{
|
|
get
|
|
{
|
|
EnsureCanvas();
|
|
return mCanvas;
|
|
}
|
|
}
|
|
|
|
void OnDestory()
|
|
{
|
|
DestroyAll();
|
|
}
|
|
|
|
public void DestroyAll()
|
|
{
|
|
for (int i = 0; i < mText.Count; i++)
|
|
{
|
|
if (mText[i] != null && mText[i].Recycled == false)
|
|
{
|
|
if (mText[i].UIText != null)
|
|
ChartCommon.SafeDestroy(mText[i].UIText.gameObject);
|
|
if (mText[i].RectTransformOverride != null)
|
|
ChartCommon.SafeDestroy(mText[i].RectTransformOverride.gameObject);
|
|
mText[i].UIText = null;
|
|
mText[i].RectTransformOverride = null;
|
|
ChartCommon.SafeDestroy(mText[i].gameObject);
|
|
}
|
|
}
|
|
mText.Clear();
|
|
}
|
|
|
|
public void AddText(BillboardText billboard)
|
|
{
|
|
if (billboard == null)
|
|
return;
|
|
if (billboard.UIText == null)
|
|
return;
|
|
|
|
mInvalidated = false;
|
|
mText.Add(billboard);
|
|
var rect = billboard.Rect;
|
|
EnsureCanvas();
|
|
float yScale = (billboard.YMirror == true) ? -1f : 1f;
|
|
if (rect == null)
|
|
{
|
|
var meshObj = billboard.UIText;
|
|
TextDirection dir = meshObj.GetComponent<TextDirection>();
|
|
if (dir != null)
|
|
dir.SetTextController(this);
|
|
|
|
billboard.parent = null;
|
|
meshObj.transform.SetParent(transform, false);
|
|
if (mParent != null)
|
|
meshObj.layer = mParent.gameObject.layer;
|
|
|
|
// meshObj.transform.localRotation = Quaternion.identity;
|
|
Vector3 v = billboard.transform.position;
|
|
if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z))
|
|
meshObj.transform.position = v;
|
|
// meshObj.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
|
|
meshObj.transform.localScale = new Vector3(billboard.Scale * mInnerScale, yScale* billboard.Scale * mInnerScale, 1f);
|
|
}
|
|
else
|
|
{
|
|
TextDirection dir = rect.GetComponent<TextDirection>();
|
|
if (dir != null)
|
|
dir.SetTextController(this);
|
|
|
|
GameObject obj = ChartCommon.CreateCanvasChartItem();
|
|
RectTransform t = obj.GetComponent<RectTransform>();
|
|
obj.AddComponent<Canvas>();
|
|
var addUnder = mAddCanvasUnder;
|
|
if (addUnder == null)
|
|
addUnder = gameObject;
|
|
|
|
obj.transform.SetParent(addUnder.transform, false);
|
|
obj.transform.localPosition = Vector3.zero;
|
|
// obj.transform.localRotation = Quaternion.identity;
|
|
obj.transform.localScale = new Vector3(1f,1f,1f);
|
|
|
|
billboard.parent = t;
|
|
billboard.Rect.SetParent(t, false);
|
|
if (mParent != null)
|
|
{
|
|
obj.layer = mParent.gameObject.layer;
|
|
billboard.Rect.gameObject.layer = mParent.gameObject.layer;
|
|
}
|
|
// billboard.Rect.localRotation = Quaternion.identity;
|
|
billboard.Rect.localPosition = Vector3.zero;
|
|
billboard.Rect.localScale = new Vector3(1f, 1f, 1f);
|
|
|
|
// rect.anchoredPosition3D = new Vector3();
|
|
if (dir == null)
|
|
{
|
|
rect.anchorMin = Vector2.zero;
|
|
rect.anchorMax = Vector2.zero;
|
|
}
|
|
Vector3 v = billboard.transform.position;
|
|
if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z))
|
|
billboard.parent.position = v;
|
|
billboard.UIText.transform.localScale = new Vector3(billboard.Scale * mInnerScale, yScale* billboard.Scale * mInnerScale, 1f);
|
|
billboard.UIText.transform.Rotate(new Vector3(0f, 0f, GlobalRotation));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Vector3 scale = new Vector3(1f/transform.lossyScale.x, 1f/transform.lossyScale.y, 1f/transform.lossyScale.z);//SafeCanvas.transform.localScale;
|
|
//Vector3 scale = SafeCanvas.transform.localScale;
|
|
|
|
//if (mUnderCanvas)
|
|
// billboard.UIText.transform.localScale = scale;
|
|
//else
|
|
|
|
|
|
|
|
// ContentSizeFitter fitter = billboard.UIText.gameObject.GetComponent<ContentSizeFitter>();
|
|
// if(fitter == null)
|
|
// fitter = billboard.UIText.gameObject.AddComponent<ContentSizeFitter>();
|
|
// fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
// fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
|
|
|
|
}
|
|
|
|
Camera EnsureCamera()
|
|
{
|
|
if (Camera == null)
|
|
return AssignCamera(Camera.main);
|
|
else
|
|
return AssignCamera(Camera);
|
|
}
|
|
|
|
Camera AssignCamera(Camera camera)
|
|
{
|
|
Canvas canvas = SafeCanvas;
|
|
if (canvas.worldCamera != camera && OwnsCanvas)
|
|
canvas.worldCamera = camera;
|
|
return camera;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if(Application.isEditor && Application.isPlaying == false)
|
|
{
|
|
ApplyTextPosition();
|
|
}
|
|
}
|
|
|
|
Vector3 ProjectPointOnPlane(Vector3 planeNormal, Vector3 planePoint, Vector3 point)
|
|
{
|
|
planeNormal.Normalize();
|
|
float distance = -Vector3.Dot(planeNormal.normalized, (point - planePoint));
|
|
return point + planeNormal * distance;
|
|
}
|
|
|
|
void CalculatePlane(Camera cam, RectTransform transform, out Vector3 center, out Vector3 normal)
|
|
{
|
|
mRect.GetWorldCorners(mPlaneCorners);
|
|
center = new Vector3();
|
|
for (int i = 0; i < mPlaneCorners.Length; i++)
|
|
{
|
|
center += mPlaneCorners[i];
|
|
}
|
|
center *= 0.25f;
|
|
Vector3 a = mPlaneCorners[1] - mPlaneCorners[0];
|
|
Vector3 b = mPlaneCorners[2] - mPlaneCorners[0];
|
|
normal = Vector3.Cross(a, b).normalized;
|
|
}
|
|
|
|
public void ApplyTextPosition()
|
|
{
|
|
Camera = EnsureCamera();
|
|
if (mCanvas == null)
|
|
return;
|
|
float scale = 1f;
|
|
if (Camera != null)
|
|
{
|
|
if (mParent != null && (mParent.VRSpaceText || mParent.PaperEffectText) && OwnsCanvas)
|
|
{
|
|
Vector3 difVector = new Vector3(transform.position.x, 0, transform.position.z) - new Vector3(Camera.transform.position.x, 0, Camera.transform.position.z);
|
|
if (difVector != Vector3.zero && mParent.PaperEffectText == false)
|
|
{
|
|
mCanvas.transform.rotation = Quaternion.LookRotation(difVector, Vector3.up);
|
|
}
|
|
|
|
// mCanvas.transform.rotation = Camera.transform.rotation;
|
|
mCanvas.transform.localScale = new Vector3(mParent.VRSpaceScale, mParent.VRSpaceScale, mParent.VRSpaceScale);
|
|
}
|
|
|
|
|
|
if (mPrivateParent != null && mPrivateParent.KeepOrthoSize)
|
|
{
|
|
|
|
if (Camera != null && Camera.orthographic && Camera.orthographicSize > 0.1f)
|
|
{
|
|
scale = 5f / Camera.orthographicSize;
|
|
}
|
|
}
|
|
scale *= mInnerScale;
|
|
if (Mathf.Abs(mPrevScale - scale) > 0.001f)
|
|
{
|
|
mInvalidated = false;
|
|
}
|
|
mPrevScale = scale;
|
|
}
|
|
else
|
|
{
|
|
if (mParent == null || mParent.IsCanvas == false)
|
|
return;
|
|
}
|
|
//if (mInvalidated == false)
|
|
// {
|
|
mText.RemoveAll(x =>
|
|
{
|
|
if (x == null)
|
|
return true;
|
|
BillboardText billboard = x;
|
|
if (mInvalidated == false || billboard.transform.hasChanged || mCanvas.transform.hasChanged)
|
|
{
|
|
var rect = billboard.Rect;
|
|
if (rect != null)
|
|
rect.transform.position = billboard.transform.position;
|
|
else
|
|
billboard.UIText.transform.position = billboard.transform.position;
|
|
float yScale = (billboard.YMirror == true) ? -1f : 1f;
|
|
billboard.UIText.transform.localScale = new Vector3(billboard.Scale * scale, yScale* billboard.Scale * scale, 1f);
|
|
billboard.transform.hasChanged = false;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
mInvalidated = true;
|
|
|
|
// }
|
|
return;
|
|
//}
|
|
/* Canvas canvas = SafeCanvas;
|
|
if (mParent != null)
|
|
{
|
|
Camera = mParent.TextCamera;
|
|
PlaneDistance = mParent.TextIdleDistance;
|
|
canvas.planeDistance = PlaneDistance;
|
|
}
|
|
|
|
Camera cam = EnsureCamera();
|
|
if (cam == null)
|
|
{
|
|
if (mWarn == false)
|
|
Debug.LogWarning("Chart Warning: No main camera set , please set the Chart's camera using \"TextCamera\" in the inspector");
|
|
mWarn = true;
|
|
return;
|
|
}
|
|
mWarn = false;
|
|
Vector3 planeCenter;
|
|
Vector3 planeNormal;
|
|
CalculatePlane(cam, mRect, out planeCenter, out planeNormal);
|
|
//Debug.DrawLine(planeCenter, planeCenter+ planeNormal,Color.red);
|
|
foreach (BillboardText text in mText)
|
|
{
|
|
// RectTransformUtility.
|
|
Vector3 point = text.transform.position;
|
|
Vector3 pointOnPlane = ProjectPointOnPlane(planeNormal, planeCenter, text.transform.position);
|
|
//Debug.DrawLine(point, pointOnPlane);
|
|
Vector3 worldVec = (pointOnPlane - point);
|
|
Vector3 vec = mRect.worldToLocalMatrix * worldVec;
|
|
float dist = vec.magnitude;
|
|
if (Vector3.Dot(worldVec, cam.transform.forward) > 0)
|
|
dist = -dist;
|
|
|
|
Vector2 viewport = cam.WorldToViewportPoint(pointOnPlane);
|
|
// Debug.DrawLine(viewport, pointOnPlane);
|
|
// Vector3 anchored = new Vector3(
|
|
// (mRect.sizeDelta.x * viewport.x) - (mRect.sizeDelta.x * mRect.anchorMin.x),
|
|
// (mRect.sizeDelta.y * viewport.y) - (mRect.sizeDelta.y * mRect.anchorMin.y),
|
|
// dist);
|
|
Vector2 screen = RectTransformUtility.WorldToScreenPoint(cam,pointOnPlane);
|
|
Vector2 pos;
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(mRect, screen, cam, out pos);
|
|
// float scaleDist = mPlaneDistance + worldVec.magnitude;
|
|
// if (scaleDist <= 0)
|
|
// scaleDist = 0.1f;
|
|
// float scale = scaleDist/ mPlaneDistance;
|
|
//text.Rect.localScale = new Vector3(scale, scale, 1f);
|
|
text.Rect.localPosition = new Vector3(pos.x, pos.y , dist);
|
|
}*/
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
//ApplyTextPosition();
|
|
}
|
|
} |