515 lines
20 KiB
C#
515 lines
20 KiB
C#
#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<CandleChartData.CandleValue> mCandles = new List<CandleChartData.CandleValue>();
|
|
|
|
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<CandleChartData.CandleValue> 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<UIVertex> 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<UIVertex> 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<UIVertex> 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<UIVertex> 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
|
|
}
|
|
}
|