UI update 02

This commit is contained in:
2026-06-30 21:21:30 +08:00
parent b2a1e307a4
commit f62f643cfc
1666 changed files with 211081 additions and 22799 deletions
+37
View File
@@ -0,0 +1,37 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(BarHandler), true)]
[SerieConvert(typeof(Line), typeof(Pie))]
[CoordOptions(typeof(GridCoord), typeof(PolarCoord))]
[DefaultAnimation(AnimationType.BottomToTop)]
[DefaultTooltip(Tooltip.Type.Shadow, Tooltip.Trigger.Axis)]
[SerieComponent(typeof(TitleStyle), typeof(LabelStyle), typeof(EmphasisStyle), typeof(BlurStyle), typeof(SelectStyle))]
[SerieDataComponent(typeof(ItemStyle), typeof(TitleStyle), typeof(LabelStyle), typeof(EmphasisStyle), typeof(BlurStyle), typeof(SelectStyle))]
[SerieDataExtraField("m_Ignore")]
public class Bar : Serie, INeedSerieContainer
{
public override bool useSortData { get { return realtimeSort; } }
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Bar>(serieName);
for (int i = 0; i < 5; i++)
{
chart.AddData(serie.index, UnityEngine.Random.Range(10, 90));
}
return serie;
}
public static Bar ConvertSerie(Serie serie)
{
var newSerie = SerieHelper.CloneSerie<Bar>(serie);
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cfb8051cfc49e4afabd94a11c5912c3e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,215 @@
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
/// <summary>
/// For polar coord
/// </summary>
internal sealed partial class BarHandler
{
private PolarCoord m_SeriePolar;
private void UpdateSeriePolarContext()
{
if (m_SeriePolar == null)
return;
var needCheck = (chart.isPointerInChart && m_SeriePolar.IsPointerEnter()) || m_LegendEnter;
var lineWidth = 0f;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
var needAnimation1 = false;
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
serie.interact.SetValue(ref needAnimation1, lineWidth);
foreach (var serieData in serie.data)
{
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData, chart.theme.serie.lineSymbolSize);
serieData.context.highlight = false;
serieData.interact.SetValue(ref needAnimation1, symbolSize);
}
if (needAnimation1)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
return;
}
m_LastCheckContextFlag = needCheck;
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
var needInteract = false;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
serie.interact.SetValue(ref needInteract, serie.animation.interaction.GetWidth(lineWidth));
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var size = SerieHelper.GetSysmbolSize(serie, serieData, themeSymbolSize, SerieState.Emphasis);
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, size);
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
var dir = chart.pointerPos - new Vector2(m_SeriePolar.context.center.x, m_SeriePolar.context.center.y);
var pointerAngle = ChartHelper.GetAngle360(Vector2.up, dir);
var pointerRadius = Vector2.Distance(chart.pointerPos, m_SeriePolar.context.center);
Color32 color, toColor;
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
if (pointerAngle >= serieData.context.startAngle &&
pointerAngle < serieData.context.toAngle &&
pointerRadius >= serieData.context.insideRadius &&
pointerRadius < serieData.context.outsideRadius)
{
serie.context.pointerItemDataIndex = i;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
}
else
{
serieData.context.highlight = false;
}
var state = SerieHelper.GetSerieState(serie, serieData, true);
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, state);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
}
if (needInteract)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
private void DrawPolarBar(VertexHelper vh, Serie serie)
{
var datas = serie.data;
if (datas.Count <= 0)
return;
m_SeriePolar = chart.GetChartComponent<PolarCoord>(serie.polarIndex);
if (m_SeriePolar == null)
return;
var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, m_SeriePolar.index);
var m_RadiusAxis = ComponentHelper.GetRadiusAxis(chart.components, m_SeriePolar.index);
if (m_AngleAxis == null || m_RadiusAxis == null)
return;
var startAngle = m_AngleAxis.context.startAngle;
var currDetailProgress = 0f;
var totalDetailProgress = datas.Count;
serie.animation.InitProgress(currDetailProgress, totalDetailProgress);
var isStack = SeriesHelper.IsStack<Bar>(chart.series, serie.stack);
if (isStack)
SeriesHelper.UpdateStackDataList(chart.series, serie, null, m_StackSerieData);
var barCount = chart.GetSerieBarRealCount<Bar>(-1);
var categoryWidth = m_AngleAxis.IsCategory() ?
AxisHelper.GetDataWidth(m_AngleAxis, 360, datas.Count, null) :
AxisHelper.GetDataWidth(m_RadiusAxis, m_SeriePolar.context.radius, datas.Count, null);
var barGap = chart.GetSerieBarGap<Bar>(-1);
var totalBarWidth = chart.GetSerieTotalWidth<Bar>(categoryWidth, barGap, barCount, -1);
var barWidth = serie.GetBarWidth(categoryWidth, barCount);
var offset = (categoryWidth - totalBarWidth) * 0.5f;
var serieReadIndex = chart.GetSerieIndexIfStack<Bar>(serie, -1);
float gap = serie.barGap == -1 ? offset :
offset + chart.GetSerieTotalGap<Bar>(categoryWidth, barGap, serieReadIndex, -1);
var areaColor = ColorUtil.clearColor32;
var areaToColor = ColorUtil.clearColor32;
var interacting = false;
var interactDuration = serie.animation.GetInteractionDuration();
float start, end;
float inside, outside;
double radiusValue, angleValue;
for (int i = 0; i < datas.Count; i++)
{
if (serie.animation.CheckDetailBreak(i))
break;
var serieData = datas[i];
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
radiusValue = serieData.GetData(0);
angleValue = serieData.GetData(1);
if (m_AngleAxis.IsCategory())
{
start = (float)(startAngle + categoryWidth * angleValue + gap);
end = start + barWidth;
inside = m_SeriePolar.context.insideRadius;
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
inside += m_StackSerieData[n][i].context.stackHeight;
}
outside = inside + m_RadiusAxis.GetValueLength(radiusValue, m_SeriePolar.context.radius);
serieData.context.stackHeight = outside - inside;
}
else
{
start = startAngle;
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
start += m_StackSerieData[n][i].context.stackHeight;
}
end = start + m_AngleAxis.GetValueLength(angleValue, 360);
serieData.context.stackHeight = end - start;
inside = m_SeriePolar.context.insideRadius + categoryWidth * (float)radiusValue + gap;
outside = inside + barWidth;
}
serieData.context.startAngle = start;
serieData.context.toAngle = end;
serieData.context.halfAngle = (start + end) / 2;
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting, interactDuration))
{
SerieHelper.GetItemColor(out areaColor, out areaToColor, serie, serieData, chart.theme);
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
}
var needRoundCap = serie.roundCap && inside > 0;
serieData.context.insideRadius = inside;
serieData.context.outsideRadius = outside;
serieData.context.areaCenter = m_SeriePolar.context.center;
serieData.context.position = ChartHelper.GetPosition(m_SeriePolar.context.center, (start + end) / 2, (inside + outside) / 2);
UGL.DrawDoughnut(vh, m_SeriePolar.context.center, inside, outside, areaColor, areaToColor,
ColorUtil.clearColor32, start, end, borderWidth, borderColor, serie.gap / 2, chart.settings.cicleSmoothness,
needRoundCap, true);
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(totalDetailProgress);
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
chart.RefreshChart();
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 152848d4f7ed84b0491d277fd55b64ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,596 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed partial class BarHandler : SerieHandler<Bar>
{
List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
private GridCoord m_SerieGrid;
private float[] m_CapusleDefaultCornerRadius = new float[] { 1, 1, 1, 1 };
public override void UpdateSerieContext()
{
if (serie.IsUseCoord<GridCoord>())
UpdateSerieGridContext();
else if (serie.IsUseCoord<PolarCoord>())
UpdateSeriePolarContext();
}
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)
{
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
marker, itemFormatter, numericFormatter, ignoreDataDefaultContent);
}
public override void DrawSerie(VertexHelper vh)
{
if (serie.IsUseCoord<PolarCoord>())
{
DrawPolarBar(vh, serie);
}
else if (serie.IsUseCoord<GridCoord>())
{
DrawBarSerie(vh, serie);
}
}
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
{
if (serie.IsUseCoord<PolarCoord>())
{
switch (label.position)
{
case LabelStyle.Position.Start:
case LabelStyle.Position.Bottom:
var center = serieData.context.areaCenter;
var angle = serieData.context.halfAngle;
var radius = serieData.context.insideRadius;
return ChartHelper.GetPosition(center, angle, radius);
case LabelStyle.Position.Top:
case LabelStyle.Position.End:
center = serieData.context.areaCenter;
angle = serieData.context.halfAngle;
radius = serieData.context.outsideRadius;
return ChartHelper.GetPosition(center, angle, radius);
default:
return serieData.context.position;
}
}
else
{
switch (label.position)
{
case LabelStyle.Position.Start:
case LabelStyle.Position.Bottom:
var center = serieData.context.rect.center;
if (serie.context.isHorizontal)
return new Vector3(center.x - serieData.context.rect.width / 2, center.y);
else
return new Vector3(center.x, center.y - serieData.context.rect.height / 2);
case LabelStyle.Position.Center:
case LabelStyle.Position.Inside:
case LabelStyle.Position.Middle:
return serieData.context.rect.center;
default:
return serieData.context.position;
}
}
}
public override Vector3 GetSerieDataTitlePosition(SerieData serieData, TitleStyle titleStyle)
{
return GetSerieDataLabelPosition(serieData, titleStyle);
}
private void UpdateSerieGridContext()
{
if (m_SerieGrid == null)
return;
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter() && !serie.placeHolder) || m_LegendEnter;
var needInteract = false;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
Color32 color1, toColor1;
foreach (var serieData in serie.data)
{
serieData.context.highlight = false;
var state = SerieHelper.GetSerieState(serie, serieData, true);
SerieHelper.GetItemColor(out color1, out toColor1, serie, serieData, chart.theme, state);
serieData.interact.SetColor(ref needInteract, color1, toColor1);
}
chart.RefreshPainter(serie);
}
return;
}
m_LastCheckContextFlag = needCheck;
Color32 color, toColor;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
foreach (var serieData in serie.data)
{
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
if (serie.context.pointerAxisDataIndexs.Contains(serieData.index) ||
serieData.context.rect.Contains(chart.pointerPos))
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
}
else
{
serieData.context.highlight = false;
}
var state = SerieHelper.GetSerieState(serie, serieData, true);
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, state);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void DrawBarSerie(VertexHelper vh, Bar serie)
{
if (!serie.show || serie.animation.HasFadeOut())
return;
Axis axis;
Axis relativedAxis;
var isY = chart.GetSerieGridCoordAxis(serie, out axis, out relativedAxis);
if (axis == null)
return;
if (relativedAxis == null)
return;
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
if (m_SerieGrid == null)
return;
if (serie.useSortData)
{
SerieHelper.UpdateSerieRuntimeFilterData(serie);
}
var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom, true);
if (showData.Count <= 0)
return;
var visualMap = chart.GetVisualMapOfSerie(serie);
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
var relativedAxisLength = isY ? m_SerieGrid.context.width : m_SerieGrid.context.height;
var axisXY = isY ? m_SerieGrid.context.y : m_SerieGrid.context.x;
var isStack = SeriesHelper.IsStack<Bar>(chart.series, serie.stack);
if (isStack)
SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
var barCount = chart.GetSerieBarRealCount<Bar>(m_SerieGrid.index);
float categoryWidth = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
float relativedCategoryWidth = AxisHelper.GetDataWidth(relativedAxis, relativedAxisLength, showData.Count, dataZoom);
float barGap = chart.GetSerieBarGap<Bar>(m_SerieGrid.index);
float totalBarWidth = chart.GetSerieTotalWidth<Bar>(categoryWidth, barGap, barCount, m_SerieGrid.index);
float barWidth = serie.GetBarWidth(categoryWidth, barCount);
float offset = (categoryWidth - totalBarWidth) * 0.5f;
var serieReadIndex = chart.GetSerieIndexIfStack<Bar>(serie, m_SerieGrid.index);
float gap = serie.barGap == -1 ? offset :
offset + chart.GetSerieTotalGap<Bar>(categoryWidth, barGap, serieReadIndex, m_SerieGrid.index);
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(chart.series, serie.stack);
var dataChanging = false;
var dataChangeDuration = serie.animation.GetChangeDuration();
var dataAddDuration = serie.animation.GetAdditionDuration();
var interactDuration = serie.animation.GetInteractionDuration();
var exchangeDuration = serie.animation.GetExchangeDuration();
var areaColor = ColorUtil.clearColor32;
var areaToColor = ColorUtil.clearColor32;
var interacting = false;
axis.context.scaleWidth = categoryWidth;
serie.context.isHorizontal = isY;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
serie.animation.InitProgress(axisXY, axisXY + axisLength);
var visualMapDimension = VisualMapHelper.GetDimension(visualMap, defaultDimension);
if (visualMap != null && visualMap.show && visualMap.autoMinMax)
{
double maxValue, minValue;
SerieHelper.GetMinMaxData(serie, visualMapDimension, out minValue, out maxValue);
VisualMapHelper.SetMinMax(visualMap, minValue, maxValue);
}
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (!serieData.show || serie.IsIgnoreValue(serieData))
{
serie.context.dataPoints.Add(Vector3.zero);
serie.context.dataIndexs.Add(serieData.index);
continue;
}
if (serieData.IsDataChanged())
dataChanging = true;
var state = SerieHelper.GetSerieState(serie, serieData);
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, state);
var value = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
var relativedValue = serieData.GetCurrData(1, dataAddDuration, dataChangeDuration, relativedAxis.inverse, 0, 0, serie.animation.unscaledTime);
var borderWidth = relativedValue == 0 ? 0 : itemStyle.borderWidth;
var borderGap = relativedValue == 0 ? 0 : itemStyle.borderGap;
var borderGapAndWidth = borderWidth + borderGap;
var backgroundColor = itemStyle.backgroundColor;
var backgroundGap = itemStyle.backgroundGap;
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting, interactDuration))
{
SerieHelper.GetItemColor(out areaColor, out areaToColor, serie, serieData, chart.theme);
if (visualMap != null && visualMap.show)
{
var visualValue = serieData.GetData(visualMapDimension, relativedAxis.inverse);
areaColor = visualMap.GetColor(visualValue);
areaToColor = areaColor;
}
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
}
var pX = 0f;
var pY = 0f;
var runtimeBarWidth = barWidth;
var runtimeGap = gap;
if (serie.ignoreZeroOccupy)
{
UpdateActiveBarLayout(serie, dataZoom, i, categoryWidth, barGap, runtimeBarWidth, ref runtimeGap);
}
UpdateXYPosition(m_SerieGrid, isY, axis, relativedAxis, i, categoryWidth, relativedCategoryWidth,
runtimeBarWidth, isStack, value, backgroundGap, ref pX, ref pY);
if (serie.useSortData)
{
serieData.context.UpdateExchangePosition(ref pX, ref pY, exchangeDuration);
}
float barHig;
if (isPercentStack)
{
var valueTotal = chart.GetSerieSameStackTotalValue<Bar>(serie.stack, i, m_SerieGrid.index);
barHig = valueTotal != 0 ? (float)(relativedValue / valueTotal * (relativedAxisLength - 2 * backgroundGap)) : 0;
}
else
{
barHig = AxisHelper.GetAxisValueLength(m_SerieGrid, relativedAxis, relativedCategoryWidth, relativedValue, 2 * backgroundGap);
}
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
Vector3 plb, plt, prt, prb, top;
UpdateRectPosition(m_SerieGrid, isY, relativedValue, pX, pY, runtimeGap, borderWidth, runtimeBarWidth, currHig,
out plb, out plt, out prt, out prb, out top);
serieData.context.stackHeight = barHig;
serieData.context.position = top;
serieData.context.rect = Rect.MinMaxRect(plb.x + borderGapAndWidth, plb.y + borderGapAndWidth,
prt.x - borderGapAndWidth, prt.y - borderGapAndWidth);
serieData.context.backgroundRect = isY ?
Rect.MinMaxRect(m_SerieGrid.context.x, plb.y - backgroundGap, m_SerieGrid.context.x + relativedAxisLength, prt.y + backgroundGap) :
Rect.MinMaxRect(plb.x - backgroundGap, m_SerieGrid.context.y, prb.x + backgroundGap, m_SerieGrid.context.y + relativedAxisLength);
if (!serie.clip || (serie.clip && m_SerieGrid.Contains(top)))
{
serie.context.dataPoints.Add(top);
serie.context.dataIndexs.Add(serieData.index);
}
else
{
continue;
}
if (serie.show && !serie.placeHolder)
{
switch (serie.barType)
{
case BarType.Normal:
case BarType.Capsule:
DrawNormalBar(vh, serie, serieData, itemStyle, backgroundColor, runtimeGap, runtimeBarWidth,
pX, pY, plb, plt, prt, prb, isY, m_SerieGrid, axis, areaColor, areaToColor, relativedValue);
break;
case BarType.Zebra:
DrawZebraBar(vh, serie, serieData, itemStyle, backgroundColor, runtimeGap, runtimeBarWidth,
pX, pY, plb, plt, prt, prb, isY, m_SerieGrid, axis, areaColor, areaToColor);
break;
}
}
if (serie.animation.CheckDetailBreak(top, isY))
{
break;
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
chart.RefreshPainter(serie);
}
if (dataChanging || interacting)
{
chart.RefreshPainter(serie);
}
}
List<string> m_SlotOrder = new List<string>();
Dictionary<string, bool> m_ActiveSlot = new Dictionary<string, bool>();
private void UpdateActiveBarLayout(Bar currentSerie, DataZoom dataZoom, int dataIndex,
float categoryWidth, float barGap, float barWidth, ref float gap)
{
m_SlotOrder.Clear();
m_ActiveSlot.Clear();
for (int n = 0; n < chart.series.Count; n++)
{
var serie = chart.series[n] as Bar;
if (serie == null || !serie.show || serie.placeHolder)
continue;
if (!IsSerieInGrid(serie, m_SerieGrid.index))
continue;
var slotKey = GetBarSlotKey(serie);
if (!m_ActiveSlot.ContainsKey(slotKey))
{
m_ActiveSlot[slotKey] = false;
m_SlotOrder.Add(slotKey);
}
if (IsSerieDataActiveForLayout(serie, dataZoom, dataIndex))
{
m_ActiveSlot[slotKey] = true;
}
}
var currentSlotKey = GetBarSlotKey(currentSerie);
if (!m_ActiveSlot.ContainsKey(currentSlotKey) || !m_ActiveSlot[currentSlotKey])
return;
var activeCount = 0;
var activeSlotIndex = -1;
for (int n = 0; n < m_SlotOrder.Count; n++)
{
var slotKey = m_SlotOrder[n];
if (!m_ActiveSlot[slotKey])
continue;
if (slotKey == currentSlotKey)
activeSlotIndex = activeCount;
activeCount++;
}
if (activeCount <= 0 || activeSlotIndex < 0)
return;
var actualGap = ChartHelper.GetActualValue(barGap, barWidth);
var totalBarWidth = barGap == -1
? barWidth
: activeCount * barWidth + (activeCount - 1) * actualGap;
var offset = (categoryWidth - totalBarWidth) * 0.5f;
gap = barGap == -1
? offset
: offset + activeSlotIndex * (barWidth + actualGap);
}
private string GetBarSlotKey(Bar serie)
{
return string.IsNullOrEmpty(serie.stack) ? "s_" + serie.index : "k_" + serie.stack;
}
private bool IsSerieDataActiveForLayout(Bar serie, DataZoom dataZoom, int dataIndex)
{
var dataList = serie.GetDataList(dataZoom, true);
if (dataList == null || dataIndex < 0 || dataIndex >= dataList.Count)
return false;
var serieData = dataList[dataIndex];
if (serieData == null || !serieData.show || serie.IsIgnoreValue(serieData))
return false;
if (!serie.ignoreZeroOccupy)
return true;
return !MathUtil.Approximately(serieData.GetData(1), 0);
}
private bool IsSerieInGrid(Bar serie, int gridIndex)
{
XAxis xAxis;
if (chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex))
{
if (xAxis.gridIndex != gridIndex)
return false;
}
YAxis yAxis;
if (chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex))
{
if (yAxis.gridIndex != gridIndex)
return false;
}
return true;
}
private void UpdateXYPosition(GridCoord grid, bool isY, Axis axis, Axis relativedAxis, int i,
float categoryWidth, float relativedCategoryWidth, float barWidth, bool isStack,
double value, float backgroundGap, ref float pX, ref float pY)
{
if (isY)
{
if (axis.IsCategory())
{
pY = grid.context.y + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pY = grid.context.y;
else
{
var valueLen = (float)((value - axis.context.minValue) / axis.context.minMaxRange) * grid.context.height;
pY = grid.context.y + valueLen - categoryWidth * 0.5f;
}
}
pX = AxisHelper.GetAxisValuePosition(grid, relativedAxis, relativedCategoryWidth, 0) + backgroundGap;
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
pX += m_StackSerieData[n][i].context.stackHeight;
}
}
else
{
if (axis.IsCategory())
{
pX = grid.context.x + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pX = grid.context.x;
else
{
var valueLen = (float)((value - axis.context.minValue) / axis.context.minMaxRange) * grid.context.width;
pX = grid.context.x + valueLen - categoryWidth * 0.5f;
}
}
pY = AxisHelper.GetAxisValuePosition(grid, relativedAxis, relativedCategoryWidth, 0) + backgroundGap;
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
pY += m_StackSerieData[n][i].context.stackHeight;
}
}
}
private void UpdateRectPosition(GridCoord grid, bool isY, double yValue, float pX, float pY, float gap, float borderWidth,
float barWidth, float currHig,
out Vector3 plb, out Vector3 plt, out Vector3 prt, out Vector3 prb, out Vector3 top)
{
if (isY)
{
if (yValue < 0)
{
plt = new Vector3(pX + currHig, pY + gap + barWidth);
prt = new Vector3(pX, pY + gap + barWidth);
prb = new Vector3(pX, pY + gap);
plb = new Vector3(pX + currHig, pY + gap);
}
else
{
plt = new Vector3(pX, pY + gap + barWidth);
prt = new Vector3(pX + currHig, pY + gap + barWidth);
prb = new Vector3(pX + currHig, pY + gap);
plb = new Vector3(pX, pY + gap);
}
top = new Vector3(pX + currHig, pY + gap + barWidth / 2);
}
else
{
if (yValue < 0)
{
plb = new Vector3(pX + gap, pY + currHig);
plt = new Vector3(pX + gap, pY);
prt = new Vector3(pX + gap + barWidth, pY);
prb = new Vector3(pX + gap + barWidth, pY + currHig);
}
else
{
plb = new Vector3(pX + gap, pY);
plt = new Vector3(pX + gap, pY + currHig);
prt = new Vector3(pX + gap + barWidth, pY + currHig);
prb = new Vector3(pX + gap + barWidth, pY);
}
top = new Vector3(pX + gap + barWidth / 2, pY + currHig);
}
if (serie.clip)
{
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
prb = chart.ClampInGrid(grid, prb);
top = chart.ClampInGrid(grid, top);
}
}
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, Color32 backgroundColor,
float gap, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, GridCoord grid, Axis axis, Color32 areaColor, Color32 areaToColor, double value)
{
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
if (ChartHelper.IsClearColor(borderColor))
{
borderColor = areaColor;
borderColor.a = (byte)(areaColor.a * 1.2f);
}
var cornerRadius = serie.barType == BarType.Capsule && !itemStyle.IsNeedCorner() ?
m_CapusleDefaultCornerRadius :
itemStyle.cornerRadius;
var invert = value < 0;
if (!ChartHelper.IsClearColor(backgroundColor))
{
UGL.DrawRoundRectangle(vh, serieData.context.backgroundRect, backgroundColor, backgroundColor, 0,
cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
UGL.DrawRoundRectangle(vh, serieData.context.rect, areaColor, areaToColor, 0,
cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
if (serie.barType == BarType.Capsule)
{
UGL.DrawBorder(vh, serieData.context.backgroundRect, borderWidth, borderColor,
0, cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert, -borderWidth);
}
else
{
UGL.DrawBorder(vh, serieData.context.rect, borderWidth, borderColor,
0, cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert, itemStyle.borderGap);
}
}
private void DrawZebraBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, Color32 backgroundColor,
float gap, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, GridCoord grid, Axis axis, Color32 barColor, Color32 barToColor)
{
if (!ChartHelper.IsClearColor(backgroundColor))
{
UGL.DrawRoundRectangle(vh, serieData.context.backgroundRect, backgroundColor, backgroundColor, 0,
null, isYAxis, chart.settings.cicleSmoothness, false);
}
if (isYAxis)
{
plt = (plb + plt) / 2;
prt = (prt + prb) / 2;
chart.DrawClipZebraLine(vh, plt, prt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
barColor, barToColor, serie.clip, grid, grid.context.width);
}
else
{
plb = (prb + plb) / 2;
plt = (plt + prt) / 2;
chart.DrawClipZebraLine(vh, plb, plt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
barColor, barToColor, serie.clip, grid, grid.context.height);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5bd8425bf4c1b4bf2adf8940be58ddec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,42 @@
using System;
using UnityEngine;
namespace XCharts.Runtime
{
[Serializable]
[SerieHandler(typeof(SimplifiedBarHandler), true)]
[SerieConvert(typeof(SimplifiedLine), typeof(Bar))]
[CoordOptions(typeof(GridCoord))]
[DefaultAnimation(AnimationType.LeftToRight, false)]
[DefaultTooltip(Tooltip.Type.Shadow, Tooltip.Trigger.Axis)]
[SerieComponent()]
[SerieDataComponent()]
[SerieDataExtraField()]
public class SimplifiedBar : Serie, INeedSerieContainer, ISimplifiedSerie
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<SimplifiedBar>(serieName);
serie.symbol.show = false;
var lastValue = 0d;
for (int i = 0; i < 50; i++)
{
if (i < 20)
lastValue += UnityEngine.Random.Range(0, 5);
else
lastValue += UnityEngine.Random.Range(-3, 5);
chart.AddData(serie.index, lastValue);
}
return serie;
}
public static SimplifiedBar ConvertSerie(Serie serie)
{
var newSerie = serie.Clone<SimplifiedBar>();
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7fc754e0afd4d4f138389c19611aaedb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,355 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class SimplifiedBarHandler : SerieHandler<SimplifiedBar>
{
private GridCoord m_SerieGrid;
public override void Update()
{
base.Update();
}
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)
{
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
marker, itemFormatter, numericFormatter, ignoreDataDefaultContent);
}
public override void DrawSerie(VertexHelper vh)
{
DrawBarSerie(vh, serie, serie.context.colorIndex);
}
public override void UpdateSerieContext()
{
if (m_SerieGrid == null)
return;
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
var needInteract = false;
Color32 color, toColor;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, SerieState.Normal);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
return;
}
m_LastCheckContextFlag = needCheck;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
foreach (var serieData in serie.data)
{
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, SerieState.Emphasis);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
if (serieData.context.rect.Contains(chart.pointerPos))
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, SerieState.Emphasis);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
else
{
serieData.context.highlight = false;
SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, SerieState.Normal);
serieData.interact.SetColor(ref needInteract, color, toColor);
}
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void DrawBarSerie(VertexHelper vh, SimplifiedBar serie, int colorIndex)
{
if (!serie.show || serie.animation.HasFadeOut())
return;
Axis axis;
Axis relativedAxis;
var isY = chart.GetSerieGridCoordAxis(serie, out axis, out relativedAxis);
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
if (axis == null)
return;
if (relativedAxis == null)
return;
if (m_SerieGrid == null)
return;
var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom);
if (showData.Count <= 0)
return;
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
var relativedAxisLength = isY ? m_SerieGrid.context.width : m_SerieGrid.context.height;
var axisXY = isY ? m_SerieGrid.context.y : m_SerieGrid.context.x;
var barCount = chart.GetSerieBarRealCount<SimplifiedBar>(m_SerieGrid.index);
float categoryWidth = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
float relativedCategoryWidth = AxisHelper.GetDataWidth(relativedAxis, relativedAxisLength, showData.Count, dataZoom);
float barGap = chart.GetSerieBarGap<SimplifiedBar>(m_SerieGrid.index);
float totalBarWidth = chart.GetSerieTotalWidth<SimplifiedBar>(categoryWidth, barGap, barCount,m_SerieGrid.index);
float barWidth = serie.GetBarWidth(categoryWidth, barCount);
float offset = (categoryWidth - totalBarWidth) * 0.5f;
float barGapWidth = barWidth + barWidth * barGap;
float gap = serie.barGap == -1 ? offset : offset + serie.index * barGapWidth;
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
var dataChanging = false;
var dataChangeDuration = serie.animation.GetChangeDuration();
var dataAddDuration = serie.animation.GetAdditionDuration();
var interactDuration = serie.animation.GetInteractionDuration();
var areaColor = ColorUtil.clearColor32;
var areaToColor = ColorUtil.clearColor32;
var interacting = false;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
serie.animation.InitProgress(axisXY, axisXY + axisLength);
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (!serieData.show || serie.IsIgnoreValue(serieData))
{
serie.context.dataPoints.Add(Vector3.zero);
serie.context.dataIndexs.Add(serieData.index);
continue;
}
if (serieData.IsDataChanged())
dataChanging = true;
var highlight = serieData.context.highlight || serie.highlight;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
var value = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
var relativedValue = serieData.GetCurrData(1, dataAddDuration, dataChangeDuration, relativedAxis.inverse, 0, 0, serie.animation.unscaledTime);
var borderWidth = relativedValue == 0 ? 0 : itemStyle.borderWidth;
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting, interactDuration))
{
SerieHelper.GetItemColor(out areaColor, out areaToColor, serie, serieData, chart.theme);
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
}
var pX = 0f;
var pY = 0f;
UpdateXYPosition(m_SerieGrid, isY, axis, relativedAxis, i, categoryWidth, relativedCategoryWidth, barWidth, value, ref pX, ref pY);
var barHig = AxisHelper.GetAxisValueLength(m_SerieGrid, relativedAxis, relativedCategoryWidth, relativedValue);
var currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
Vector3 plb, plt, prt, prb, top;
UpdateRectPosition(m_SerieGrid, isY, relativedValue, pX, pY, gap, borderWidth, barWidth, currHig,
out plb, out plt, out prt, out prb, out top);
serieData.context.stackHeight = barHig;
serieData.context.position = top;
serieData.context.rect = Rect.MinMaxRect(plb.x, plb.y, prb.x, prt.y);
serie.context.dataPoints.Add(top);
serie.context.dataIndexs.Add(serieData.index);
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, gap, barWidth,
pX, pY, plb, plt, prt, prb, false, m_SerieGrid, areaColor, areaToColor);
if (serie.animation.CheckDetailBreak(top, isY))
{
break;
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
chart.RefreshPainter(serie);
}
if (dataChanging || interacting)
{
chart.RefreshPainter(serie);
}
}
private void UpdateXYPosition(GridCoord grid, bool isY, Axis axis, Axis relativedAxis, int i, float categoryWidth,
float relativedCategoryWidth, float barWidth, double value, ref float pX, ref float pY)
{
if (isY)
{
if (axis.IsCategory())
{
pY = grid.context.y + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pY = grid.context.y;
else pY = grid.context.y + (float)((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.height - barWidth);
}
pX = AxisHelper.GetAxisValuePosition(grid, relativedAxis, relativedCategoryWidth, 0);
}
else
{
if (axis.IsCategory())
{
pX = grid.context.x + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pX = grid.context.x;
else pX = grid.context.x + (float)((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.width - barWidth);
}
pY = AxisHelper.GetAxisValuePosition(grid, relativedAxis, relativedCategoryWidth, 0);
}
}
private void UpdateRectPosition(GridCoord grid, bool isY, double yValue, float pX, float pY, float gap, float borderWidth,
float barWidth, float currHig,
out Vector3 plb, out Vector3 plt, out Vector3 prt, out Vector3 prb, out Vector3 top)
{
if (isY)
{
if (yValue < 0)
{
plt = new Vector3(pX - borderWidth, pY + gap + barWidth - borderWidth);
prt = new Vector3(pX + currHig + borderWidth, pY + gap + barWidth - borderWidth);
prb = new Vector3(pX + currHig + borderWidth, pY + gap + borderWidth);
plb = new Vector3(pX - borderWidth, pY + gap + borderWidth);
}
else
{
plt = new Vector3(pX + borderWidth, pY + gap + barWidth - borderWidth);
prt = new Vector3(pX + currHig - borderWidth, pY + gap + barWidth - borderWidth);
prb = new Vector3(pX + currHig - borderWidth, pY + gap + borderWidth);
plb = new Vector3(pX + borderWidth, pY + gap + borderWidth);
}
top = new Vector3(pX + currHig - borderWidth, pY + gap + barWidth / 2);
}
else
{
if (yValue < 0)
{
plb = new Vector3(pX + gap + borderWidth, pY - borderWidth);
plt = new Vector3(pX + gap + borderWidth, pY + currHig + borderWidth);
prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig + borderWidth);
prb = new Vector3(pX + gap + barWidth - borderWidth, pY - borderWidth);
}
else
{
plb = new Vector3(pX + gap + borderWidth, pY + borderWidth);
plt = new Vector3(pX + gap + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + gap + barWidth - borderWidth, pY + borderWidth);
}
top = new Vector3(pX + gap + barWidth / 2, pY + currHig - borderWidth);
}
if (serie.clip)
{
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
prb = chart.ClampInGrid(grid, prb);
top = chart.ClampInGrid(grid, top);
}
}
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float gap, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, GridCoord grid, Color32 areaColor, Color32 areaToColor)
{
var borderWidth = itemStyle.borderWidth;
if (isYAxis)
{
if (serie.clip)
{
prb = chart.ClampInGrid(grid, prb);
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
}
var itemWidth = Mathf.Abs(prb.x - plt.x);
var itemHeight = Mathf.Abs(prt.y - plb.y);
var center = new Vector3((plt.x + prb.x) / 2, (prt.y + plb.y) / 2);
if (itemWidth > 0 && itemHeight > 0)
{
var invert = center.x < plb.x;
if (itemStyle.IsNeedCorner())
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
else
{
chart.DrawClipPolygon(vh, plb, plt, prt, prb, areaColor, areaToColor, serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
}
else
{
if (serie.clip)
{
prb = chart.ClampInGrid(grid, prb);
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
}
var itemWidth = Mathf.Abs(prt.x - plb.x);
var itemHeight = Mathf.Abs(plt.y - prb.y);
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
if (itemWidth > 0 && itemHeight > 0)
{
var invert = center.y < plb.y;
if (itemStyle.IsNeedCorner())
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
else
{
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaToColor,
serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afd7226ecff7f4b9fad297101bc33b8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: