#define Graph_And_Chart_PRO using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using UnityEngine; using UnityEngine.UI; namespace ChartAndGraph { /// /// holds common operations of the charting library /// public partial class ChartCommon { class IntComparer : IEqualityComparer { public bool Equals(int x, int y) { return x == y; } public int GetHashCode(int obj) { return obj.GetHashCode(); } } class DoubleComparer : IEqualityComparer { public bool Equals(double x, double y) { return x == y; } public int GetHashCode(double obj) { return obj.GetHashCode(); } } class DoubleVector3Comparer : IEqualityComparer { public bool Equals(DoubleVector3 x, DoubleVector3 y) { return x == y; } public int GetHashCode(DoubleVector3 obj) { return obj.GetHashCode(); } } private static Material mDefaultMaterial; static ChartCommon() { DefaultIntComparer = new IntComparer(); DefaultDoubleComparer = new DoubleComparer(); DefaultDoubleVector3Comparer = new DoubleVector3Comparer(); } internal static float SmoothLerp(float from, float to, float factor) { return (from * (1f - factor)) + (to * factor); } internal static GameObject CreateCanvasChartItem() { GameObject obj = new GameObject("item", typeof(RectTransform)); ChartCommon.HideObject(obj, true); obj.AddComponent(); return obj; } internal static double Max(double? x, double y) { if (x.HasValue == false) return y; return Math.Max(x.Value, y); } internal static double Min(double? x, double y) { if (x.HasValue == false) return y; return Math.Min(x.Value, y); } internal static double Clamp(double val) { if (val > 1.0) return 1.0; if (val < 0.0) return 0.0; return val; } internal static GameObject CreateChartItem() { GameObject obj = new GameObject(); ChartCommon.HideObject(obj, true); obj.AddComponent(); return obj; } internal static double normalizeInRangeX(double value, DoubleVector3 min, DoubleVector3 size) { return normalizeInRange(value, min.x, size.x); } internal static double normalizeInRangeY(double value, DoubleVector3 min, DoubleVector3 size) { return normalizeInRange(value, min.y, size.y); } internal static double normalizeInRange(double value, double min, double size) { return (value - min) / size; } internal static double interpolateInRectX(Rect rect, double x) { return rect.x + rect.width * x; } internal static double interpolateInRectY(Rect rect, double y) { return rect.y + rect.height * y; } internal static Rect RectFromCenter(float centerX, float sizeX, float top, float bottom) { float half = sizeX * 0.5f; return new Rect(centerX - half, top, sizeX, bottom - top); } internal static DoubleVector4 interpolateInRect(Rect rect, DoubleVector3 point) { double x = rect.x + rect.width * point.x; double y = rect.y + rect.height * point.y; return new DoubleVector4(x, y, point.z, 0.0); } internal static void HideObjectEditor(GameObject obj, bool hideMode) { obj.hideFlags = HideFlags.DontSaveInEditor | HideFlags.HideInHierarchy | HideFlags.HideInInspector; } internal static void HideObject(GameObject obj, bool hideMode) { // return; if (IsInEditMode == true) { obj.tag = "EditorOnly"; obj.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.NotEditable | HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; return; } if (hideMode == false) { obj.hideFlags = HideFlags.DontSaveInEditor; return; } obj.hideFlags = HideFlags.DontSaveInEditor | HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.NotEditable; } internal static float GetAutoLength(AnyChart parent, ChartOrientation orientation) { return (orientation == ChartOrientation.Vertical) ? ((IInternalUse)parent).InternalTotalWidth : ((IInternalUse)parent).InternalTotalHeight; } internal static float GetAutoDepth(AnyChart parent, ChartOrientation orientation, ChartDivisionInfo info) { float depth = ((IInternalUse)parent).InternalTotalDepth; if (info.MarkDepth.Automatic == false) depth = info.MarkDepth.Value; return depth; } internal static float GetAutoLength(AnyChart parent, ChartOrientation orientation, ChartDivisionInfo info) { float length = (orientation == ChartOrientation.Vertical) ? ((IInternalUse)parent).InternalTotalWidth : ((IInternalUse)parent).InternalTotalHeight; if (info.MarkLength.Automatic == false) length = info.MarkLength.Value; return length; } public static Vector2 Perpendicular(Vector2 v) { return new Vector2(v.y, -v.x); } internal static bool SegmentIntersection(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, out Vector2 intersection) { intersection = new Vector2(); Vector2 dirA = a2 - a1; Vector2 dirB = b2 - b1; float dotA = Vector2.Dot(dirA, Perpendicular(dirB)); if (dotA == 0) return false; Vector2 dirAB = b1 - a1; float t = Vector2.Dot(dirAB, Perpendicular(dirB)) / dotA; if (t < 0 || t > 1) return false; float s = Vector2.Dot(dirAB, Perpendicular(dirA)) / dotA; if (s < 0 || s > 1) return false; intersection = a1 + t * dirA; return true; } internal static Vector2 FromPolarRadians(float angleDeg, float radius) { float x = radius * Mathf.Cos(angleDeg); float y = radius * Mathf.Sin(angleDeg); return new Vector2(x, y); } internal static Vector2 FromPolar(float angleDeg, float radius) { angleDeg *= Mathf.Deg2Rad; float x = radius * Mathf.Cos(angleDeg); float y = radius * Mathf.Sin(angleDeg); return new Vector2(x, y); } internal static Rect FixRect(Rect r) { float x = r.x; float y = r.y; float width = r.width; float height = r.height; if (width < 0) { x = r.x + width; width = -width; } if (height < 0) { y = r.y + height; height = -height; } return new Rect(x, y, width, height); } internal static Material DefaultMaterial { get { if (mDefaultMaterial == null) { mDefaultMaterial = new Material(Shader.Find("Standard")); mDefaultMaterial.color = Color.blue; } return mDefaultMaterial; } } /// /// safely assigns a material to a renderer. if the material is null than the default material is set instead /// /// the renderer /// the material /// true if material is not null, false otherwise internal static bool SafeAssignMaterial(Renderer renderer, Material material, Material defualt) { Material toSet = material; if (toSet == null) { toSet = defualt; if (toSet == null) toSet = DefaultMaterial; } renderer.sharedMaterial = toSet; return material != null; } /// /// /// /// /// internal static void CleanMesh(Mesh newMesh, ref Mesh cleanMesh) { if (cleanMesh == newMesh) return; if (cleanMesh != null) ChartCommon.SafeDestroy(cleanMesh); cleanMesh = newMesh; } internal static bool IsInEditMode { get { return Application.isPlaying == false && Application.isEditor; } } //#if UNITY_2018_3_OR_NEWER //#if UNITY_EDITOR // public static void SafeDestroy(GameObject obj) // { // if (obj == null) // return; // if (Application.isEditor && Application.isPlaying == false) // { // if (UnityEditor.PrefabUtility.GetPrefabAssetType(obj) != UnityEditor.PrefabAssetType.NotAPrefab) // { // if (UnityEditor.PrefabUtility.IsPartOfPrefabInstance(obj)) // { // var parent = UnityEditor.PrefabUtility.GetNearestPrefabInstanceRoot(obj); // UnityEditor.PrefabUtility.UnpackPrefabInstance(parent, UnityEditor.PrefabUnpackMode.Completely, UnityEditor.InteractionMode.AutomatedAction); // } // } // UnityEngine.Object.DestroyImmediate(obj); // } // else // UnityEngine.Object.Destroy(obj); // } //#endif //#endif public static void SafeDestroy(UnityEngine.Object obj) { if (obj == null) return; if (Application.isEditor && Application.isPlaying == false) UnityEngine.Object.DestroyImmediate(obj); else UnityEngine.Object.Destroy(obj); } internal static UIVertex CreateVertex(Vector3 pos, Vector2 uv) { return CreateVertex(pos, uv, pos.z); } internal static UIVertex CreateVertex(Vector3 pos, Vector2 uv, float z) { UIVertex vert = new UIVertex(); vert.color = Color.white; vert.uv0 = uv; pos.z = z; vert.position = pos; return vert; } internal static float GetTiling(MaterialTiling tiling) { if (tiling.EnableTiling == false) return -1f; return tiling.TileFactor; } internal static void FixBillboardText(ItemLabelsBase labels, BillboardText text) { float sharpness = Mathf.Clamp(labels.FontSharpness, 1f, 3f); ChartCommon.SetTextParams(text.UIText, null, labels.FontSize, sharpness); text.Scale = 1f / sharpness; text.UIText.transform.localScale = new Vector3(text.Scale, text.Scale); } internal static T EnsureComponent(GameObject obj) where T : Component { T comp = obj.GetComponent(); if (comp == null) comp = obj.AddComponent(); return comp; } static private float DotProduct(Vector2 a, Vector2 b, Vector2 c) { Vector2 ab = b - a; Vector2 bc = c - b; return Vector2.Dot(ab, bc); } static private float CrossProduct(Vector2 a, Vector2 b, Vector2 c) { Vector2 ab = b - a; Vector2 ac = c - a; return ab.x * ac.y - ab.y * ac.x; } static internal float SegmentPointSqrDistance(Vector2 a, Vector2 b, Vector2 point) { float dot = DotProduct(a, b, point); if (dot > 0) return (b - point).sqrMagnitude; dot = DotProduct(b, a, point); if (dot > 0) return (a - point).sqrMagnitude; float cross = CrossProduct(a, b, point); return (cross * cross) / (a - b).sqrMagnitude; } /* internal static BillboardText CreateBillboardText(Text prefab, Transform parentTransform, string text, float x, float y, float z, float angle, bool hideHirarechy, int fontSize, float sharpness) { return CreateBillboardText(prefab, parentTransform, text, x, y, z, angle, null, hideHirarechy, fontSize, sharpness); }*/ internal static Vector3 LineCrossing(Vector3 v1,Vector3 v2,float horizontal) { if (Math.Abs(v1.x - v2.x) < 0.0001f) return new Vector3(v1.x, horizontal, v1.z); if (Math.Abs(v1.y - v2.y) < 0.0001f) return v1; float slope = (v1.y - v2.y) / (v1.x - v2.x); float n = v1.y - (v1.x * slope); float x = (horizontal - n) / slope; float y = slope * x + n; return new Vector3(x, y, v1.z); } internal static BillboardText UpdateBillboardText(BillboardText billboardText, Transform parentTransform, string text, float x, float y, float z, float angle, Transform relativeFrom, bool hideHirarechy, bool yMirror) { GameObject UIText = billboardText.UIText.gameObject; GameObject billboard = billboardText.gameObject; ChartCommon.HideObject(billboard, hideHirarechy); TextDirection direction = UIText.GetComponent(); GameObject TextObj = billboardText.UIText; billboardText.YMirror = yMirror; if (direction != null) { TextObj = direction.Text.gameObject; if (relativeFrom != null) direction.SetRelativeTo(relativeFrom, billboard.transform); // else direction.SetDirection(angle); } // if (parentTransform != null && billboard.transform.parent != parentTransform) // { // billboard.transform.SetParent(parentTransform, false); // } UpdateTextParams(TextObj, text); billboard.transform.localPosition = new Vector3(x, y, z); return billboardText; } internal static BillboardText CreateBillboardText(BillboardText item, MonoBehaviour prefab, Transform parentTransform, string text, float x, float y, float z, float angle, Transform relativeFrom, bool hideHirarechy, int fontSize, float sharpness) { if (item != null) return UpdateBillboardText(item, parentTransform, text, x, y, z, angle, relativeFrom, hideHirarechy, prefab != null && prefab.transform.localScale.y < 0); if (prefab == null || prefab.gameObject == null) { GameObject g = Resources.Load("Chart And Graph/DefaultText") as GameObject; prefab = g.GetComponent(); } GameObject UIText = (GameObject)GameObject.Instantiate(prefab.gameObject); GameObject billboard = new GameObject(); ChartCommon.HideObject(UIText, hideHirarechy); ChartCommon.HideObject(billboard, hideHirarechy); if (parentTransform.GetComponent()) billboard.AddComponent(); if (parentTransform != null) { billboard.transform.SetParent(parentTransform, false); UIText.transform.SetParent(parentTransform, false); } BillboardText billboardText = billboard.AddComponent(); billboard.AddComponent(); TextDirection direction = UIText.GetComponent(); GameObject obj = null; if (direction != null) { ChartCommon.HideObject(direction.Text.gameObject, hideHirarechy); ChartCommon.HideObject(direction.Lines.gameObject, hideHirarechy); ChartCommon.HideObject(direction.Point.gameObject, hideHirarechy); obj = direction.Text.gameObject; if (relativeFrom != null) direction.SetRelativeTo(relativeFrom, billboard.transform); // else direction.SetDirection(angle); } if (obj == null) obj = UIText; sharpness = Mathf.Clamp(sharpness, 1f, 3f); bool setParams = SetTextParams(obj, text, fontSize, sharpness); if (billboardText == null || setParams == false) { SafeDestroy(UIText); SafeDestroy(billboard); return null; } if (prefab != null && prefab.transform.localScale.y < 0) billboardText.YMirror = true; billboardText.Scale = (1f / sharpness); billboardText.UIText = obj; billboardText.Direction = direction; if (direction != null) billboardText.RectTransformOverride = direction.GetComponent(); else billboardText.RectTransformOverride = null; billboard.transform.localPosition = new Vector3(x, y, z); return billboardText; } static partial void DoTextSignInternal(MonoBehaviour Text, double sign); static partial void DoTextSignInternal3D(MonoBehaviour Text, double sign); internal static void DoTextSign(MonoBehaviour Text, double sign) { DoTextSignInternal(Text, sign); DoTextSignInternal3D(Text, sign); } static partial void GetTextInternal(GameObject obj, ref string text); static partial void GetTextInternal3D(GameObject obj, ref string text); internal static string GetText(GameObject obj) { var t = obj.GetComponent(); if (t != null) return t.text; string res = null; GetTextInternal(obj, ref res); if (res == null) GetTextInternal3D(obj, ref res); return res; } static partial void UpdateTextParamsInternal(GameObject obj, string text); static partial void UpdateTextParamsInternal3D(GameObject obj, string text); internal static void UpdateTextParams(GameObject obj, string text) { var t = obj.GetComponent(); if (t != null) t.text = text; UpdateTextParamsInternal(obj, text); UpdateTextParamsInternal3D(obj, text); } internal static void MakeMaskable(GameObject obj, bool masksable) { foreach (MaskableGraphic g in obj.GetComponents()) g.maskable = masksable; } static partial void SetTextParamsInternal(GameObject obj, string text, int fontSize, float sharpness, ref bool res); static partial void SetTextParamsInternal3D(GameObject obj, string text, int fontSize, float sharpness, ref bool res); internal static bool SetTextParams(GameObject obj, string text, int fontSize, float sharpness) { var t = obj.GetComponent(); if (t != null) { t.fontSize = (int)(fontSize * sharpness); t.horizontalOverflow = HorizontalWrapMode.Overflow; t.verticalOverflow = VerticalWrapMode.Overflow; t.resizeTextForBestFit = false; if (text != null) t.text = text; return true; } bool res = false; SetTextParamsInternal(obj, text, fontSize, sharpness, ref res); if (res == false) SetTextParamsInternal3D(obj, text, fontSize, sharpness, ref res); if (res == false) Debug.LogError("Text prefab must be either UI.Text or TextMeshPro object. For text mesh pro , you need to import the support package first. worldSpace text meshpro can only be used with non canvas charts. Check out the following link for more info http://prosourcelabs.com/Tutorials/TextMeshPro/IntegratingTextMeshPro.html"); return res; } /// /// /// public static IEqualityComparer DefaultIntComparer { get; private set; } public static IEqualityComparer DefaultDoubleComparer { get; private set; } public static IEqualityComparer DefaultDoubleVector3Comparer { get; private set; } } }