| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 | using System.Collections.Generic;using UnityEngine;using UnityEngine.EventSystems;using UnityEngine.UI;using XUGL;namespace XCharts.Runtime{    [UnityEngine.Scripting.Preserve]    internal sealed class PieHandler : SerieHandler<Pie>    {        public override void Update()        {            base.Update();        }        public override void DrawBase(VertexHelper vh)        {            UpdateRuntimeData(serie);            DrawPieLabelLine(vh, serie, false);        }        public override void DrawSerie(VertexHelper vh)        {            UpdateRuntimeData(serie);            DrawPie(vh, serie);            chart.RefreshBasePainter();        }        public override void DrawUpper(VertexHelper vh)        {            DrawPieLabelLine(vh, serie, true);        }        public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,            string marker, string itemFormatter, string numericFormatter, string ignoreDataDefaultContent,            ref List<SerieParams> paramList, ref string title)        {            UpdateItemSerieParams(ref paramList, ref title, dataIndex, category,                marker, itemFormatter, numericFormatter, ignoreDataDefaultContent);        }        public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)        {            var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);            if (labelLine != null && labelLine.show && serieData.labelObject != null)            {                var currAngle = serieData.context.halfAngle - serie.context.startAngle;                var isLeft = currAngle > 180 || (currAngle == 0 && serieData.context.startAngle > 0);                var textOffset = serieData.labelObject.text.GetPreferredWidth() / 2;                return serieData.context.labelPosition + (isLeft ? Vector3.left : Vector3.right) * textOffset;            }            else            {                return serieData.context.labelPosition;            }        }        public override Vector3 GetSerieDataLabelOffset(SerieData serieData, LabelStyle label)        {            var offset = label.GetOffset(serie.context.insideRadius);            if (label.autoOffset)            {                var currAngle = serieData.context.halfAngle - serie.context.startAngle;                var isLeft = currAngle > 180 || (currAngle == 0 && serieData.context.startAngle > 0);                if (isLeft)                    return new Vector3(-offset.x, offset.y, offset.z);                else                    return offset;            }            else            {                return offset;            }        }        public override Vector3 GetSerieDataTitlePosition(SerieData serieData, TitleStyle titleStyle)        {            return serie.context.center;        }        public override void OnPointerDown(PointerEventData eventData)        {            if (chart.pointerPos == Vector2.zero) return;            var dataIndex = GetPiePosIndex(serie, chart.pointerPos);            var refresh = false;            if (dataIndex >= 0)            {                refresh = true;                for (int j = 0; j < serie.data.Count; j++)                {                    if (j == dataIndex) serie.data[j].context.selected = !serie.data[j].context.selected;                    else serie.data[j].context.selected = false;                }            }            if (refresh) chart.RefreshChart();            base.OnPointerDown(eventData);        }        public override int GetPointerItemDataIndex()        {            return GetPiePosIndex(serie, chart.pointerPos);        }        public override void UpdateSerieContext()        {            var needCheck = m_LegendEnter || m_LegendExiting || m_ForceUpdateSerieContext || (chart.isPointerInChart && PointerIsInPieSerie(serie, chart.pointerPos));            var needInteract = false;            var interactEnable = serie.animation.enable && serie.animation.interaction.enable;            Color32 color, toColor;            if (!needCheck)            {                if (m_LastCheckContextFlag != needCheck || m_ForceUpdateSerieContext)                {                    serie.context.pointerItemDataIndex = -1;                    serie.context.pointerEnter = false;                    bool isAllZeroValue1 = SerieHelper.IsAllZeroValue(serie, 1);                    var zeroReplaceValue1 = isAllZeroValue1 ? 360 / serie.dataCount : 0;                    foreach (var serieData in serie.data)                    {                        serieData.context.highlight = false;                        if (interactEnable)                        {                            var value = isAllZeroValue1 ? zeroReplaceValue1 : serieData.GetCurrData(1, serie.animation);                            var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);                            SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, colorIndex, SerieState.Normal);                            UpdateSerieDataRadius(serieData, value);                            serieData.interact.SetValueAndColor(ref needInteract, serieData.context.outsideRadius, color, toColor);                            serieData.interact.SetPosition(ref needInteract, serieData.context.offsetCenter);                        }                    }                    if (needInteract)                    {                        chart.RefreshPainter(serie);                    }                    else                    {                        m_LastCheckContextFlag = needCheck;                        m_LegendExiting = false;                        chart.RefreshPainter(serie);                    }                }                return;            }            m_LastCheckContextFlag = needCheck;            var lastPointerItemDataIndex = serie.context.pointerItemDataIndex;            var dataIndex = GetPiePosIndex(serie, chart.pointerPos);            serie.context.pointerItemDataIndex = -1;            serie.context.pointerEnter = dataIndex >= 0;            bool isAllZeroValue = SerieHelper.IsAllZeroValue(serie, 1);            var zeroReplaceValue = isAllZeroValue ? 360 / serie.dataCount : 0;            for (int i = 0; i < serie.dataCount; i++)            {                var serieData = serie.data[i];                var value = isAllZeroValue ? zeroReplaceValue : serieData.GetCurrData(1, serie.animation);                var state = SerieState.Normal;                if (dataIndex == i || (m_LegendEnter && m_LegendEnterIndex == i))                {                    serie.context.pointerItemDataIndex = i;                    serieData.context.highlight = true;                    state = SerieState.Emphasis;                }                else                {                    serieData.context.highlight = false;                }                if (interactEnable)                {                    UpdateSerieDataRadius(serieData, value);                    var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);                    SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, colorIndex, state);                    serieData.interact.SetValueAndColor(ref needInteract, serieData.context.outsideRadius, color, toColor);                    serieData.interact.SetPosition(ref needInteract, serieData.context.offsetCenter);                }            }            if (lastPointerItemDataIndex != serie.context.pointerItemDataIndex)            {                needInteract = true;            }            if (needInteract)            {                chart.RefreshPainter(serie);            }        }        private void UpdateRuntimeData(Serie serie)        {            var data = serie.data;            serie.context.dataMax = serie.yMax;            serie.context.startAngle = GetStartAngle(serie);            var runtimePieDataTotal = serie.yTotal;            SerieHelper.UpdateCenter(serie, chart);            float startDegree = serie.context.startAngle;            float totalDegree = 0;            float zeroReplaceValue = 0;            int showdataCount = 0;            foreach (var sd in serie.data)            {                if (sd.show && serie.pieRoseType == RoseType.Area) showdataCount++;                sd.context.canShowLabel = false;            }            bool isAllZeroValue = SerieHelper.IsAllZeroValue(serie, 1);            var dataTotalFilterMinAngle = runtimePieDataTotal;            if (isAllZeroValue)            {                totalDegree = 360;                zeroReplaceValue = totalDegree / data.Count;                serie.context.dataMax = zeroReplaceValue;                runtimePieDataTotal = 360;                dataTotalFilterMinAngle = 360;            }            else            {                dataTotalFilterMinAngle = GetTotalAngle(serie, runtimePieDataTotal, ref totalDegree);            }            if (dataTotalFilterMinAngle == 0)            {                dataTotalFilterMinAngle = 360;            }            for (int n = 0; n < data.Count; n++)            {                var serieData = data[n];                var value = isAllZeroValue ? zeroReplaceValue : serieData.GetCurrData(1, serie.animation);                serieData.context.startAngle = startDegree;                serieData.context.toAngle = startDegree;                serieData.context.halfAngle = startDegree;                serieData.context.currentAngle = startDegree;                if (!serieData.show)                {                    continue;                }                float degree = serie.pieRoseType == RoseType.Area ?                    (totalDegree / showdataCount) :                    (float)(totalDegree * value / dataTotalFilterMinAngle);                if (serie.minAngle > 0 && degree < serie.minAngle) degree = serie.minAngle;                serieData.context.toAngle = startDegree + degree;                var halfDegree = (serieData.context.toAngle - startDegree) / 2;                serieData.context.halfAngle = startDegree + halfDegree;                serieData.context.angle = startDegree + halfDegree;                serieData.context.currentAngle = serie.animation.CheckDetailBreak(serieData.context.toAngle)                    ? serie.animation.GetCurrDetail() : serieData.context.toAngle;                serieData.context.insideRadius = serie.context.insideRadius;                serieData.context.canShowLabel = serieData.context.currentAngle >= serieData.context.halfAngle && !serie.IsMinShowLabelValue(value);                UpdateSerieDataRadius(serieData, value);                UpdatePieLabelPosition(serie, serieData);                startDegree = serieData.context.toAngle;            }            AvoidLabelOverlap(serie, chart.theme.common);        }        private void UpdateSerieDataRadius(SerieData serieData, double value)        {            var minChartWidth = Mathf.Min(chart.chartWidth, chart.chartHeight);            var minRadius = serie.minRadius > 0 ? ChartHelper.GetActualValue(serie.minRadius, minChartWidth) : 0;            if (serieData.radius > 0)            {                serieData.context.outsideRadius = ChartHelper.GetActualValue(serieData.radius, minChartWidth);            }            else            {                var minInsideRadius = minRadius > 0 ? minRadius : serie.context.insideRadius;                serieData.context.outsideRadius = serie.pieRoseType > 0 ?                minInsideRadius + (float)((serie.context.outsideRadius - minInsideRadius) * value / serie.context.dataMax) :                serie.context.outsideRadius;            }            if (minRadius > 0 && serieData.context.outsideRadius < minRadius)            {                serieData.context.outsideRadius = minRadius;            }            var offset = 0f;            var interactOffset = serie.animation.interaction.GetOffset(serie.context.outsideRadius);            if (serie.pieClickOffset && (serieData.selected || serieData.context.selected))            {                offset += interactOffset;            }            if (offset > 0)            {                serieData.context.outsideRadius += interactOffset;                var currRad = serieData.context.halfAngle * Mathf.Deg2Rad;                var currSin = Mathf.Sin(currRad);                var currCos = Mathf.Cos(currRad);                serieData.context.offsetRadius = 0;                if (serie.pieClickOffset && (serieData.selected || serieData.context.selected))                {                    serieData.context.offsetRadius += interactOffset;                    if (serieData.context.insideRadius > 0)                    {                        serieData.context.insideRadius += interactOffset;                    }                }                serieData.context.offsetCenter = new Vector3(                    serie.context.center.x + serieData.context.offsetRadius * currSin,                    serie.context.center.y + serieData.context.offsetRadius * currCos);            }            else            {                serieData.context.offsetCenter = serie.context.center;            }            if (serieData.context.highlight)            {                serieData.context.outsideRadius = serie.animation.GetInteractionRadius(serieData.context.outsideRadius);            }            var halfRadius = serie.context.insideRadius + (serieData.context.outsideRadius - serie.context.insideRadius) / 2;            serieData.context.position = ChartHelper.GetPosition(serie.context.center, serieData.context.halfAngle, halfRadius);        }        private double GetTotalAngle(Serie serie, double dataTotal, ref float totalAngle)        {            totalAngle = serie.context.startAngle + 360f;            if (serie.minAngle > 0)            {                var rate = serie.minAngle / 360;                var minAngleValue = dataTotal * rate;                foreach (var serieData in serie.data)                {                    var value = serieData.GetData(1);                    if (value < minAngleValue)                    {                        totalAngle -= serie.minAngle;                        dataTotal -= value;                    }                }                return dataTotal;            }            else            {                return dataTotal;            }        }        private void DrawPieCenter(VertexHelper vh, Serie serie, ItemStyle itemStyle, float insideRadius)        {            if (!ChartHelper.IsClearColor(itemStyle.centerColor))            {                var radius = insideRadius - itemStyle.centerGap;                UGL.DrawCricle(vh, serie.context.center, radius, itemStyle.centerColor, chart.settings.cicleSmoothness);            }        }        private void DrawPie(VertexHelper vh, Pie serie)        {            if (!serie.show || serie.animation.HasFadeOut())            {                return;            }            var dataChanging = false;            var interacting = false;            var color = ColorUtil.clearColor32;            var toColor = ColorUtil.clearColor32;            var interactDuration = serie.animation.GetInteractionDuration();            var interactEnable = serie.animation.enable && serie.animation.interaction.enable                && !serie.animation.IsFadeIn() && !serie.animation.IsFadeOut();            var data = serie.data;            serie.animation.InitProgress(0, 360);            if (data.Count == 0)            {                var itemStyle = SerieHelper.GetItemStyle(serie, null);                var fillColor = ChartHelper.IsClearColor(itemStyle.backgroundColor) ?                    (Color32)chart.theme.legend.unableColor : itemStyle.backgroundColor;                UGL.DrawDoughnut(vh, serie.context.center, serie.context.insideRadius,                    serie.context.outsideRadius, fillColor, fillColor, Color.clear, 0,                    360, itemStyle.borderWidth, itemStyle.borderColor, serie.gap / 2, chart.settings.cicleSmoothness,                    false, true, serie.radiusGradient);            }            for (int n = 0; n < data.Count; n++)            {                var serieData = data[n];                if (!serieData.show)                {                    continue;                }                if (serieData.IsDataChanged())                    dataChanging = true;                var itemStyle = SerieHelper.GetItemStyle(serie, serieData);                var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);                var outsideRadius = 0f;                var needOffset = (serie.pieClickOffset && (serieData.selected || serieData.context.selected));                var offsetCenter = needOffset ? serieData.context.offsetCenter : serie.context.center;                var borderWidth = itemStyle.borderWidth;                var borderColor = itemStyle.borderColor;                var progress = AnimationStyleHelper.CheckDataAnimation(chart, serie, n, 1);                var insideRadius = serieData.context.insideRadius * progress;                if (!interactEnable || !serieData.interact.TryGetValueAndColor(                    ref outsideRadius, ref offsetCenter, ref color, ref toColor, ref interacting, interactDuration))                {                    SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, colorIndex);                    outsideRadius = serieData.context.outsideRadius * progress;                    if (interactEnable)                    {                        serieData.interact.SetValueAndColor(ref interacting, outsideRadius, color, toColor);                        serieData.interact.SetPosition(ref interacting, offsetCenter);                    }                }                var drawEndDegree = serieData.context.currentAngle;                var needRoundCap = serie.roundCap && insideRadius > 0;                UGL.DrawDoughnut(vh, offsetCenter, insideRadius,                    outsideRadius, color, toColor, Color.clear, serieData.context.startAngle,                    drawEndDegree, borderWidth, borderColor, serie.gap / 2, chart.settings.cicleSmoothness,                    needRoundCap, true, serie.radiusGradient);                DrawPieCenter(vh, serie, itemStyle, insideRadius);                if (serie.animation.CheckDetailBreak(serieData.context.toAngle))                    break;            }            if (!serie.animation.IsFinish())            {                serie.animation.CheckProgress();                serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));                chart.RefreshPainter(serie);            }            if (dataChanging || interacting)            {                chart.RefreshPainter(serie);            }        }        private static void UpdatePieLabelPosition(Serie serie, SerieData serieData)        {            if (serieData.labelObject == null) return;            var startAngle = serie.context.startAngle;            var currAngle = serieData.context.halfAngle;            var currRad = currAngle * Mathf.Deg2Rad;            var offsetRadius = serieData.context.offsetRadius;            var insideRadius = serieData.context.insideRadius;            var outsideRadius = serieData.context.outsideRadius;            var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);            var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);            var center = serieData.context.offsetCenter;            var interact = false;            serieData.interact.TryGetValueAndColor(ref outsideRadius, ref center, ref interact, serie.animation.GetInteractionDuration());            var diffAngle = (currAngle - startAngle) % 360;            var isLeft = diffAngle > 180 || (diffAngle == 0 && serieData.context.startAngle > 0);            switch (serieLabel.position)            {                case LabelStyle.Position.Center:                    serieData.context.labelPosition = serie.context.center;                    break;                case LabelStyle.Position.Inside:                case LabelStyle.Position.Middle:                    var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2 + serieLabel.distance;                    var labelCenter = new Vector2(center.x + labelRadius * Mathf.Sin(currRad),                        center.y + labelRadius * Mathf.Cos(currRad));                    UpdateLabelPosition(serie, serieData, labelLine, labelCenter, isLeft);                    break;                default:                    //LabelStyle.Position.Outside                    var startPos = new Vector2(center.x + outsideRadius * Mathf.Sin(currRad),                            center.y + outsideRadius * Mathf.Cos(currRad));                    UpdateLabelPosition(serie, serieData, labelLine, startPos, isLeft);                    break;            }        }        private static void UpdateLabelPosition(Serie serie, SerieData serieData, LabelLine labelLine, Vector3 startPosition, bool isLeft)        {            serieData.context.labelLinePosition = startPosition;            if (labelLine == null || !labelLine.show)            {                serieData.context.labelPosition = startPosition;                return;            }            var dire = isLeft ? Vector3.left : Vector3.right;            var rad = Mathf.Deg2Rad * serieData.context.halfAngle;            var lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);            var lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);            var radius = lineLength1 + serie.context.outsideRadius - serieData.context.outsideRadius;            var pos1 = startPosition;            var pos2 = pos1 + new Vector3(Mathf.Sin(rad) * radius, Mathf.Cos(rad) * radius);            var pos5 = labelLine.lineType == LabelLine.LineType.HorizontalLine                ? pos1 + dire * (radius + lineLength2) + labelLine.GetEndSymbolOffset()                : pos2 + dire * lineLength2 + labelLine.GetEndSymbolOffset();            if (labelLine.lineEndX != 0)            {                pos5.x = serie.context.center.x + (isLeft ? -Mathf.Abs(labelLine.lineEndX) : Mathf.Abs(labelLine.lineEndX));            }            serieData.context.labelLinePosition2 = pos2;            serieData.context.labelPosition = pos5;        }        private void DrawPieLabelLine(VertexHelper vh, Serie serie, bool isTop)        {            foreach (var serieData in serie.data)            {                var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);                var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);                if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))                {                    int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);                    if (serieLabel != null && serieLabel.show &&                        labelLine != null && labelLine.show)                    {                        if (serieLabel.position == LabelStyle.Position.Inside || serieLabel.position == LabelStyle.Position.Middle)                        {                            if (!isTop) continue;                        }                        else                        {                            if (isTop && !labelLine.startSymbol.show) continue;                        }                        var color = ChartHelper.IsClearColor(labelLine.lineColor) ?                            chart.theme.GetColor(colorIndex) :                            labelLine.lineColor;                        switch (labelLine.lineType)                        {                            case LabelLine.LineType.BrokenLine:                                UGL.DrawLine(vh, serieData.context.labelLinePosition, serieData.context.labelLinePosition2,                                    serieData.context.labelPosition, labelLine.lineWidth, color);                                break;                            case LabelLine.LineType.Curves:                                if (serieData.context.labelLinePosition2 == serieData.context.labelPosition)                                {                                    UGL.DrawCurves(vh, serieData.context.labelLinePosition, serieData.context.labelPosition,                                    serieData.context.labelLinePosition, (serieData.context.labelLinePosition + serieData.context.labelPosition) * 0.6f,                                    labelLine.lineWidth, color, chart.settings.lineSmoothness);                                }                                else                                {                                    UGL.DrawCurves(vh, serieData.context.labelLinePosition, serieData.context.labelPosition,                                    serieData.context.labelLinePosition, serieData.context.labelLinePosition2,                                    labelLine.lineWidth, color, chart.settings.lineSmoothness);                                }                                break;                            case LabelLine.LineType.HorizontalLine:                                UGL.DrawLine(vh, serieData.context.labelLinePosition, serieData.context.labelPosition,                                    labelLine.lineWidth, color);                                break;                        }                        DrawLabelLineSymbol(vh, labelLine, serieData.context.labelLinePosition, serieData.context.labelPosition, color);                    }                }            }        }        private int GetPiePosIndex(Serie serie, Vector2 local)        {            if (!(serie is Pie))                return -1;            var dist = Vector2.Distance(local, serie.context.center);            var interactOffset = serie.animation.interaction.GetOffset(serie.context.outsideRadius);            var maxRadius = serie.context.outsideRadius + 2 * interactOffset;            if (dist < serie.context.insideRadius || dist > maxRadius)                return -1;            var dir = local - new Vector2(serie.context.center.x, serie.context.center.y);            var angle = ChartHelper.GetAngle360(Vector2.up, dir);            for (int i = 0; i < serie.data.Count; i++)            {                var serieData = serie.data[i];                if (angle >= serieData.context.startAngle && angle <= serieData.context.toAngle)                {                    var ndist = (serieData.selected || serieData.context.selected) ?                        Vector2.Distance(local, serieData.context.offsetCenter) :                        dist;                    if (ndist >= serieData.context.insideRadius && ndist <= serieData.context.outsideRadius)                    {                        return i;                    }                }            }            return -1;        }        private bool PointerIsInPieSerie(Serie serie, Vector2 local)        {            if (!(serie is Pie))                return false;            var dist = Vector2.Distance(local, serie.context.center);            if (dist >= serie.context.insideRadius && dist <= serie.context.outsideRadius)                return true;            return false;        }        private float GetStartAngle(Serie serie)        {            return serie.clockwise ? (serie.startAngle + 360) % 360 : 360 - serie.startAngle;        }        private float GetToAngle(Serie serie, float angle)        {            var toAngle = angle + serie.startAngle;            if (!serie.clockwise)            {                toAngle = 360 - angle - serie.startAngle;            }            if (!serie.animation.IsFinish())            {                var currAngle = serie.animation.GetCurrDetail();                if (serie.clockwise)                {                    toAngle = toAngle > currAngle ? currAngle : toAngle;                }                else                {                    toAngle = toAngle < 360 - currAngle ? 360 - currAngle : toAngle;                }            }            return toAngle;        }        private void AvoidLabelOverlap(Serie serie, ComponentTheme theme)        {            if (!serie.avoidLabelOverlap) return;            var lastCheckPos = Vector3.zero;            var lastX = 0f;            var data = serie.data;            var splitCount = 0;            for (int n = 0; n < data.Count; n++)            {                var serieData = data[n];                if (serieData.context.labelPosition.x != 0 && serieData.context.labelPosition.x < serie.context.center.x)                {                    splitCount = n;                    break;                }            }            var limitX = float.MinValue;            for (int n = 0; n < splitCount; n++)            {                CheckSerieDataLabel(serie, data[n], splitCount, false, n == splitCount - 1, theme, ref lastCheckPos, ref lastX, ref limitX);            }            lastCheckPos = Vector3.zero;            limitX = float.MaxValue;            for (int n = data.Count - 1; n >= splitCount; n--)            {                CheckSerieDataLabel(serie, data[n], data.Count - splitCount, true, n == splitCount, theme, ref lastCheckPos, ref lastX, ref limitX);            }        }        private void CheckSerieDataLabel(Serie serie, SerieData serieData, int total, bool isLeft, bool isLastOne, ComponentTheme theme,            ref Vector3 lastCheckPos, ref float lastX, ref float limitX)        {            if (!serieData.context.canShowLabel)            {                serieData.SetLabelActive(false);                return;            }            if (!serieData.show) return;            var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);            if (serieLabel == null) return;            if (!serieLabel.show) return;            var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);            var fontSize = serieData.labelObject.GetHeight();            var lineLength1 = 0f;            var lineLength2 = 0f;            if (labelLine != null && labelLine.show)            {                lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);                lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);            }            if (lastCheckPos == Vector3.zero)            {                lastCheckPos = serieData.context.labelPosition;            }            else if (serieData.context.labelPosition.x != 0)            {                if (lastCheckPos.y - serieData.context.labelPosition.y < fontSize)                {                    var labelRadius = serie.context.outsideRadius + lineLength1;                    var y1 = lastCheckPos.y - fontSize;                    var cy = serie.context.center.y;                    var diff = Mathf.Abs(y1 - cy);                    var diffX = labelRadius * labelRadius - diff * diff;                    diffX = diffX <= 0 ? 0 : diffX;                    var x1 = serie.context.center.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);                    var newPos = new Vector3(x1, y1);                    serieData.context.labelLinePosition2 = newPos;                    if (isLeft)                    {                        if (x1 < limitX)                        {                            limitX = x1;                            serieData.context.labelPosition = new Vector3(newPos.x - lineLength2, newPos.y);                            lastX = serieData.context.labelPosition.x;                        }                        else                        {                            serieData.context.labelPosition = new Vector3(lastX, y1);                            lastX += 2;                        }                    }                    else                    {                        if (x1 > limitX)                        {                            limitX = x1;                            serieData.context.labelPosition = new Vector3(newPos.x + lineLength2, newPos.y);                            lastX = serieData.context.labelPosition.x;                        }                        else                        {                            serieData.context.labelPosition = new Vector3(lastX, y1);                            lastX -= 2;                        }                    }                    if (labelLine != null && labelLine.show && labelLine.lineEndX != 0)                    {                        serieData.context.labelPosition.x = isLeft ? -Mathf.Abs(labelLine.lineEndX) : Mathf.Abs(labelLine.lineEndX);                    }                    if (!isLastOne && serieData.context.labelPosition.y < serieData.context.labelLinePosition.y)                    {                        serieData.context.labelLinePosition2 = serieData.context.labelPosition;                    }                    else                    {                        if (isLeft && serieData.context.labelLinePosition2.x > serieData.context.labelLinePosition.x)                        {                            serieData.context.labelLinePosition2.x = serieData.context.labelLinePosition.x;                        }                        else if (!isLeft && serieData.context.labelLinePosition2.x < serieData.context.labelLinePosition.x)                        {                            serieData.context.labelLinePosition2.x = serieData.context.labelLinePosition.x;                        }                    }                }                else                {                    lastX = serieData.context.labelPosition.x;                }                lastCheckPos = serieData.context.labelPosition;                UpdateLabelPosition(serieData, serieLabel);            }        }    }}
 |