#define Graph_And_Chart_PRO using ChartAndGraph; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; /// /// posistions world space text on a special canvas used for billboarding. /// [RequireComponent(typeof(ChartItem))] [ExecuteInEditMode] public class TextController : MonoBehaviour { public Camera Camera = null; Canvas mCanvas; RectTransform mRect; List mText = new List(); 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 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(); if (mCanvas == null) { OwnsCanvas = true; mAddCanvasUnder = new GameObject(); ChartCommon.HideObject(mAddCanvasUnder, true); mAddCanvasUnder.AddComponent(); mAddCanvasUnder.AddComponent(); 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(); mAddCanvasUnder.AddComponent(); mAddCanvasUnder.AddComponent(); if (mParent != null && (mParent.VRSpaceText || mParent.PaperEffectText)) { mCanvas.renderMode = RenderMode.WorldSpace; } else { mCanvas.renderMode = RenderMode.ScreenSpaceCamera; } mCanvas.planeDistance = PlaneDistance; Camera = EnsureCamera(); mRect = mCanvas.GetComponent(); // mCanvas.pixelPerfect = true; CanvasScaler scaler = mCanvas.GetComponent(); 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(); 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(); if (dir != null) dir.SetTextController(this); GameObject obj = ChartCommon.CreateCanvasChartItem(); RectTransform t = obj.GetComponent(); obj.AddComponent(); 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(); // if(fitter == null) // fitter = billboard.UIText.gameObject.AddComponent(); // 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(); } }