#define Graph_And_Chart_PRO using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; using UnityEngine.UI; namespace ChartAndGraph { class CanvasCandleGraphic : EventHandlingGraphic { CandleChartData.CandleSettings mCandleSettings; List mCandles = new List(); int mPart; UIVertex[] mTmpVerts = new UIVertex[4]; Vector2 mMin, mMax; protected override Vector2 Min { get { return mMin; } } protected override Vector2 Max { get { return mMax; } } protected Rect RectFromIndex(int index, int type, Rect Default) { if (index >= mCandles.Count) return Default; CandleChartData.CandleValue candle = mCandles[index]; float max = (float)candle.Max; float min = (float)candle.Min; float start = (float)candle.Start; float end = (float)(candle.Start + candle.Duration); float mid = (start + end) * 0.5f; if (type == 0) return ChartCommon.RectFromCenter(mid, (float)mCandleSettings.LineThickness, max, (float)candle.High); if (type == 2) return ChartCommon.RectFromCenter(mid, (float)mCandleSettings.LineThickness, (float)candle.Low, min); return ChartCommon.RectFromCenter(mid, (float)(mCandleSettings.CandleThicknessMultiplier * candle.Duration), min, max); } protected override void SetUpHoverObject(ChartItemEffect hover, int index, int type, object selectionData) { Rect selectionRect = (Rect)selectionData; selectionRect = RectFromIndex(index, type, selectionRect); hover.ItemData = selectionRect; SetupHoverObjectToRect(hover, index, type, selectionRect); } protected void PickLine(Vector3 mouse, out int pickedIndex, out int pickedType, out object selectionData) { pickedIndex = -1; pickedType = -1; selectionData = null; for (int i = 0; i < mCandles.Count; i++) { CandleChartData.CandleValue candle = mCandles[i]; float max = (float)candle.Max; float min = (float)candle.Min; float start = (float)candle.Start; float end = (float)(candle.Start + candle.Duration); float mid = (start + end) * 0.5f; Rect high = ChartCommon.RectFromCenter(mid, (float)mCandleSettings.LineThickness, max, (float)candle.High); Rect low = ChartCommon.RectFromCenter(mid, (float)mCandleSettings.LineThickness, (float)candle.Low, min); if (high.Contains(mouse)) { selectionData = high; pickedType = 0; pickedIndex = i; return; } if (low.Contains(mouse)) { selectionData = low; pickedType = 2; pickedIndex = i; return; } } } protected void PickBody(Vector3 mouse, out int pickedIndex, out int pickedType, out object selectionData) { pickedIndex = -1; pickedType = -1; selectionData = null; for (int i = 0; i < mCandles.Count; i++) { CandleChartData.CandleValue candle = mCandles[i]; float max = (float)candle.Max; float min = (float)candle.Min; float start = (float)candle.Start; float end = (float)(candle.Start + candle.Duration); float mid = (start + end) * 0.5f; Rect Body = ChartCommon.RectFromCenter(mid, (float)(mCandleSettings.CandleThicknessMultiplier * candle.Duration), min, max); if (Body.Contains(mouse)) { selectionData = Body; pickedType = 1; pickedIndex = i; return; } } } protected override void Pick(Vector3 mouse, out int pickedIndex, out int pickedType, out object selectionData) { if (mPart == 0) PickBody(mouse, out pickedIndex, out pickedType, out selectionData); else PickLine(mouse, out pickedIndex, out pickedType, out selectionData); if (pickedIndex >= 0) pickedIndex += refrenceIndex; } protected override float MouseInThreshold { get { return Sensitivity; } } public void ClearCandles() { mCandles = null; SetAllDirty(); Rebuild(CanvasUpdate.PreRender); } public void SetCandle(int part, IList candles, CandleChartData.CandleSettings settings) { mPart = part; mCandles.Clear(); mCandles.AddRange(candles); mCandleSettings = settings; double minX = double.PositiveInfinity; double minY = double.PositiveInfinity; double maxX = double.NegativeInfinity; double maxY = double.NegativeInfinity; for (int i = 0; i < mCandles.Count; i++) { var candle = mCandles[i]; minY = Math.Min(candle.LowBound, minY); maxY = Math.Max(candle.HighBound, maxY); minX = Math.Min(minX, candle.Start); maxX = Math.Max(maxX, candle.Start + candle.Duration); } mMin = new Vector2((float)minX, (float)minY); mMax = new Vector2((float)maxX, (float)maxY); SetAllDirty(); Rebuild(CanvasUpdate.PreRender); SetUpAllHoverObjects(); } IEnumerable getOutline() { UIVertex v = new UIVertex(); if (mCandles == null) yield break; float outlineThickness = (float)mCandleSettings.OutlineThickness * 0.5f; for (int i = 0; i < mCandles.Count; i++) { CandleChartData.CandleValue candle = mCandles[i]; float max = (float)Math.Max(candle.Open, candle.Close); float min = (float)Math.Min(candle.Open, candle.Close); float start = (float)candle.Start; float end = (float)(candle.Start + candle.Duration); float mid = (start + end) * 0.5f; float thickness = (float)(mCandleSettings.CandleThicknessMultiplier * candle.Duration * 0.5); if (min == max) { min -= 2f; max += 2f; } //long and dirty part the defines all the verices of the candle outline //outline of the body v.position = new Vector3(mid - thickness - outlineThickness, max, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid - thickness + outlineThickness, max, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - thickness - outlineThickness, min, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid - thickness + outlineThickness, min, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the body v.position = new Vector3(mid + thickness - outlineThickness, max, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + thickness + outlineThickness, max, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid + thickness - outlineThickness, min, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + thickness + outlineThickness, min, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the high line v.position = new Vector3(mid - (float)mCandleSettings.LineThickness - outlineThickness, (float)candle.High, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness + outlineThickness, (float)candle.High, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness - outlineThickness, max, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness + outlineThickness, max, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the high line v.position = new Vector3(mid + (float)mCandleSettings.LineThickness - outlineThickness, (float)candle.High, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness + outlineThickness, (float)candle.High, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness - outlineThickness, max, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness + outlineThickness, max, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the low line v.position = new Vector3(mid - (float)mCandleSettings.LineThickness - outlineThickness, min, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness + outlineThickness, min, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness - outlineThickness, (float)candle.Low, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness + outlineThickness, (float)candle.Low, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the low line v.position = new Vector3(mid + (float)mCandleSettings.LineThickness - outlineThickness, min, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness + outlineThickness, min, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness - outlineThickness, (float)candle.Low, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness + outlineThickness, (float)candle.Low, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the low line connection with body v.position = new Vector3(mid - thickness - outlineThickness, min + outlineThickness, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, min + outlineThickness, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - thickness - outlineThickness, min - outlineThickness, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, min - outlineThickness, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the low line connection with body v.position = new Vector3(mid + thickness + outlineThickness, min + outlineThickness, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, min + outlineThickness, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid + thickness + outlineThickness, min - outlineThickness, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, min - outlineThickness, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the high line connection with body v.position = new Vector3(mid - thickness - outlineThickness, max - outlineThickness, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, max - outlineThickness, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - thickness - outlineThickness, max + outlineThickness, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, max + outlineThickness, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; //outline of the high line connection with body v.position = new Vector3(mid + thickness + outlineThickness, max - outlineThickness, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, max - outlineThickness, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid + thickness + outlineThickness, max + outlineThickness, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, max + outlineThickness, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; } } IEnumerable getCandle() { UIVertex v = new UIVertex(); if (mCandles == null) yield break; for (int i = 0; i < mCandles.Count; i++) { CandleChartData.CandleValue candle = mCandles[i]; float max = (float)Math.Max(candle.Open, candle.Close); float min = (float)Math.Min(candle.Open, candle.Close); float start = (float)candle.Start; float end = (float)(candle.Start + candle.Duration); float mid = (start + end) * 0.5f; float thickness = (float)(mCandleSettings.CandleThicknessMultiplier * candle.Duration * 0.5); if (min == max) { min -= 2f; max += 2f; } v.position = new Vector3(mid - thickness, max, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + thickness, max, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - thickness, min, 0f); v.uv0 = new Vector2(-0f, 1f); yield return v; v.position = new Vector3(mid + thickness, min, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; } } IEnumerable getLine() { UIVertex v = new UIVertex(); if (mCandles == null) yield break; for (int i = 0; i < mCandles.Count; i++) { CandleChartData.CandleValue candle = mCandles[i]; float max = (float)Math.Max(candle.Open, candle.Close); float min = (float)Math.Min(candle.Open, candle.Close); float start = (float)candle.Start; float end = (float)(candle.Start + candle.Duration); float mid = (start + end) * 0.5f; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, (float)candle.High, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, (float)candle.High, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, max, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, max, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, min, 0f); v.uv0 = new Vector2(0f, 0f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, min, 0f); v.uv0 = new Vector2(1f, 0f); yield return v; v.position = new Vector3(mid - (float)mCandleSettings.LineThickness, (float)candle.Low, 0f); v.uv0 = new Vector2(0f, 1f); yield return v; v.position = new Vector3(mid + (float)mCandleSettings.LineThickness, (float)candle.Low, 0f); v.uv0 = new Vector2(1f, 1f); yield return v; } } IEnumerable getVerices() { if (mCandles == null) return new UIVertex[0]; if (mPart == 0) return getCandle(); else if (mPart == 1) return getLine(); return getOutline(); } #if (!UNITY_5_2_0) && (!UNITY_5_2_1) protected override void OnPopulateMesh(VertexHelper vh) { base.OnPopulateMesh(vh); vh.Clear(); int vPos = 0; foreach (UIVertex v in getVerices()) { mTmpVerts[vPos++] = v; if (vPos == 4) { UIVertex tmp = mTmpVerts[2]; mTmpVerts[2] = mTmpVerts[3]; mTmpVerts[3] = tmp; vPos = 0; vh.AddUIVertexQuad(mTmpVerts); } } } #endif #pragma warning disable 0672 #if !UNITY_2017_1_OR_NEWER protected override void OnPopulateMesh(Mesh m) { WorldSpaceChartMesh mesh = new WorldSpaceChartMesh(1); int vPos = 0; foreach (UIVertex v in getVerices()) { mTmpVerts[vPos++] = v; if (vPos == 4) { vPos = 0; mesh.AddQuad(mTmpVerts[0], mTmpVerts[1], mTmpVerts[2], mTmpVerts[3]); } } mesh.ApplyToMesh(m); } #endif #pragma warning restore 0672 } }