From 14023cc713ef42aea6262ce4d9d9754a6ac9bc1b Mon Sep 17 00:00:00 2001 From: monitor1394 Date: Mon, 6 Jul 2020 08:41:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0`LiquidChart`=E6=B0=B4?= =?UTF-8?q?=E4=BD=8D=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + Editor/LiquidChartEditor.cs | 34 +++ Editor/LiquidChartEditor.cs.meta | 11 + Editor/PropertyDrawers/SerieDrawer.cs | 31 +++ Editor/PropertyDrawers/VesselDrawer.cs | 68 +++++ Editor/PropertyDrawers/VesselDrawer.cs.meta | 11 + Editor/XChartEditor.cs | 7 + Runtime/API/LiquidChart_API.cs | 61 +++++ Runtime/API/LiquidChart_API.cs.meta | 11 + Runtime/Component/Main/Serie.cs | 53 ++++ Runtime/Component/Main/Vessel.cs | 176 +++++++++++++ Runtime/Component/Main/Vessel.cs.meta | 11 + Runtime/GaugeChart.cs | 2 +- Runtime/Internal/BaseChart.cs | 2 +- Runtime/Internal/Helper/SerieHelper.cs | 1 + Runtime/Internal/Helper/SerieLabelHelper.cs | 29 ++- Runtime/Internal/Helper/SeriesHelper.cs | 9 + Runtime/Internal/Helper/VesselHelper.cs | 39 +++ Runtime/Internal/Helper/VesselHelper.cs.meta | 11 + Runtime/LiquidChart.cs | 253 +++++++++++++++++++ Runtime/LiquidChart.cs.meta | 11 + Runtime/RingChart.cs | 4 +- Runtime/Utility/ChartHelper.cs | 16 ++ 23 files changed, 847 insertions(+), 5 deletions(-) create mode 100644 Editor/LiquidChartEditor.cs create mode 100644 Editor/LiquidChartEditor.cs.meta create mode 100644 Editor/PropertyDrawers/VesselDrawer.cs create mode 100644 Editor/PropertyDrawers/VesselDrawer.cs.meta create mode 100644 Runtime/API/LiquidChart_API.cs create mode 100644 Runtime/API/LiquidChart_API.cs.meta create mode 100644 Runtime/Component/Main/Vessel.cs create mode 100644 Runtime/Component/Main/Vessel.cs.meta create mode 100644 Runtime/Internal/Helper/VesselHelper.cs create mode 100644 Runtime/Internal/Helper/VesselHelper.cs.meta create mode 100644 Runtime/LiquidChart.cs create mode 100644 Runtime/LiquidChart.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eb1b21a..30dd12fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 更新日志 +* (2020.07.06) 增加`LiquidChart`水位图 * (2020.07.01) 增加`PolarChart`极坐标图表 * (2020.06.25) 发布`v1.5.2`版本 * (2020.06.25) 修复`BarChart`在数值为`0`时还会绘制一小部分柱条的问题 diff --git a/Editor/LiquidChartEditor.cs b/Editor/LiquidChartEditor.cs new file mode 100644 index 00000000..874436da --- /dev/null +++ b/Editor/LiquidChartEditor.cs @@ -0,0 +1,34 @@ +/******************************************/ +/* */ +/* Copyright (c) 2018 monitor1394 */ +/* https://github.com/monitor1394 */ +/* */ +/******************************************/ + +using UnityEditor; + +namespace XCharts +{ + /// + /// Editor class used to edit UI LiquidChart. + /// + + [CustomEditor(typeof(LiquidChart), false)] + public class LiquidChartEditor : BaseChartEditor + { + protected SerializedProperty m_Vessels; + + protected override void OnEnable() + { + base.OnEnable(); + m_Target = (LiquidChart)target; + m_Vessels = serializedObject.FindProperty("m_Vessels"); + } + + protected override void OnStartInspectorGUI() + { + base.OnStartInspectorGUI(); + EditorGUILayout.PropertyField(m_Vessels, true); + } + } +} \ No newline at end of file diff --git a/Editor/LiquidChartEditor.cs.meta b/Editor/LiquidChartEditor.cs.meta new file mode 100644 index 00000000..b96a37c4 --- /dev/null +++ b/Editor/LiquidChartEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 307a1578a6be1403c98fdc27d99d1808 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/PropertyDrawers/SerieDrawer.cs b/Editor/PropertyDrawers/SerieDrawer.cs index 7d6c7e62..c7cb36bc 100644 --- a/Editor/PropertyDrawers/SerieDrawer.cs +++ b/Editor/PropertyDrawers/SerieDrawer.cs @@ -30,6 +30,7 @@ namespace XCharts SerializedProperty m_AxisIndex = prop.FindPropertyRelative("m_AxisIndex"); SerializedProperty m_RadarType = prop.FindPropertyRelative("m_RadarType"); SerializedProperty m_RadarIndex = prop.FindPropertyRelative("m_RadarIndex"); + SerializedProperty m_VesselIndex = prop.FindPropertyRelative("m_VesselIndex"); SerializedProperty m_MinShow = prop.FindPropertyRelative("m_MinShow"); SerializedProperty m_MaxShow = prop.FindPropertyRelative("m_MaxShow"); SerializedProperty m_MaxCache = prop.FindPropertyRelative("m_MaxCache"); @@ -78,6 +79,10 @@ namespace XCharts SerializedProperty m_Large = prop.FindPropertyRelative("m_Large"); SerializedProperty m_LargeThreshold = prop.FindPropertyRelative("m_LargeThreshold"); SerializedProperty m_AvoidLabelOverlap = prop.FindPropertyRelative("m_AvoidLabelOverlap"); + SerializedProperty m_WaveHeight = prop.FindPropertyRelative("m_WaveHeight"); + SerializedProperty m_WaveLength = prop.FindPropertyRelative("m_WaveLength"); + SerializedProperty m_WaveSpeed = prop.FindPropertyRelative("m_WaveSpeed"); + SerializedProperty m_WaveOffset = prop.FindPropertyRelative("m_WaveOffset"); SerializedProperty m_Datas = prop.FindPropertyRelative("m_Data"); int index = InitToggle(prop); @@ -322,6 +327,26 @@ namespace XCharts EditorGUI.PropertyField(drawRect, m_Emphasis); drawRect.y += EditorGUI.GetPropertyHeight(m_Emphasis); break; + case SerieType.Liquid: + EditorGUI.PropertyField(drawRect, m_VesselIndex); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_Min); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_Max); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_WaveLength); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_WaveHeight); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_WaveSpeed); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_WaveOffset); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_ItemStyle); + drawRect.y += EditorGUI.GetPropertyHeight(m_ItemStyle); + EditorGUI.PropertyField(drawRect, m_Label); + drawRect.y += EditorGUI.GetPropertyHeight(m_Label); + break; } EditorGUI.PropertyField(drawRect, m_Animation); drawRect.y += EditorGUI.GetPropertyHeight(m_Animation); @@ -589,6 +614,12 @@ namespace XCharts height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_Emphasis")); height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_Animation")); break; + case SerieType.Liquid: + height += 11 * EditorGUIUtility.singleLineHeight + 10 * EditorGUIUtility.standardVerticalSpacing; + height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_ItemStyle")); + height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_Label")); + height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_Animation")); + break; } if (m_DataFoldout[index]) { diff --git a/Editor/PropertyDrawers/VesselDrawer.cs b/Editor/PropertyDrawers/VesselDrawer.cs new file mode 100644 index 00000000..782c05de --- /dev/null +++ b/Editor/PropertyDrawers/VesselDrawer.cs @@ -0,0 +1,68 @@ +/******************************************/ +/* */ +/* Copyright (c) 2018 monitor1394 */ +/* https://github.com/monitor1394 */ +/* */ +/******************************************/ + +using UnityEditor; +using UnityEngine; + +namespace XCharts +{ + [CustomPropertyDrawer(typeof(Vessel), true)] + public class VesselDrawer : PropertyDrawer + { + private bool m_VesselModuleToggle = false; + + public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label) + { + Rect drawRect = pos; + drawRect.height = EditorGUIUtility.singleLineHeight; + SerializedProperty show = prop.FindPropertyRelative("m_Show"); + SerializedProperty m_Shape = prop.FindPropertyRelative("m_Shape"); + SerializedProperty m_Center = prop.FindPropertyRelative("m_Center"); + SerializedProperty m_Radius = prop.FindPropertyRelative("m_Radius"); + SerializedProperty m_ShapeWidth = prop.FindPropertyRelative("m_ShapeWidth"); + SerializedProperty m_Gap = prop.FindPropertyRelative("m_Gap"); + SerializedProperty m_Smoothness = prop.FindPropertyRelative("m_Smoothness"); + SerializedProperty m_AutoColor = prop.FindPropertyRelative("m_AutoColor"); + SerializedProperty m_Color = prop.FindPropertyRelative("m_Color"); + SerializedProperty m_BackgroundColor = prop.FindPropertyRelative("m_BackgroundColor"); + + int index = ChartEditorHelper.GetIndexFromPath(prop); + ChartEditorHelper.MakeFoldout(ref drawRect, ref m_VesselModuleToggle, "Vessel " + index, show); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + if (m_VesselModuleToggle) + { + EditorGUI.indentLevel++; + EditorGUI.PropertyField(drawRect, m_Shape); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_ShapeWidth); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_Gap); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + ChartEditorHelper.MakeTwoField(ref drawRect, pos.width, m_Center, "Center"); + EditorGUI.PropertyField(drawRect, m_Radius); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_BackgroundColor); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_Color); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_AutoColor); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_Smoothness); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.indentLevel--; + } + } + + public override float GetPropertyHeight(SerializedProperty prop, GUIContent label) + { + if (m_VesselModuleToggle) + return 10 * EditorGUIUtility.singleLineHeight + 9 * EditorGUIUtility.standardVerticalSpacing; + else + return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + } + } +} \ No newline at end of file diff --git a/Editor/PropertyDrawers/VesselDrawer.cs.meta b/Editor/PropertyDrawers/VesselDrawer.cs.meta new file mode 100644 index 00000000..514cb0b0 --- /dev/null +++ b/Editor/PropertyDrawers/VesselDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 744a68155f2f349dc8fe26536ec83f80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/XChartEditor.cs b/Editor/XChartEditor.cs index 3aa23e35..b3f967a2 100644 --- a/Editor/XChartEditor.cs +++ b/Editor/XChartEditor.cs @@ -134,5 +134,12 @@ namespace XCharts { AddChart("PolarChart"); } + + [MenuItem("XCharts/LiquidChart", priority = 53)] + [MenuItem("GameObject/XCharts/LiquidChart", priority = 53)] + public static void AddLiquidChart() + { + AddChart("LiquidChart"); + } } } \ No newline at end of file diff --git a/Runtime/API/LiquidChart_API.cs b/Runtime/API/LiquidChart_API.cs new file mode 100644 index 00000000..faec6f50 --- /dev/null +++ b/Runtime/API/LiquidChart_API.cs @@ -0,0 +1,61 @@ +/******************************************/ +/* */ +/* Copyright (c) 2018 monitor1394 */ +/* https://github.com/monitor1394 */ +/* */ +/******************************************/ + +using System.Collections.Generic; +using UnityEngine; + +namespace XCharts +{ + public partial class LiquidChart + { + /// + /// 容器组件列表。 + /// + public List vessels { get { return m_Vessels; } } + + /// + /// 移除所有容器组件。 + /// + public void RemoveVessel() + { + m_Vessels.Clear(); + } + + /// + /// 添加容器组件。 + /// + public void AddVessel(Vessel vessel) + { + m_Vessels.Add(vessel); + } + + /// + /// 添加容器组件。 + /// + public Vessel AddVessel(Vessel.Shape shape, Vector2 center, float radius) + { + var vessel = new Vessel(); + vessel.shape = shape; + vessel.radius = radius; + vessel.center[0] = center.x; + vessel.center[1] = center.y; + AddVessel(vessel); + return vessel; + } + + /// + /// 获得指定索引的容器组件。 + /// + /// + /// + public Vessel GetVessel(int vesselIndex) + { + if (vesselIndex < 0 || vesselIndex > m_Vessels.Count - 1) return null; + return m_Vessels[vesselIndex]; + } + } +} \ No newline at end of file diff --git a/Runtime/API/LiquidChart_API.cs.meta b/Runtime/API/LiquidChart_API.cs.meta new file mode 100644 index 00000000..631f910e --- /dev/null +++ b/Runtime/API/LiquidChart_API.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd14dec4102b848f699bbf42babbe4c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Component/Main/Serie.cs b/Runtime/Component/Main/Serie.cs index 9b20269d..790265db 100644 --- a/Runtime/Component/Main/Serie.cs +++ b/Runtime/Component/Main/Serie.cs @@ -56,6 +56,10 @@ namespace XCharts /// 环形图。只支持一个数据的环形图。 /// Ring, + /// + /// 水位图。 + /// + Liquid, } /// @@ -218,6 +222,7 @@ namespace XCharts [SerializeField] private string m_Stack; [SerializeField] [Range(0, 1)] private int m_AxisIndex = 0; [SerializeField] private int m_RadarIndex = 0; + [SerializeField] private int m_VesselIndex = 0; [SerializeField] protected int m_MinShow; [SerializeField] protected int m_MaxShow; [SerializeField] protected int m_MaxCache; @@ -274,6 +279,10 @@ namespace XCharts [SerializeField] private bool m_Large = true; [SerializeField] private int m_LargeThreshold = 200; [SerializeField] private bool m_AvoidLabelOverlap = false; + [SerializeField] private float m_WaveHeight = 10f; + [SerializeField] private float m_WaveLength = 20f; + [SerializeField] private float m_WaveSpeed = 5f; + [SerializeField] private float m_WaveOffset = 0f; [SerializeField] private RadarType m_RadarType = RadarType.Multiple; [SerializeField] private List m_Data = new List(); @@ -347,6 +356,15 @@ namespace XCharts set { if (PropertyUtility.SetStruct(ref m_RadarIndex, value)) SetVerticesDirty(); } } /// + /// Index of vesel component that liquid chart uses. + /// 水位图所使用的 vessel 组件的 index。 + /// + public int vesselIndex + { + get { return m_VesselIndex; } + set { if (PropertyUtility.SetStruct(ref m_VesselIndex, value)) SetVerticesDirty(); } + } + /// /// The min number of data to show in chart. /// 系列所显示数据的最小索引 /// @@ -796,6 +814,39 @@ namespace XCharts set { if (PropertyUtility.SetStruct(ref m_AvoidLabelOverlap, value)) SetVerticesDirty(); } } /// + /// Wave length of the wave, which is relative to the diameter. + /// 波长。为0-1小数时指直线的百分比。 + /// + public float waveLength + { + get { return m_WaveLength; } + set { if (PropertyUtility.SetStruct(ref m_WaveLength, value)) SetVerticesDirty(); } + } + /// + /// 波高。 + /// + public float waveHeight + { + get { return m_WaveHeight; } + set { if (PropertyUtility.SetStruct(ref m_WaveHeight, value)) SetVerticesDirty(); } + } + /// + /// 波偏移。 + /// + public float waveOffset + { + get { return m_WaveOffset; } + set { if (PropertyUtility.SetStruct(ref m_WaveOffset, value)) SetVerticesDirty(); } + } + /// + /// 波速。正数时左移,负数时右移。 + /// + public float waveSpeed + { + get { return m_WaveSpeed; } + set { if (PropertyUtility.SetStruct(ref m_WaveSpeed, value)) SetVerticesDirty(); } + } + /// /// 系列中的数据内容数组。SerieData可以设置1到n维数据。 /// public List data { get { return m_Data; } } @@ -891,7 +942,9 @@ namespace XCharts /// 饼图的数据项之和 /// public float runtimePieDataTotal { get; internal set; } + public float runtimeWaveSpeed { get; internal set; } internal int runtimeLastCheckDataCount { get; set; } + internal float runtimeCheckValue { get; set; } public bool nameDirty { get { return m_NameDirty; } } private void SetNameDirty() diff --git a/Runtime/Component/Main/Vessel.cs b/Runtime/Component/Main/Vessel.cs new file mode 100644 index 00000000..e9a898cd --- /dev/null +++ b/Runtime/Component/Main/Vessel.cs @@ -0,0 +1,176 @@ +/******************************************/ +/* */ +/* Copyright (c) 2018 monitor1394 */ +/* https://github.com/monitor1394 */ +/* */ +/******************************************/ + +using System; +using UnityEngine; + +namespace XCharts +{ + /// + /// Vessel component for liquid chart. + /// + /// 容器组件。 + /// 一般用于LiquidChart。 + /// + /// + [Serializable] + public class Vessel : MainComponent + { + public enum Shape + { + /// + /// 圆形 + /// + Circle, + /// + /// 正方形。 + /// + Rect, + /// + /// 三角形。 + /// + Triangle, + /// + /// 菱形。 + /// + Diamond, + /// + /// 不显示标记。 + /// + None, + } + [SerializeField] private bool m_Show = true; + [SerializeField] private Shape m_Shape = Shape.Circle; + [SerializeField] private float m_ShapeWidth = 5f; + [SerializeField] private float m_Gap = 10f; + [SerializeField] private Color m_Color; + [SerializeField] private Color m_BackgroundColor; + [SerializeField] private bool m_AutoColor = true; + [SerializeField] private float[] m_Center = new float[2] { 0.5f, 0.5f }; + [SerializeField] private float m_Radius = 0.5f; + [SerializeField] [Range(0.5f, 10f)] private float m_Smoothness = 1f; + + /// + /// Whether to show the grid in rectangular coordinate. + /// 是否显示直角坐标系网格。 + /// + public bool show + { + get { return m_Show; } + set { if (PropertyUtility.SetStruct(ref m_Show, value)) SetVerticesDirty(); } + } + /// + /// 形状。 + /// + public Shape shape + { + get { return m_Shape; } + set { if (PropertyUtility.SetStruct(ref m_Shape, value)) SetVerticesDirty(); } + } + /// + /// 容器宽度。 + /// + public float shapeWidth + { + get { return m_ShapeWidth; } + set { if (PropertyUtility.SetStruct(ref m_ShapeWidth, value)) SetVerticesDirty(); } + } + /// + /// 间隙 + /// + public float gap + { + get { return m_Gap; } + set { if (PropertyUtility.SetStruct(ref m_Gap, value)) SetVerticesDirty(); } + } + /// + /// 中心点。数组的第一项是横坐标,第二项是纵坐标。 + /// 当值为0-1之间时表示百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高度。 + /// + public float[] center + { + get { return m_Center; } + set { if (value != null) { m_Center = value; SetAllDirty(); } } + } + /// + /// 半径。 + /// + public float radius + { + get { return m_Radius; } + set { if (PropertyUtility.SetStruct(ref m_Radius, value)) SetAllDirty(); } + } + /// + /// 水波平滑度。 + /// + public float smoothness + { + get { return m_Smoothness; } + set { if (PropertyUtility.SetStruct(ref m_Smoothness, value)) SetAllDirty(); } + } + /// + /// Background color of polar, which is transparent by default. + /// 背景色,默认透明。 + /// + public Color backgroundColor + { + get { return m_BackgroundColor; } + set { if (PropertyUtility.SetColor(ref m_BackgroundColor, value)) SetVerticesDirty(); } + } + /// + /// 容器颜色。默认和serie一致。 + /// + public Color color + { + get { return m_Color; } + set { if (PropertyUtility.SetColor(ref m_Color, value)) SetVerticesDirty(); } + } + /// + /// 是否自动颜色。为true时颜色会和serie一致。 + /// + public bool autoColor + { + get { return m_AutoColor; } + set { if (PropertyUtility.SetStruct(ref m_AutoColor, value)) SetVerticesDirty(); } + } + public int index { get; internal set; } + /// + /// the runtime center position of vessel. + /// 运行时中心点。 + /// + public Vector3 runtimeCenterPos { get; internal set; } + /// + /// the runtime radius of vessel. + /// 运行时半径。 + /// + public float runtimeRadius { get; internal set; } + /// + /// 运行时内半径。 + /// + public float runtimeInnerRadius { get; internal set; } + public static Vessel defaultVessel + { + get + { + var vessel = new Vessel + { + m_Show = true, + m_Shape = Shape.Circle, + m_ShapeWidth = 5, + m_Gap = 10, + m_Radius = 0.35f, + m_AutoColor = true, + m_Color = new Color32(70, 70, 240, 255), + m_Smoothness = 1 + }; + vessel.center[0] = 0.5f; + vessel.center[1] = 0.45f; + return vessel; + } + } + } +} \ No newline at end of file diff --git a/Runtime/Component/Main/Vessel.cs.meta b/Runtime/Component/Main/Vessel.cs.meta new file mode 100644 index 00000000..1e991d25 --- /dev/null +++ b/Runtime/Component/Main/Vessel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 04afad352c62a405691c66f18c3f9db7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/GaugeChart.cs b/Runtime/GaugeChart.cs index fff2cad4..fdbdf92e 100644 --- a/Runtime/GaugeChart.cs +++ b/Runtime/GaugeChart.cs @@ -49,7 +49,7 @@ namespace XCharts if (m_UpdateLabelText) { m_UpdateLabelText = false; - SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo); + SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo, m_LegendRealShowName); UpdateAxisLabel(); } } diff --git a/Runtime/Internal/BaseChart.cs b/Runtime/Internal/BaseChart.cs index 1a3210b2..97a49c49 100644 --- a/Runtime/Internal/BaseChart.cs +++ b/Runtime/Internal/BaseChart.cs @@ -446,7 +446,7 @@ namespace XCharts count++; } } - SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo); + SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo, m_LegendRealShowName); } protected void AddSerieLabel(Serie serie, SerieData serieData, int count = -1) diff --git a/Runtime/Internal/Helper/SerieHelper.cs b/Runtime/Internal/Helper/SerieHelper.cs index 97dd2d49..90a7f8f4 100644 --- a/Runtime/Internal/Helper/SerieHelper.cs +++ b/Runtime/Internal/Helper/SerieHelper.cs @@ -44,6 +44,7 @@ namespace XCharts internal static Color GetItemColor(Serie serie, SerieData serieData, ThemeInfo theme, int index, bool highlight) { + if (serie == null) return Color.clear; if (highlight) { var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData); diff --git a/Runtime/Internal/Helper/SerieLabelHelper.cs b/Runtime/Internal/Helper/SerieLabelHelper.cs index abf94ff9..63d8724b 100644 --- a/Runtime/Internal/Helper/SerieLabelHelper.cs +++ b/Runtime/Internal/Helper/SerieLabelHelper.cs @@ -4,6 +4,7 @@ /* https://github.com/monitor1394 */ /* */ /******************************************/ +using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; @@ -41,11 +42,12 @@ namespace XCharts } } - public static void UpdateLabelText(Series series, ThemeInfo themeInfo) + public static void UpdateLabelText(Series series, ThemeInfo themeInfo, List legendRealShowName) { foreach (var serie in series.list) { if (!serie.label.show) continue; + var colorIndex = legendRealShowName.IndexOf(serie.name); switch (serie.type) { case SerieType.Gauge: @@ -54,6 +56,9 @@ namespace XCharts case SerieType.Ring: SetRingLabelText(serie, themeInfo); break; + case SerieType.Liquid: + SetLiquidLabelText(serie, themeInfo, colorIndex); + break; } } } @@ -176,6 +181,28 @@ namespace XCharts } } + private static void SetLiquidLabelText(Serie serie, ThemeInfo themeInfo, int colorIndex) + { + var serieData = serie.GetSerieData(0); + if (serieData == null) return; + var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.highlighted); + if (serieLabel.show && serieData.labelObject != null) + { + if (!serie.show || !serieData.show) + { + serieData.SetLabelActive(false); + return; + } + var value = serieData.GetData(1); + var total = serie.max - serie.min; + var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total); + serieData.SetLabelActive(true); + serieData.labelObject.SetText(content); + serieData.labelObject.SetLabelColor(GetLabelColor(serie, themeInfo, colorIndex)); + serieData.labelObject.SetLabelPosition(serieData.labelPosition + serieLabel.offset); + } + } + public static void UpdatePieLabelPosition(Serie serie, SerieData serieData) { if (serieData.labelObject == null) return; diff --git a/Runtime/Internal/Helper/SeriesHelper.cs b/Runtime/Internal/Helper/SeriesHelper.cs index db5c5227..2e57f4ef 100644 --- a/Runtime/Internal/Helper/SeriesHelper.cs +++ b/Runtime/Internal/Helper/SeriesHelper.cs @@ -191,6 +191,15 @@ namespace XCharts return GetLastStackSerie(series, serie); } + internal static Serie GetSerieByVesselIndex(Series series, int vesselIndex) + { + foreach (var serie in series.list) + { + if (serie.vesselIndex == vesselIndex) return serie; + } + return null; + } + /// /// 是否由系列在用指定索引的axis /// diff --git a/Runtime/Internal/Helper/VesselHelper.cs b/Runtime/Internal/Helper/VesselHelper.cs new file mode 100644 index 00000000..179920b1 --- /dev/null +++ b/Runtime/Internal/Helper/VesselHelper.cs @@ -0,0 +1,39 @@ +/******************************************/ +/* */ +/* Copyright (c) 2018 monitor1394 */ +/* https://github.com/monitor1394 */ +/* */ +/******************************************/ + +using System.Collections.Generic; +using UnityEngine; + +namespace XCharts +{ + public static class VesselHelper + { + internal static Color GetColor(Vessel vessel, Serie serie, ThemeInfo themeInfo, List legendRealShowName) + { + if (serie != null && vessel.autoColor) + { + var colorIndex = legendRealShowName.IndexOf(serie.name); + return SerieHelper.GetItemColor(serie, null, themeInfo, colorIndex, false); + } + else + { + return vessel.color; + } + } + + internal static void UpdateVesselCenter(Vessel vessel, Vector3 chartPosition, float chartWidth, float chartHeight) + { + if (vessel.center.Length < 2) return; + var centerX = vessel.center[0] <= 1 ? chartWidth * vessel.center[0] : vessel.center[0]; + var centerY = vessel.center[1] <= 1 ? chartHeight * vessel.center[1] : vessel.center[1]; + var checkWidth = Mathf.Min(chartWidth, chartHeight); + vessel.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY); + vessel.runtimeRadius = ChartHelper.GetRuntimeRelativeOrAbsoluteValue(vessel.radius, checkWidth); + vessel.runtimeInnerRadius = vessel.runtimeRadius - vessel.shapeWidth - vessel.gap; + } + } +} \ No newline at end of file diff --git a/Runtime/Internal/Helper/VesselHelper.cs.meta b/Runtime/Internal/Helper/VesselHelper.cs.meta new file mode 100644 index 00000000..33e9dfa9 --- /dev/null +++ b/Runtime/Internal/Helper/VesselHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0c82cb73437a4004bf946cf4dcaa567 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/LiquidChart.cs b/Runtime/LiquidChart.cs new file mode 100644 index 00000000..2bec8f9a --- /dev/null +++ b/Runtime/LiquidChart.cs @@ -0,0 +1,253 @@ +using System.Linq; + +/******************************************/ +/* */ +/* Copyright (c) 2018 monitor1394 */ +/* https://github.com/monitor1394 */ +/* */ +/******************************************/ + +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace XCharts +{ + /// + /// 水位图 + /// + [AddComponentMenu("XCharts/LiquidChart", 22)] + [ExecuteInEditMode] + [RequireComponent(typeof(RectTransform))] + [DisallowMultipleComponent] + public partial class LiquidChart : BaseChart + { + [SerializeField] private List m_Vessels = new List(); + private bool m_UpdateLabelText = false; + + protected override void Awake() + { + base.Awake(); + UpdateRuntimeValue(); + SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo, m_LegendRealShowName); + } + +#if UNITY_EDITOR + protected override void Reset() + { + base.Reset(); + m_Title.text = "LiquidChart"; + RemoveData(); + RemoveVessel(); + AddVessel(Vessel.defaultVessel); + var serie = AddSerie(SerieType.Liquid, "serie1"); + serie.min = 0; + serie.max = 100; + serie.label.show = true; + serie.label.fontSize = 40; + serie.label.formatter = "{d}%"; + serie.label.color = new Color32(70, 70, 240, 255); + AddData(0, UnityEngine.Random.Range(0, 100)); + } + + protected override void OnValidate() + { + base.OnValidate(); + RefreshChart(); + } +#endif + + protected override void OnSizeChanged() + { + base.OnSizeChanged(); + UpdateRuntimeValue(); + m_UpdateLabelText = true; + } + + protected override void Update() + { + base.Update(); + if (m_UpdateLabelText) + { + m_UpdateLabelText = false; + SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo, m_LegendRealShowName); + } + } + + protected override void DrawChart(VertexHelper vh) + { + base.DrawChart(vh); + UpdateRuntimeValue(); + DrawVesselBackground(vh); + DrawSeries(vh); + DrawVessel(vh); + } + + private void UpdateRuntimeValue() + { + for (int i = 0; i < m_Vessels.Count; i++) + { + var vessel = m_Vessels[i]; + vessel.index = i; + VesselHelper.UpdateVesselCenter(vessel, m_ChartPosition, m_ChartWidth, m_ChartHeight); + } + } + + private void DrawVesselBackground(VertexHelper vh) + { + for (int i = 0; i < m_Vessels.Count; i++) + { + var vessel = m_Vessels[i]; + if (vessel.backgroundColor.a != 0) + { + var cenPos = vessel.runtimeCenterPos; + var radius = vessel.runtimeRadius; + var serie = SeriesHelper.GetSerieByVesselIndex(m_Series, vessel.index); + ChartDrawer.DrawCricle(vh, cenPos, vessel.runtimeInnerRadius, vessel.backgroundColor, m_Settings.cicleSmoothness); + } + } + } + + private void DrawVessel(VertexHelper vh) + { + for (int i = 0; i < m_Vessels.Count; i++) + { + var vessel = m_Vessels[i]; + vessel.index = i; + DrawCirleVessel(vh, vessel); + } + } + + private void DrawCirleVessel(VertexHelper vh, Vessel vessel) + { + var cenPos = vessel.runtimeCenterPos; + var radius = vessel.runtimeRadius; + var serie = SeriesHelper.GetSerieByVesselIndex(m_Series, vessel.index); + var vesselColor = VesselHelper.GetColor(vessel, serie, m_ThemeInfo, m_LegendRealShowName); + ChartDrawer.DrawDoughnut(vh, cenPos, radius - vessel.shapeWidth, radius, vesselColor, Color.clear, m_Settings.cicleSmoothness); + } + + private void DrawSeries(VertexHelper vh) + { + for (int i = 0; i < m_Series.Count; i++) + { + var serie = m_Series.GetSerie(i); + if (!serie.show) continue; + DrawSerie(vh, serie); + } + } + + private void DrawSerie(VertexHelper vh, Serie serie) + { + var vessel = GetVessel(serie.vesselIndex); + if (vessel == null) return; + var cenPos = vessel.runtimeCenterPos; + var radius = vessel.runtimeInnerRadius; + var serieData = serie.GetSerieData(0); + if (serieData == null) return; + + var value = serieData.GetData(1); + if (serie.runtimeCheckValue != value) + { + serie.runtimeCheckValue = value; + m_UpdateLabelText = true; + } + if (serieData.labelPosition != cenPos) + { + serieData.labelPosition = cenPos; + m_UpdateLabelText = true; + } + if (value == 0) return; + var colorIndex = m_LegendRealShowName.IndexOf(serie.name); + + var realHig = (value - serie.min) / (serie.max - serie.min) * radius * 2; + serie.animation.InitProgress(1, 0, realHig); + + var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail(); + var a = Mathf.Abs(radius - hig + (hig > radius ? serie.waveHeight : -serie.waveHeight)); + var diff = Mathf.Sqrt(radius * radius - Mathf.Pow(a, 2)); + + var color = SerieHelper.GetItemColor(serie, serieData, m_ThemeInfo, colorIndex, false); + var toColor = SerieHelper.GetItemToColor(serie, serieData, m_ThemeInfo, colorIndex, false); + + if (hig >= 2 * radius) + { + ChartDrawer.DrawCricle(vh, cenPos, radius, toColor, m_Settings.cicleSmoothness); + } + else + { + var startY = cenPos.y - radius + hig; + var waveStartPos = new Vector3(cenPos.x - diff, startY); + var waveEndPos = new Vector3(cenPos.x + diff, startY); + var startX = hig > radius ? cenPos.x - radius : waveStartPos.x; + var endX = hig > radius ? cenPos.x + radius : waveEndPos.x; + + var step = vessel.smoothness; + if (step < 0.5f) step = 0.5f; + var lup = hig > radius ? new Vector3(cenPos.x - radius, cenPos.y) : waveStartPos; + var ldp = lup; + var nup = Vector3.zero; + var ndp = Vector3.zero; + var angle = 0f; + serie.runtimeWaveSpeed += serie.waveSpeed * Time.deltaTime; + var isStarted = false; + var isEnded = false; + while (startX < endX) + { + startX += step; + if (startX > endX) startX = endX; + if (startX > waveStartPos.x && !isStarted) + { + startX = waveStartPos.x; + isStarted = true; + } + if (startX > waveEndPos.x && !isEnded) + { + startX = waveEndPos.x; + isEnded = true; + } + var py = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2)); + if (startX < waveStartPos.x || startX > waveEndPos.x) + { + nup = new Vector3(startX, cenPos.y + py); + } + else + { + var py2 = serie.waveHeight * Mathf.Sin(1 / serie.waveLength * angle + serie.runtimeWaveSpeed + serie.waveOffset); + var nupY = waveStartPos.y + py2; + if (nupY > cenPos.y + py) nupY = cenPos.y + py; + else if (nupY < cenPos.y - py) nupY = cenPos.y - py; + nup = new Vector3(startX, nupY); + angle += step; + } + ndp = new Vector3(startX, cenPos.y - py); + if (!ChartHelper.IsValueEqualsColor(color, toColor)) + { + var colorMin = cenPos.y - radius; + var colorMax = startY + serie.waveHeight; + var tcolor1 = Color.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin)); + var tcolor2 = Color.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin)); + ChartDrawer.DrawPolygon(vh, lup, nup, ndp, ldp, tcolor1, tcolor2); + } + else + { + ChartDrawer.DrawPolygon(vh, lup, nup, ndp, ldp, color); + } + lup = nup; + ldp = ndp; + } + } + + if (serie.waveSpeed != 0 && Application.isPlaying) + { + RefreshChart(); + } + if (!serie.animation.IsFinish()) + { + serie.animation.CheckProgress(realHig); + m_IsPlayingAnimation = true; + RefreshChart(); + } + } + } +} diff --git a/Runtime/LiquidChart.cs.meta b/Runtime/LiquidChart.cs.meta new file mode 100644 index 00000000..c80a4829 --- /dev/null +++ b/Runtime/LiquidChart.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41f7e109291bd44de96fccf526e9c7f1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/RingChart.cs b/Runtime/RingChart.cs index 92500915..6442d92f 100644 --- a/Runtime/RingChart.cs +++ b/Runtime/RingChart.cs @@ -34,7 +34,7 @@ namespace XCharts if (m_UpdateLabelText) { m_UpdateLabelText = false; - SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo); + SerieLabelHelper.UpdateLabelText(m_Series, m_ThemeInfo, m_LegendRealShowName); } } @@ -331,7 +331,7 @@ namespace XCharts if (index < 0) continue; showTooltip = true; var content = TooltipHelper.GetFormatterContent(m_Tooltip, index, m_Series, m_ThemeInfo); - TooltipHelper.SetContentAndPosition(tooltip,content,chartRect); + TooltipHelper.SetContentAndPosition(tooltip, content, chartRect); } m_Tooltip.SetActive(showTooltip); } diff --git a/Runtime/Utility/ChartHelper.cs b/Runtime/Utility/ChartHelper.cs index fb54b384..ff41173b 100644 --- a/Runtime/Utility/ChartHelper.cs +++ b/Runtime/Utility/ChartHelper.cs @@ -792,5 +792,21 @@ namespace XCharts return new Vector3(-dire.y / dire.x, 1, 0).normalized; } } + + public static float GetRuntimeRelativeOrAbsoluteValue(float check, float total) + { + if (check <= 0) + { + return 0; + } + else if (check <= 1) + { + return total * check; + } + else + { + return check; + } + } } } \ No newline at end of file