1500 lines
53 KiB
C#
1500 lines
53 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace EasyChart
|
|
{
|
|
public enum CoordinateSystemType
|
|
{
|
|
Cartesian2D,
|
|
Polar2D,
|
|
None
|
|
}
|
|
|
|
public enum AxisId
|
|
{
|
|
XBottom,
|
|
XTop,
|
|
YLeft,
|
|
YRight
|
|
}
|
|
|
|
public enum AxisType
|
|
{
|
|
Category,
|
|
Value
|
|
}
|
|
|
|
public enum CategoryLabelPlacement
|
|
{
|
|
Tick,
|
|
CellCenter
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class CartesianMapping
|
|
{
|
|
public AxisId xAxisId = AxisId.XBottom;
|
|
public AxisId yAxisId = AxisId.YLeft;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PlotLayoutSettings
|
|
{
|
|
public Vector2 centerOffset = Vector2.zero;
|
|
public float padding = 10f;
|
|
public float labelRadialOffset = 0f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class LabelStyleSettings
|
|
{
|
|
public bool enabled = true;
|
|
public int fontSize = 10;
|
|
public Color color = Color.white;
|
|
public LabelPosition position = LabelPosition.Outside;
|
|
public Vector2 offset = Vector2.zero;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class AxisConfig
|
|
{
|
|
public AxisId id;
|
|
public AxisType axisType = AxisType.Value;
|
|
|
|
public List<string> labels = new List<string>();
|
|
|
|
public bool visible = true;
|
|
public Color color = Color.white;
|
|
public float width = 2.0f;
|
|
|
|
public LabelStyleSettings labelStyle;
|
|
|
|
public bool showLabels = true;
|
|
public int fontSize = 10;
|
|
public Color labelColor = Color.white;
|
|
public LabelPosition labelPosition = LabelPosition.Outside;
|
|
[InspectorName("LabelPlacement")]
|
|
public CategoryLabelPlacement labelPlacement = CategoryLabelPlacement.Tick;
|
|
public Vector2 labelOffset = Vector2.zero;
|
|
public bool autoRangeMin = true;
|
|
public bool autoRangeMax = true;
|
|
public AutoRangeRoundingMode autoRangeRounding = AutoRangeRoundingMode.Tens;
|
|
public float autoRangeUnit = 1f;
|
|
public float minValue = 0f;
|
|
public float maxValue = 1f;
|
|
|
|
public bool autoTicks = true;
|
|
public int splitCount = 5;
|
|
public string labelFormat;
|
|
|
|
public bool categoryAutoScroll = false;
|
|
public bool categorySmoothScroll = true;
|
|
public float categoryScrollInterval = 1.0f;
|
|
public int categoryScrollStep = 1;
|
|
|
|
public bool showUnit = false;
|
|
public string unitText;
|
|
public LabelStyleSettings unitLabelStyle;
|
|
}
|
|
|
|
public enum AutoRangeRoundingMode
|
|
{
|
|
None,
|
|
Integer,
|
|
Tens,
|
|
Hundreds,
|
|
Custom
|
|
}
|
|
|
|
public enum SerieType
|
|
{
|
|
// 折线图:适合展示随时间/类别变化的趋势(连续变化)。常用度:★★★★★ 难度:★★☆☆☆
|
|
Line = 0,
|
|
// 柱状图:适合展示分类对比(离散类别),强调数量大小。常用度:★★★★★ 难度:★★☆☆☆
|
|
Bar = 1,
|
|
// 饼图:适合展示占比构成(总量=100%),不适合类别过多。常用度:★★★★☆ 难度:★★★☆☆
|
|
Pie = 2,
|
|
// 散点图:适合展示二维数据分布、相关性(x-y 点)。常用度:★★★★☆ 难度:★★★☆☆
|
|
Scatter = 4,
|
|
// 雷达图:适合展示多维指标对比(同一维度尺度下的多项指标)。常用度:★★★☆☆ 难度:★★★★☆
|
|
Radar = 5,
|
|
// 环形图:饼图的变体,可在中心留空用于显示总量/标题等。常用度:★★★☆☆ 难度:★★★☆☆
|
|
RingChart = 6,
|
|
// 热力图:适合展示二维矩阵强度/密度(例如日历热力、相关矩阵等)。常用度:★★★☆☆ 难度:★★★★☆
|
|
Heatmap = 7,
|
|
// 仪表盘:展示单一指标当前值/区间(类似速度表)。常用度:★★☆☆☆ 难度:★★★☆☆
|
|
Gauge = 8,
|
|
// 横向柱状图:与柱状图类似,但横向布局更适合长标签类别。常用度:★★★★☆ 难度:★★☆☆☆
|
|
HorizontalBar = 9,
|
|
// K 线图:金融蜡烛图(开/高/低/收),用于行情走势。常用度:★★☆☆☆ 难度:★★★★★
|
|
Candlestick = 21,
|
|
// OHLC 图:与 K 线类似,用线段表示开高低收(更简洁)。常用度:★★☆☆☆ 难度:★★★★★
|
|
OHLC = 22,
|
|
// 箱线图:展示分布统计(四分位数、中位数、异常值)。常用度:★★☆☆☆ 难度:★★★★★
|
|
BoxPlot = 23,
|
|
// 直方图:展示单变量分布(分箱计数)。常用度:★★★☆☆ 难度:★★★☆☆
|
|
Histogram = 24,
|
|
// 瀑布图:展示从起点到终点的增减构成(正负贡献)。常用度:★★☆☆☆ 难度:★★★★☆
|
|
Waterfall = 25,
|
|
// 漏斗图:展示流程转化/阶段漏损(例如注册→下单→支付)。常用度:★★☆☆☆ 难度:★★★☆☆
|
|
Funnel = 26,
|
|
// 桑基图:展示流量/能量/资金流向与分配(有向流图)。常用度:★☆☆☆☆ 难度:★★★★★(不适合用当前 SeriesData,需图结构/边数据,先注释)
|
|
// Sankey = 30,
|
|
// 矩形树图:用矩形面积展示层级与占比(适合层级占比对比)。常用度:★☆☆☆☆ 难度:★★★★★(不适合用当前 SeriesData,需层级节点数据,先注释)
|
|
// TreeMap = 31,
|
|
// 旭日图:环形层级占比图(层级结构的构成展示)。常用度:★☆☆☆☆ 难度:★★★★★(不适合用当前 SeriesData,需层级节点数据,先注释)
|
|
// Sunburst = 32,
|
|
// 弦图:展示类别之间的关联/流量(成对关系强度)。常用度:★☆☆☆☆ 难度:★★★★★(不适合用当前 SeriesData,需矩阵/边数据,先注释)
|
|
// Chord = 33,
|
|
// 3D 饼图:饼图的三维表现形式(通常属于 Pro 扩展)。常用度:★☆☆☆☆ 难度:★★★★★
|
|
Pie3D = 100,
|
|
// 3D 柱状图:三维柱形对比(可能用于二维分类 + 数值)。常用度:★☆☆☆☆ 难度:★★★★★
|
|
Bar3D = 101,
|
|
// 3D 折线图:三维折线/轨迹展示(z 维度叠加)。常用度:★☆☆☆☆ 难度:★★★★★
|
|
Line3D = 102,
|
|
// 3D 散点图:三维坐标点分布(x,y,z)。常用度:★☆☆☆☆ 难度:★★★★★
|
|
Scatter3D = 103,
|
|
|
|
}
|
|
|
|
[System.Serializable]
|
|
public abstract class BaseSerieSettings
|
|
{
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PointSettings : ISerializationCallbackReceiver
|
|
{
|
|
public bool show = true;
|
|
public float size = 4.0f;
|
|
|
|
[InspectorName("Texture")]
|
|
public TextureFillSettings textureFill = new TextureFillSettings();
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings();
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings();
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class TextureMappingSettings
|
|
{
|
|
public Texture2D texture;
|
|
public Vector2 tiling = Vector2.one;
|
|
public Vector2 offset = Vector2.zero;
|
|
}
|
|
|
|
public enum TextureFillAnimationType
|
|
{
|
|
None = 0,
|
|
TextureUvMove = 1,
|
|
TextureScale = 2,
|
|
TextureFade = 3
|
|
}
|
|
|
|
public enum TextureFillScaleType
|
|
{
|
|
ZoomIn = 0,
|
|
ZoomOut = 1,
|
|
Sin = 2,
|
|
PingPong = 3
|
|
}
|
|
|
|
public enum TextureFillColorOverLifeWrap
|
|
{
|
|
Loop = 0,
|
|
PingPong = 1,
|
|
Clamp = 2
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class TextureFillSettings : ISerializationCallbackReceiver
|
|
{
|
|
public Texture2D texture;
|
|
public Vector2 tiling = Vector2.one;
|
|
public Vector2 offset = Vector2.zero;
|
|
public Color color = Color.white;
|
|
|
|
public TextureFillAnimationType animationType = TextureFillAnimationType.None;
|
|
|
|
public Vector2 uvMoveSpeed = Vector2.zero;
|
|
|
|
public TextureFillScaleType scaleType = TextureFillScaleType.Sin;
|
|
public float scaleSpeed = 1f;
|
|
|
|
public Vector2 scaleFrom = Vector2.one;
|
|
public Vector2 scaleTo = new Vector2(1.2f, 1.2f);
|
|
public Color colorFadeStart = Color.white;
|
|
public Color colorFadeEnd = new Color(1f, 1f, 1f, 0f);
|
|
public float colorFadeSpeed = 1f;
|
|
|
|
public TextureFillColorOverLifeWrap colorFadeWrap = TextureFillColorOverLifeWrap.PingPong;
|
|
public Gradient colorFadeGradient;
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (colorFadeGradient == null)
|
|
{
|
|
colorFadeGradient = new Gradient();
|
|
colorFadeGradient.SetKeys(
|
|
new[]
|
|
{
|
|
new GradientColorKey(colorFadeStart, 0f),
|
|
new GradientColorKey(colorFadeEnd, 1f)
|
|
},
|
|
new[]
|
|
{
|
|
new GradientAlphaKey(colorFadeStart.a, 0f),
|
|
new GradientAlphaKey(colorFadeEnd.a, 1f)
|
|
}
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class SeriesData
|
|
{
|
|
public string id;
|
|
public float x;
|
|
public float value;
|
|
public float y;
|
|
public float z;
|
|
public string name;
|
|
public bool useColor = false;
|
|
public Color color = Color.white;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class SizeMappingSettings
|
|
{
|
|
public bool enabled = false;
|
|
public float minValue = 0f;
|
|
public float maxValue = 1f;
|
|
public float minSize = 4f;
|
|
public float maxSize = 12f;
|
|
public bool clamp = true;
|
|
public AnimationCurve curve = AnimationCurve.Linear(0, 0, 1, 1);
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class HoverHighlightSettings : ISerializationCallbackReceiver
|
|
{
|
|
public bool enabled = false;
|
|
[SerializeField, HideInInspector]
|
|
private float _scale = 1.5f;
|
|
|
|
[SerializeField, HideInInspector]
|
|
private TextureFillSettings _textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.35f) };
|
|
|
|
public float scale
|
|
{
|
|
get => _scale;
|
|
set => _scale = value;
|
|
}
|
|
|
|
public TextureFillSettings textureFill
|
|
{
|
|
get => _textureFill;
|
|
set => _textureFill = value;
|
|
}
|
|
|
|
public float pickRadius = 8f;
|
|
|
|
public PointSettings point = new PointSettings();
|
|
|
|
public Color lineColor = new Color(1f, 1f, 1f, 0.35f);
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (_textureFill == null) _textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.35f) };
|
|
if (point == null) point = new PointSettings();
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (_textureFill == null) _textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.35f) };
|
|
if (point == null) point = new PointSettings();
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class BarHoverSettings : ISerializationCallbackReceiver
|
|
{
|
|
public bool enabled = false;
|
|
public float pickRadius = 8f;
|
|
public float scale = 1.5f;
|
|
public TextureFillSettings textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.35f) };
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.35f) };
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.35f) };
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class LineStrokeSettings
|
|
{
|
|
public LineType lineType = LineType.Straight;
|
|
public float width = 2.0f;
|
|
public Color color = Color.white;
|
|
|
|
[InspectorName("Texture")]
|
|
public TextureFillSettings textureFill = new TextureFillSettings();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class AreaFillSettings : ISerializationCallbackReceiver
|
|
{
|
|
public bool show = false;
|
|
|
|
[InspectorName("Texture")]
|
|
public TextureFillSettings textureFill = new TextureFillSettings { color = new Color(1, 1, 1, 0.2f) };
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings { color = new Color(1, 1, 1, 0.2f) };
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings { color = new Color(1, 1, 1, 0.2f) };
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class BorderSettings
|
|
{
|
|
public float width = 0f;
|
|
public Color color = new Color(0, 0, 0, 0);
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class BackgroundSettings : ISerializationCallbackReceiver
|
|
{
|
|
public bool show = false;
|
|
|
|
[InspectorName("Texture")]
|
|
public TextureFillSettings textureFill = new TextureFillSettings { color = new Color(1, 1, 1, 0.08f) };
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings { color = new Color(1, 1, 1, 0.08f) };
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings { color = new Color(1, 1, 1, 0.08f) };
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class LineSettings : BaseSerieSettings
|
|
{
|
|
[Header("Stroke")]
|
|
[InspectorName("Stroke")]
|
|
public LineStrokeSettings stroke = new LineStrokeSettings();
|
|
|
|
[Header("Point")]
|
|
public PointSettings point = new PointSettings();
|
|
|
|
[Header("Hover")]
|
|
public HoverHighlightSettings hover = new HoverHighlightSettings();
|
|
|
|
[Header("Area")]
|
|
public AreaFillSettings area = new AreaFillSettings();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class ScatterSettings : BaseSerieSettings
|
|
{
|
|
[Header("Point")]
|
|
public PointSettings point = new PointSettings();
|
|
|
|
public SizeMappingSettings sizeMapping = new SizeMappingSettings();
|
|
|
|
public HoverHighlightSettings hover = new HoverHighlightSettings();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class HeatmapSettings : BaseSerieSettings
|
|
{
|
|
public enum RenderMode
|
|
{
|
|
[Tooltip("Discrete cell-based rendering with sharp boundaries")]
|
|
Grid,
|
|
[Tooltip("Smooth pixel-based rendering using Gaussian interpolation")]
|
|
Gradient,
|
|
[Tooltip("Contour lines with optional filled regions")]
|
|
Contour
|
|
}
|
|
|
|
public enum InfluenceMode
|
|
{
|
|
[Tooltip("No influence spreading between cells")]
|
|
None,
|
|
[Tooltip("Values bleed into neighboring cells with falloff")]
|
|
Bleed,
|
|
[Tooltip("Gaussian smoothing applied to the grid")]
|
|
Smooth
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class BleedSettings
|
|
{
|
|
[Tooltip("Number of cells the influence spreads to")]
|
|
public int radiusCells = 1;
|
|
[Tooltip("Number of discrete falloff steps")]
|
|
public int steps = 6;
|
|
[Tooltip("Strength of the bleed effect (0-1)")]
|
|
[Range(0f, 1f)]
|
|
public float strength = 0.35f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class SmoothSettings
|
|
{
|
|
[Tooltip("Radius of the smoothing kernel in cells")]
|
|
public int radiusCells = 1;
|
|
[Tooltip("Number of smoothing passes to apply")]
|
|
public int passes = 1;
|
|
[Tooltip("Standard deviation of the Gaussian kernel")]
|
|
public float sigma = 1f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class GradientSettings
|
|
{
|
|
[Tooltip("Texture resolution for gradient rendering (higher = smoother but slower)")]
|
|
public int resolution = 256;
|
|
[Tooltip("Gaussian kernel sigma for density estimation (larger = smoother blending)")]
|
|
public float sigma = 30f;
|
|
[Tooltip("Contrast adjustment: higher values increase contrast (sharper peaks), lower values spread colors more evenly")]
|
|
public float intensity = 1f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class ContourSettings
|
|
{
|
|
[Tooltip("Number of contour levels to generate")]
|
|
public int levels = 10;
|
|
[Tooltip("Width of contour lines in pixels")]
|
|
public float lineWidth = 1f;
|
|
[Tooltip("Show filled regions between contour lines")]
|
|
public bool showFill = true;
|
|
[Tooltip("Show contour lines")]
|
|
public bool showLines = true;
|
|
[Tooltip("Color of the contour lines")]
|
|
public Color lineColor = new Color(0.2f, 0.2f, 0.2f, 0.8f);
|
|
}
|
|
|
|
[Tooltip("Rendering mode: Grid (discrete cells), Gradient (smooth interpolation), or Contour (isolines)")]
|
|
public RenderMode renderMode = RenderMode.Grid;
|
|
|
|
[Tooltip("Gap between cells in pixels (Grid mode only)")]
|
|
public float cellGapPx = 1f;
|
|
|
|
[Tooltip("Number of horizontal cells when using Value axis type")]
|
|
public int xSplitCount = 10;
|
|
[Tooltip("Number of vertical cells when using Value axis type")]
|
|
public int ySplitCount = 10;
|
|
|
|
[Tooltip("Automatically calculate value range from data")]
|
|
public bool autoRange = true;
|
|
[Tooltip("Minimum value for color mapping (when autoRange is off)")]
|
|
public float minValue = 0f;
|
|
[Tooltip("Maximum value for color mapping (when autoRange is off)")]
|
|
public float maxValue = 1f;
|
|
|
|
[Tooltip("How cell values influence neighboring cells (Grid mode only)")]
|
|
public InfluenceMode influenceMode = InfluenceMode.None;
|
|
[Tooltip("Settings for Bleed influence mode")]
|
|
public BleedSettings bleed = new BleedSettings();
|
|
[Tooltip("Settings for Smooth influence mode")]
|
|
public SmoothSettings smooth = new SmoothSettings();
|
|
[Tooltip("Settings for Gradient render mode")]
|
|
public GradientSettings gradient = new GradientSettings();
|
|
[Tooltip("Settings for Contour render mode")]
|
|
public ContourSettings contour = new ContourSettings();
|
|
|
|
[Tooltip("Clamp values to min/max range before color mapping")]
|
|
public bool clamp = true;
|
|
[Tooltip("Color for minimum values")]
|
|
public Color lowColor = new Color(0f, 0.55f, 1f, 1f);
|
|
[Tooltip("Color for middle values (used for interpolation)")]
|
|
public Color midColor = Color.white;
|
|
[Tooltip("Color for maximum values")]
|
|
public Color highColor = new Color(1f, 0.25f, 0.25f, 1f);
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class RadarSettings : BaseSerieSettings
|
|
{
|
|
[System.Serializable]
|
|
public class RadarLayoutSettings
|
|
{
|
|
public float startAngleDeg = -90f;
|
|
public bool clockwise = true;
|
|
|
|
public float innerRadius = 0f;
|
|
public float outerRadius = 0f;
|
|
|
|
public PlotLayoutSettings plot = new PlotLayoutSettings();
|
|
|
|
public TextureFillSettings background = new TextureFillSettings { color = new Color(0.2f, 0.2f, 0.2f, 0.3f) };
|
|
}
|
|
|
|
[Header("Radar")]
|
|
public RadarLayoutSettings radar = new RadarLayoutSettings();
|
|
|
|
[Header("LineStroke")]
|
|
[InspectorName("LineStroke")]
|
|
public LineStrokeSettings stroke = new LineStrokeSettings();
|
|
|
|
[Header("Area")]
|
|
public AreaFillSettings area = new AreaFillSettings { show = true, textureFill = new TextureFillSettings { color = new Color(1f, 1f, 1f, 0.2f) } };
|
|
|
|
[Header("Point")]
|
|
public PointSettings point = new PointSettings();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class BarSettings : BaseSerieSettings, ISerializationCallbackReceiver
|
|
{
|
|
public float barWidth = 10f;
|
|
|
|
[InspectorName("Texture")]
|
|
public TextureFillSettings textureFill = new TextureFillSettings();
|
|
|
|
public bool stacked = false;
|
|
|
|
public float cornerRadius = 0f;
|
|
public int cornerSegments = 4;
|
|
|
|
public string stackGroup = "";
|
|
public float barGap = 2f;
|
|
public float categoryGap = 0f;
|
|
|
|
public BorderSettings border = new BorderSettings();
|
|
|
|
public BackgroundSettings background = new BackgroundSettings();
|
|
|
|
public BarHoverSettings hover = new BarHoverSettings();
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings();
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (textureFill == null) textureFill = new TextureFillSettings();
|
|
|
|
if (hover == null) hover = new BarHoverSettings();
|
|
hover.OnAfterDeserialize();
|
|
}
|
|
}
|
|
|
|
public enum SliceGapType
|
|
{
|
|
Radial,
|
|
Translate,
|
|
Uniform
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PieLayoutSettings
|
|
{
|
|
public float startAngleDeg = -90f;
|
|
public bool clockwise = true;
|
|
public float angleRangeDeg = 360f;
|
|
|
|
public float innerRadius = 0f;
|
|
public Color innerRadiusColor = new Color(0, 0, 0, 0);
|
|
public float cornerRadius = 0f;
|
|
public float sliceGapPx = 0f;
|
|
public SliceGapType sliceGapType = SliceGapType.Radial;
|
|
public float outerRadius = 0f;
|
|
|
|
public PlotLayoutSettings plot = new PlotLayoutSettings();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class RingSettings
|
|
{
|
|
public bool showBackground = false;
|
|
public float backgroundAlpha = 0.25f;
|
|
public Color backgroundColor = new Color(0, 0, 0, 0);
|
|
public float cornerRadius = 0f;
|
|
public float ringGapPx = 0f;
|
|
}
|
|
|
|
public enum PieLegendSource
|
|
{
|
|
Slice,
|
|
RingSlice,
|
|
Series
|
|
}
|
|
|
|
public enum ValueDisplayStyle
|
|
{
|
|
None,
|
|
Parentheses,
|
|
AlignedColumns
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PieLegendSettings
|
|
{
|
|
[HideInInspector] public bool overrideEnabled = false;
|
|
public PieLegendSource source = PieLegendSource.Slice;
|
|
|
|
public bool enabled = true;
|
|
[HideInInspector] public bool showValue = false;
|
|
public ValueDisplayStyle valueDisplayStyle = ValueDisplayStyle.None;
|
|
public LegendPosition position = LegendPosition.Bottom;
|
|
public int fontSize = 12;
|
|
public Color color = Color.white;
|
|
public Color backgroundColor = new Color(0, 0, 0, 0);
|
|
public float itemSpacing = 10f;
|
|
public Vector2 offset = Vector2.zero;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PieSettings : BaseSerieSettings
|
|
{
|
|
public bool sortByValue = false;
|
|
public PieLayoutSettings layout = new PieLayoutSettings();
|
|
public PieHoverSettings hover = new PieHoverSettings();
|
|
public PieAggregationSettings aggregation = new PieAggregationSettings();
|
|
public RingSettings ring = new RingSettings();
|
|
public PieLegendSettings legend = new PieLegendSettings();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class RingChartLayoutSettings
|
|
{
|
|
public float startAngleDeg = -90f;
|
|
public bool clockwise = true;
|
|
public float angleRangeDeg = 360f;
|
|
public float innerRadius = 0.3f;
|
|
public float outerRadius = 0f;
|
|
public PlotLayoutSettings plot = new PlotLayoutSettings();
|
|
}
|
|
|
|
public enum RingValueMappingMode
|
|
{
|
|
Percent,
|
|
Range
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class RingValueMappingSettings
|
|
{
|
|
public RingValueMappingMode mode = RingValueMappingMode.Percent;
|
|
public bool autoRange = true;
|
|
public float minValue = 0f;
|
|
public float maxValue = 1f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class RingChartSettings : BaseSerieSettings
|
|
{
|
|
public RingChartLayoutSettings layout = new RingChartLayoutSettings();
|
|
public RingValueMappingSettings valueMapping = new RingValueMappingSettings();
|
|
public PieHoverSettings hover = new PieHoverSettings();
|
|
public PieLegendSettings legend = new PieLegendSettings();
|
|
|
|
public bool showBackground = false;
|
|
public float backgroundAlpha = 0.25f;
|
|
public Color backgroundColor = new Color(0, 0, 0, 0);
|
|
public float cornerRadius = 0f;
|
|
public float ringGapPx = 0f;
|
|
}
|
|
|
|
public enum PieExplodeType
|
|
{
|
|
Translate,
|
|
Pull,
|
|
Color,
|
|
Stroke
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PieHoverSettings
|
|
{
|
|
public bool enabled = false;
|
|
public float explodeDistance = 10f;
|
|
public PieExplodeType explodeType = PieExplodeType.Translate;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PieAggregationSettings
|
|
{
|
|
public bool enabled = false;
|
|
public int keepTopN = 0;
|
|
public string othersName = "Others";
|
|
public bool useOthersColor = false;
|
|
public Color othersColor = new Color(0.6f, 0.6f, 0.6f, 1f);
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class SerieLabelSettings
|
|
{
|
|
public bool enabled = true;
|
|
public Color color = Color.white;
|
|
public int fontSize = 10;
|
|
public int decimalPlaces = 2;
|
|
public bool showName = false; // For Pie: show category name
|
|
public Vector2 offset = Vector2.zero;
|
|
public LabelPosition position = LabelPosition.Outside;
|
|
public TextureFillSettings background = new TextureFillSettings { color = new Color(0f, 0f, 0f, 0f) };
|
|
}
|
|
|
|
public enum LegendPosition
|
|
{
|
|
Top,
|
|
Bottom,
|
|
Left,
|
|
Right
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class LegendSettings : ISerializationCallbackReceiver
|
|
{
|
|
public bool enabled = true;
|
|
public LegendPosition position = LegendPosition.Bottom;
|
|
public int fontSize = 12;
|
|
public Color color = Color.white;
|
|
public Color backgroundColor = new Color(0, 0, 0, 0);
|
|
public float itemSpacing = 10f;
|
|
[Tooltip("Offset from edge. Auto-set based on position when zero.")]
|
|
public Vector2 offset = new Vector2(0, -30);
|
|
|
|
[System.NonSerialized] private LegendPosition _lastPosition = LegendPosition.Bottom;
|
|
[System.NonSerialized] private bool _initialized;
|
|
|
|
public void OnBeforeSerialize() { }
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (!_initialized)
|
|
{
|
|
_lastPosition = position;
|
|
_initialized = true;
|
|
}
|
|
}
|
|
|
|
public void SyncOffsetToPosition()
|
|
{
|
|
if (_lastPosition != position)
|
|
{
|
|
offset = GetDefaultOffsetForPosition(position);
|
|
_lastPosition = position;
|
|
}
|
|
}
|
|
|
|
public static Vector2 GetDefaultOffsetForPosition(LegendPosition pos)
|
|
{
|
|
switch (pos)
|
|
{
|
|
case LegendPosition.Top: return new Vector2(0, 30);
|
|
case LegendPosition.Bottom: return new Vector2(0, -30);
|
|
case LegendPosition.Right: return new Vector2(-30, 0);
|
|
case LegendPosition.Left: return new Vector2(30, 0);
|
|
default: return Vector2.zero;
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PlotSettings
|
|
{
|
|
public bool overrideTheme = false;
|
|
public Color backgroundColor = new Color(0f, 0f, 0f, 0f);
|
|
public Color borderColor = new Color(0f, 0f, 0f, 0f);
|
|
public float borderWidth = 0f;
|
|
|
|
[Tooltip("Edge fade distance in pixels for series labels. Labels outside PlotArea will fade to transparent over this distance.")]
|
|
public float labelEdgeFadePx = 20f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class CartesianGridSettings
|
|
{
|
|
public Color xGridColor = new Color(0.5f, 0.5f, 0.5f, 0.2f);
|
|
public float xGridLineWidth = 1.0f;
|
|
public bool xGridDashed = false;
|
|
public float xGridDashLength = 4f;
|
|
public float xGridDashGap = 2f;
|
|
public float xGridDashOffset = 0f;
|
|
public Color yGridColor = new Color(0.5f, 0.5f, 0.5f, 0.2f);
|
|
public float yGridLineWidth = 1.0f;
|
|
public bool yGridDashed = false;
|
|
public float yGridDashLength = 4f;
|
|
public float yGridDashGap = 2f;
|
|
public float yGridDashOffset = 0f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class HoverSettings
|
|
{
|
|
public bool cursorLineDashed = false;
|
|
public float cursorLineWidth = 1f;
|
|
public Color cursorLineColor = Color.yellow;
|
|
public float cursorLineDashLength = 4f;
|
|
public float cursorLineDashGap = 2f;
|
|
public float cursorLineDashOffset = 0f;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PolarAxisStyle
|
|
{
|
|
public List<string> labels = new List<string>();
|
|
|
|
public bool visible = true;
|
|
public Color color = Color.white;
|
|
public Color edgeColor = Color.white;
|
|
public float width = 2.0f;
|
|
|
|
public LabelStyleSettings labelStyle;
|
|
|
|
public bool showLabels = true;
|
|
public int fontSize = 10;
|
|
public Color labelColor = Color.white;
|
|
public LabelPosition labelPosition = LabelPosition.Outside;
|
|
public Vector2 labelOffset = Vector2.zero;
|
|
public bool autoRangeMin = true;
|
|
public bool autoRangeMax = true;
|
|
public AutoRangeRoundingMode autoRangeRounding = AutoRangeRoundingMode.Tens;
|
|
public float autoRangeUnit = 1f;
|
|
public float minValue = 0f;
|
|
public float maxValue = 1f;
|
|
|
|
public bool autoTicks = true;
|
|
public int splitCount = 5;
|
|
public string labelFormat;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class PolarAxesSettings
|
|
{
|
|
public PolarAxisStyle angleAxis = new PolarAxisStyle();
|
|
public PolarAxisStyle radiusAxis = new PolarAxisStyle();
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class ChartData
|
|
{
|
|
public CoordinateSystemType CoordinateSystem = CoordinateSystemType.Cartesian2D;
|
|
public CartesianMapping Cartesian = new CartesianMapping();
|
|
public List<AxisConfig> Axes = new List<AxisConfig>();
|
|
|
|
// New axis fields (X/Y based)
|
|
public AxisId XAxisId = AxisId.XBottom;
|
|
public AxisId YAxisId = AxisId.YLeft;
|
|
|
|
public CartesianGridSettings CartesianGrid = new CartesianGridSettings();
|
|
public HoverSettings Hover = new HoverSettings();
|
|
public PolarAxesSettings PolarAxes = new PolarAxesSettings();
|
|
public PlotSettings Plot = new PlotSettings();
|
|
|
|
public List<Serie> Series = new List<Serie>();
|
|
public LegendSettings legend = new LegendSettings();
|
|
|
|
public float animationDuration = 1.0f;
|
|
}
|
|
|
|
public enum LineType
|
|
{
|
|
Straight,
|
|
Smooth,
|
|
Step
|
|
}
|
|
|
|
public enum LabelPosition
|
|
{
|
|
Outside,
|
|
Inside,
|
|
Center
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class Serie : ISerializationCallbackReceiver
|
|
{
|
|
public string name;
|
|
public string id;
|
|
public SerieType type = SerieType.Line;
|
|
public bool visible = true;
|
|
|
|
[SerializeReference]
|
|
public BaseSerieSettings settings;
|
|
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedLineSettings;
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedBarSettings;
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedPieSettings;
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedRingChartSettings;
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedScatterSettings;
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedRadarSettings;
|
|
[SerializeField, SerializeReference]
|
|
private BaseSerieSettings _cachedHeatmapSettings;
|
|
|
|
public SerieLabelSettings labelSettings = new SerieLabelSettings();
|
|
|
|
// Actual Data
|
|
public List<SeriesData> seriesData = new List<SeriesData>();
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
}
|
|
|
|
public bool SetType(SerieType newType)
|
|
{
|
|
bool changed = false;
|
|
|
|
// Preserve current settings into a per-type cache before switching.
|
|
// IMPORTANT: in editor workflows the enum `type` might already be changed
|
|
// (via SerializedObject.ApplyModifiedProperties) before SetType is called,
|
|
// so we cache based on the runtime type of `settings`, not the current `type`.
|
|
if (settings != null)
|
|
{
|
|
if (settings is LineSettings) _cachedLineSettings = settings;
|
|
else if (settings is BarSettings) _cachedBarSettings = settings;
|
|
else if (settings is PieSettings) _cachedPieSettings = settings;
|
|
else if (settings is ScatterSettings) _cachedScatterSettings = settings;
|
|
else if (settings is RadarSettings) _cachedRadarSettings = settings;
|
|
else if (settings is HeatmapSettings) _cachedHeatmapSettings = settings;
|
|
}
|
|
|
|
if (type != newType)
|
|
{
|
|
type = newType;
|
|
changed = true;
|
|
}
|
|
|
|
// Minimal migration / preservation for common edits.
|
|
// Data loss is acceptable per design, but keeping point settings improves UX.
|
|
if (newType == SerieType.Scatter)
|
|
{
|
|
if (settings is ScatterSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedScatterSettings is ScatterSettings cached)
|
|
{
|
|
settings = cached;
|
|
changed = true;
|
|
}
|
|
else if (settings is LineSettings ls)
|
|
{
|
|
if (ls.point == null) ls.point = new PointSettings();
|
|
settings = new ScatterSettings
|
|
{
|
|
point = ls.point,
|
|
sizeMapping = new SizeMappingSettings(),
|
|
hover = new HoverHighlightSettings()
|
|
};
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new ScatterSettings();
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (newType == SerieType.Line)
|
|
{
|
|
if (settings is LineSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedLineSettings is LineSettings cached)
|
|
{
|
|
settings = cached;
|
|
changed = true;
|
|
}
|
|
else if (settings is ScatterSettings ss)
|
|
{
|
|
if (ss.point == null) ss.point = new PointSettings();
|
|
settings = new LineSettings
|
|
{
|
|
point = ss.point,
|
|
stroke = new LineStrokeSettings(),
|
|
area = new AreaFillSettings()
|
|
};
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new LineSettings();
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (newType == SerieType.Bar || newType == SerieType.HorizontalBar)
|
|
{
|
|
if (settings is BarSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedBarSettings is BarSettings cached)
|
|
{
|
|
settings = cached;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new BarSettings();
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (newType == SerieType.Pie)
|
|
{
|
|
if (settings is PieSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedPieSettings is PieSettings cached)
|
|
{
|
|
settings = cached;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new PieSettings();
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (newType == SerieType.RingChart)
|
|
{
|
|
if (settings is RingChartSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedRingChartSettings is RingChartSettings cachedRing)
|
|
{
|
|
settings = cachedRing;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new RingChartSettings();
|
|
changed = true;
|
|
}
|
|
|
|
if (settings is RingChartSettings ringSettings)
|
|
{
|
|
if (ringSettings.layout == null) { ringSettings.layout = new RingChartLayoutSettings(); changed = true; }
|
|
if (ringSettings.layout != null && ringSettings.layout.innerRadius <= 0f) { ringSettings.layout.innerRadius = 0.3f; changed = true; }
|
|
}
|
|
}
|
|
else if (newType == SerieType.Pie3D)
|
|
{
|
|
if (SerieSettingsRegistry.TryCreate(newType, out var created))
|
|
{
|
|
if (settings is PieSettings oldPs && created is PieSettings newPs && created.GetType() != settings.GetType())
|
|
{
|
|
if (oldPs.layout != null) newPs.layout = oldPs.layout;
|
|
if (oldPs.hover != null) newPs.hover = oldPs.hover;
|
|
if (oldPs.aggregation != null) newPs.aggregation = oldPs.aggregation;
|
|
if (oldPs.ring != null) newPs.ring = oldPs.ring;
|
|
if (oldPs.legend != null) newPs.legend = oldPs.legend;
|
|
settings = newPs;
|
|
changed = true;
|
|
}
|
|
else if (!(settings is PieSettings))
|
|
{
|
|
settings = created;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
settings = null;
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (newType == SerieType.Radar)
|
|
{
|
|
if (settings is RadarSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedRadarSettings is RadarSettings cached)
|
|
{
|
|
settings = cached;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new RadarSettings();
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (newType == SerieType.Heatmap)
|
|
{
|
|
if (settings is HeatmapSettings)
|
|
{
|
|
// ok
|
|
}
|
|
else if (_cachedHeatmapSettings is HeatmapSettings cached)
|
|
{
|
|
settings = cached;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = new HeatmapSettings();
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SerieSettingsRegistry.TryCreate(newType, out var created))
|
|
{
|
|
settings = created;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
settings = null;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (EnsureIntegrity()) changed = true;
|
|
return changed;
|
|
}
|
|
|
|
public bool EnsureIntegrity()
|
|
{
|
|
bool changed = false;
|
|
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
id = Guid.NewGuid().ToString("N");
|
|
changed = true;
|
|
}
|
|
|
|
var before = settings;
|
|
EnsureSettings();
|
|
if (!ReferenceEquals(before, settings)) changed = true;
|
|
|
|
if (labelSettings == null)
|
|
{
|
|
labelSettings = new SerieLabelSettings();
|
|
changed = true;
|
|
}
|
|
|
|
if (labelSettings != null)
|
|
{
|
|
if (labelSettings.fontSize <= 0)
|
|
{
|
|
labelSettings.fontSize = 10;
|
|
changed = true;
|
|
}
|
|
|
|
if (labelSettings.decimalPlaces < 0 || labelSettings.decimalPlaces > 8)
|
|
{
|
|
labelSettings.decimalPlaces = Mathf.Clamp(labelSettings.decimalPlaces, 0, 8);
|
|
changed = true;
|
|
}
|
|
|
|
var c = labelSettings.color;
|
|
bool looksUninitialized = Mathf.Approximately(c.r, 0f)
|
|
&& Mathf.Approximately(c.g, 0f)
|
|
&& Mathf.Approximately(c.b, 0f)
|
|
&& Mathf.Approximately(c.a, 0f);
|
|
if (looksUninitialized)
|
|
{
|
|
labelSettings.color = Color.white;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (seriesData == null)
|
|
{
|
|
seriesData = new List<SeriesData>();
|
|
changed = true;
|
|
}
|
|
|
|
for (int i = 0; i < seriesData.Count; i++)
|
|
{
|
|
var dp = seriesData[i];
|
|
if (dp == null) continue;
|
|
if (string.IsNullOrEmpty(dp.id))
|
|
{
|
|
dp.id = Guid.NewGuid().ToString("N");
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (settings is LineSettings ls)
|
|
{
|
|
if (ls.stroke == null) { ls.stroke = new LineStrokeSettings(); changed = true; }
|
|
if (ls.point == null) { ls.point = new PointSettings(); changed = true; }
|
|
if (ls.area == null) { ls.area = new AreaFillSettings(); changed = true; }
|
|
}
|
|
else if (settings is ScatterSettings ss)
|
|
{
|
|
if (ss.point == null) { ss.point = new PointSettings(); changed = true; }
|
|
if (ss.sizeMapping == null) { ss.sizeMapping = new SizeMappingSettings(); changed = true; }
|
|
if (ss.hover == null) { ss.hover = new HoverHighlightSettings(); changed = true; }
|
|
}
|
|
else if (settings is BarSettings bs)
|
|
{
|
|
if (bs.border == null) { bs.border = new BorderSettings(); changed = true; }
|
|
if (bs.background == null) { bs.background = new BackgroundSettings(); changed = true; }
|
|
if (bs.hover == null) { bs.hover = new BarHoverSettings(); changed = true; }
|
|
}
|
|
else if (settings is PieSettings ps)
|
|
{
|
|
if (ps.layout == null) { ps.layout = new PieLayoutSettings(); changed = true; }
|
|
if (ps.hover == null) { ps.hover = new PieHoverSettings(); changed = true; }
|
|
if (ps.aggregation == null) { ps.aggregation = new PieAggregationSettings(); changed = true; }
|
|
if (ps.ring == null) { ps.ring = new RingSettings(); changed = true; }
|
|
if (ps.legend == null) { ps.legend = new PieLegendSettings(); changed = true; }
|
|
|
|
if (ps.legend != null
|
|
&& ps.legend.valueDisplayStyle == ValueDisplayStyle.None
|
|
&& ps.legend.showValue)
|
|
{
|
|
ps.legend.valueDisplayStyle = ValueDisplayStyle.Parentheses;
|
|
ps.legend.showValue = false;
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (settings is RadarSettings rs)
|
|
{
|
|
if (rs.radar == null) { rs.radar = new RadarSettings.RadarLayoutSettings(); changed = true; }
|
|
if (rs.radar != null && rs.radar.plot == null) { rs.radar.plot = new PlotLayoutSettings(); changed = true; }
|
|
if (rs.stroke == null) { rs.stroke = new LineStrokeSettings(); changed = true; }
|
|
if (rs.area == null) { rs.area = new AreaFillSettings(); changed = true; }
|
|
if (rs.point == null) { rs.point = new PointSettings(); changed = true; }
|
|
}
|
|
else if (settings is HeatmapSettings hs)
|
|
{
|
|
if (hs.cellGapPx < 0f) { hs.cellGapPx = 0f; changed = true; }
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
public void EnsureSettings()
|
|
{
|
|
bool needCreate = settings == null;
|
|
|
|
if (!needCreate)
|
|
{
|
|
switch (type)
|
|
{
|
|
case SerieType.Line:
|
|
needCreate = !(settings is LineSettings);
|
|
break;
|
|
case SerieType.Scatter:
|
|
needCreate = !(settings is ScatterSettings);
|
|
break;
|
|
case SerieType.Bar:
|
|
case SerieType.HorizontalBar:
|
|
needCreate = !(settings is BarSettings);
|
|
break;
|
|
case SerieType.Pie:
|
|
needCreate = !(settings is PieSettings);
|
|
break;
|
|
case SerieType.RingChart:
|
|
needCreate = !(settings is RingChartSettings);
|
|
break;
|
|
case SerieType.Pie3D:
|
|
if (SerieSettingsRegistry.HasFactory(SerieType.Pie3D))
|
|
{
|
|
if (!(settings is PieSettings))
|
|
{
|
|
needCreate = true;
|
|
}
|
|
else if (SerieSettingsRegistry.TryCreate(SerieType.Pie3D, out var created3D))
|
|
{
|
|
needCreate = created3D != null && created3D.GetType() != settings.GetType();
|
|
}
|
|
else
|
|
{
|
|
needCreate = false;
|
|
}
|
|
}
|
|
else needCreate = false;
|
|
break;
|
|
case SerieType.Radar:
|
|
needCreate = !(settings is RadarSettings);
|
|
break;
|
|
case SerieType.Heatmap:
|
|
needCreate = !(settings is HeatmapSettings);
|
|
break;
|
|
default:
|
|
if (SerieSettingsRegistry.HasFactory(type))
|
|
{
|
|
if (settings == null)
|
|
{
|
|
needCreate = true;
|
|
}
|
|
else if (SerieSettingsRegistry.TryCreate(type, out var createdAny))
|
|
{
|
|
needCreate = createdAny != null && createdAny.GetType() != settings.GetType();
|
|
}
|
|
else
|
|
{
|
|
needCreate = false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If the type enum changed (or data was migrated) before we got a chance to cache,
|
|
// avoid losing the previous settings instance by stashing it into the matching cache.
|
|
if (needCreate && settings != null)
|
|
{
|
|
if (settings is LineSettings) _cachedLineSettings = settings;
|
|
else if (settings is BarSettings) _cachedBarSettings = settings;
|
|
else if (settings is RingChartSettings) _cachedRingChartSettings = settings;
|
|
else if (settings is PieSettings) _cachedPieSettings = settings;
|
|
else if (settings is ScatterSettings) _cachedScatterSettings = settings;
|
|
else if (settings is RadarSettings) _cachedRadarSettings = settings;
|
|
else if (settings is HeatmapSettings) _cachedHeatmapSettings = settings;
|
|
}
|
|
|
|
if (needCreate)
|
|
{
|
|
switch (type)
|
|
{
|
|
case SerieType.Line:
|
|
settings = _cachedLineSettings is LineSettings cachedLine ? cachedLine : new LineSettings();
|
|
break;
|
|
case SerieType.Scatter:
|
|
settings = _cachedScatterSettings is ScatterSettings cachedScatter ? cachedScatter : new ScatterSettings();
|
|
break;
|
|
case SerieType.Bar:
|
|
case SerieType.HorizontalBar:
|
|
settings = _cachedBarSettings is BarSettings cachedBar ? cachedBar : new BarSettings();
|
|
break;
|
|
case SerieType.Pie:
|
|
settings = _cachedPieSettings is PieSettings cachedPie ? cachedPie : new PieSettings();
|
|
break;
|
|
case SerieType.RingChart:
|
|
settings = _cachedRingChartSettings is RingChartSettings cachedRing ? cachedRing : new RingChartSettings();
|
|
break;
|
|
case SerieType.Pie3D:
|
|
if (SerieSettingsRegistry.TryCreate(type, out var created3D))
|
|
{
|
|
if (created3D is PieSettings createdPie && _cachedPieSettings is PieSettings cachedPieFor3D)
|
|
{
|
|
if (cachedPieFor3D.layout != null) createdPie.layout = cachedPieFor3D.layout;
|
|
if (cachedPieFor3D.hover != null) createdPie.hover = cachedPieFor3D.hover;
|
|
if (cachedPieFor3D.aggregation != null) createdPie.aggregation = cachedPieFor3D.aggregation;
|
|
if (cachedPieFor3D.ring != null) createdPie.ring = cachedPieFor3D.ring;
|
|
}
|
|
settings = created3D;
|
|
}
|
|
else settings = null;
|
|
break;
|
|
case SerieType.Radar:
|
|
settings = _cachedRadarSettings is RadarSettings cachedRadar ? cachedRadar : new RadarSettings();
|
|
break;
|
|
case SerieType.Heatmap:
|
|
settings = _cachedHeatmapSettings is HeatmapSettings cachedHeatmap ? cachedHeatmap : new HeatmapSettings();
|
|
break;
|
|
default:
|
|
if (SerieSettingsRegistry.TryCreate(type, out var createdAny))
|
|
{
|
|
settings = createdAny;
|
|
}
|
|
else
|
|
{
|
|
settings = null;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (type == SerieType.Scatter && settings is ScatterSettings ss)
|
|
{
|
|
if (ss.point == null) ss.point = new PointSettings();
|
|
if (ss.sizeMapping == null) ss.sizeMapping = new SizeMappingSettings();
|
|
if (ss.hover == null) ss.hover = new HoverHighlightSettings();
|
|
}
|
|
|
|
if (type == SerieType.Line && settings is LineSettings ls)
|
|
{
|
|
if (ls.stroke == null) ls.stroke = new LineStrokeSettings();
|
|
if (ls.point == null) ls.point = new PointSettings();
|
|
if (ls.area == null) ls.area = new AreaFillSettings();
|
|
}
|
|
|
|
if (type == SerieType.Bar && settings is BarSettings bs)
|
|
{
|
|
if (bs.border == null) bs.border = new BorderSettings();
|
|
if (bs.background == null) bs.background = new BackgroundSettings();
|
|
}
|
|
|
|
if (type == SerieType.Pie && settings is PieSettings ps)
|
|
{
|
|
if (ps.layout == null) ps.layout = new PieLayoutSettings();
|
|
if (ps.hover == null) ps.hover = new PieHoverSettings();
|
|
if (ps.aggregation == null) ps.aggregation = new PieAggregationSettings();
|
|
if (ps.ring == null) ps.ring = new RingSettings();
|
|
}
|
|
|
|
if (type == SerieType.RingChart && settings is RingChartSettings rcs)
|
|
{
|
|
if (rcs.layout == null) rcs.layout = new RingChartLayoutSettings();
|
|
if (rcs.hover == null) rcs.hover = new PieHoverSettings();
|
|
if (rcs.legend == null) rcs.legend = new PieLegendSettings();
|
|
}
|
|
|
|
if (type == SerieType.Pie3D && settings is PieSettings ps3d)
|
|
{
|
|
if (ps3d.layout == null) ps3d.layout = new PieLayoutSettings();
|
|
if (ps3d.hover == null) ps3d.hover = new PieHoverSettings();
|
|
if (ps3d.aggregation == null) ps3d.aggregation = new PieAggregationSettings();
|
|
if (ps3d.ring == null) ps3d.ring = new RingSettings();
|
|
}
|
|
|
|
if (type == SerieType.Radar && settings is RadarSettings rs)
|
|
{
|
|
if (rs.stroke == null) rs.stroke = new LineStrokeSettings();
|
|
if (rs.point == null) rs.point = new PointSettings();
|
|
}
|
|
|
|
if (type == SerieType.Heatmap && settings is HeatmapSettings hs)
|
|
{
|
|
if (hs.cellGapPx < 0f) hs.cellGapPx = 0f;
|
|
}
|
|
|
|
if (seriesData == null) seriesData = new List<SeriesData>();
|
|
}
|
|
}
|
|
}
|