增加GanttChart甘特图

This commit is contained in:
monitor1394
2021-03-25 12:55:52 +08:00
parent 6a548899fa
commit ac64bd9435
54 changed files with 38355 additions and 6917 deletions

View File

@@ -32,6 +32,7 @@
## Latest ## Latest
* (2021.03.25) Added `Ganttchart`
* (2021.03.22) Added `Theme` `Unbind` button to unbind theme when copying chart #118 * (2021.03.22) Added `Theme` `Unbind` button to unbind theme when copying chart #118
* (2021.03.18) Fixed an issue where the check box after `Foldout` in `Inspector` could not be checked * (2021.03.18) Fixed an issue where the check box after `Foldout` in `Inspector` could not be checked
* (2021.03.18) Fixed an issue with `BarChart` displaying an exception in the `0` value * (2021.03.18) Fixed an issue with `BarChart` displaying an exception in the `0` value

View File

@@ -32,6 +32,7 @@
## Latest ## Latest
* (2021.03.25) 增加`GanttChart`甘特图
* (2021.03.22) 增加`Theme``Unbind`按钮用于解绑复制图表时的主题 #118 * (2021.03.22) 增加`Theme``Unbind`按钮用于解绑复制图表时的主题 #118
* (2021.03.18) 修复`Inspector``Foldout`后的勾选框无法选中的问题 * (2021.03.18) 修复`Inspector``Foldout`后的勾选框无法选中的问题
* (2021.03.18) 修复`BarChart``0`数值时显示异常的问题 * (2021.03.18) 修复`BarChart``0`数值时显示异常的问题

View File

@@ -24,6 +24,7 @@
* [Serie-Ring 环形图](#Serie-Ring) * [Serie-Ring 环形图](#Serie-Ring)
* [Serie-Liquid 水位图](#Serie-Liquid) * [Serie-Liquid 水位图](#Serie-Liquid)
* [Serie-Candlestick K线图](#Serie-Candlestick) * [Serie-Candlestick K线图](#Serie-Candlestick)
* [Serie-Gantt 甘特图](#Serie-Gantt)
* [Settings 设置](#Settings) * [Settings 设置](#Settings)
* [Theme 主题](#Theme) * [Theme 主题](#Theme)
* [Tooltip 提示框](#Tooltip) * [Tooltip 提示框](#Tooltip)
@@ -774,6 +775,24 @@ K线图系列。
* `animation`:起始动画 [SerieAnimation](#SerieAnimation)。 * `animation`:起始动画 [SerieAnimation](#SerieAnimation)。
* `data`:系列中的数据项 [SerieData](#SerieData) 数组K线图至少需要4个维度的数组`[open, close, lowest, highest]` * `data`:系列中的数据项 [SerieData](#SerieData) 数组K线图至少需要4个维度的数组`[open, close, lowest, highest]`
## `Serie-Gantt`
甘特图系列。支持类目轴和时间轴的甘特图,当 `X` 轴为类目轴时,数据为类目的索引,`X` 轴为时间轴时,数据为时间戳(秒为单位)。`Y` 轴默认为类目轴,显示的数据来源于`Serie``Data``Name`
甘特图默认支持开始和结束时间,也可以额外支持实际开始和结束时间。
* `show`:系列是否显示在图表上。
* `type``Gantt`
* `name`:系列名称。用于 `tooltip` 的显示,`legend` 的图例筛选。
* `xAxisIndex`使用的坐标轴X轴的 `index`,在单个图表实例中存在多个坐标轴的时候有用。
* `yAxisIndex`使用的坐标轴Y轴的 `index`,在单个图表实例中存在多个坐标轴的时候有用。
* `clip`:是否裁剪超出坐标系部分的图形。
* `large`:是否开启大数据量优化,在数据图形特别多而出现卡顿时候可以开启。开启后配合 largeThreshold 在数据量大于指定阈值的时候对绘制进行优化。缺点优化后不能自定义设置单个数据项的样式不能显示Label折线图不绘制Symbol。
* `largeThreshold`开启大数量优化的阈值。只有当开启了large并且数据量大于该阀值时才进入性能模式。
* `itemStyle`:甘特图的柱条样式,包括设置背景颜色和边框等 [ItemStyle](#ItemStyle)。
* `emphasis`:高亮样式 [Emphasis](#Emphasis)。
* `animation`:起始动画 [SerieAnimation](#SerieAnimation)。
* `data`:系列中的数据项 [SerieData](#SerieData) 数组甘特图至少需要2个维度的数组`[start, end]`也支持4个维度的数组`[start, end, actualStart, actualEnd]`。当 X 轴为类目轴时数据为类目的索引X 轴为时间轴时,数据为时间戳(秒为单位)。
## `Settings` ## `Settings`
全局参数设置组件。一般情况下可使用默认值,当有需要时可进行调整。 全局参数设置组件。一般情况下可使用默认值,当有需要时可进行调整。

View File

@@ -26,6 +26,7 @@ __Main component:__
* [Serie-Ring](#Serie-Ring) * [Serie-Ring](#Serie-Ring)
* [Serie-Liquid](#Serie-Liquid) * [Serie-Liquid](#Serie-Liquid)
* [Serie-Candlestick](#Serie-Candlestick) * [Serie-Candlestick](#Serie-Candlestick)
* [Serie-Gantt](#Serie-Gantt)
* [Settings](#Settings) * [Settings](#Settings)
* [Theme](#Theme) * [Theme](#Theme)
* [Title](#Title) * [Title](#Title)
@@ -667,6 +668,24 @@ K线图系列。
* `animation`:起始动画 [SerieAnimation](#SerieAnimation)。 * `animation`:起始动画 [SerieAnimation](#SerieAnimation)。
* `data`:系列中的数据项 [SerieData](#SerieData) 数组K线图至少需要4个维度的数组`[open, close, lowest, highest]` * `data`:系列中的数据项 [SerieData](#SerieData) 数组K线图至少需要4个维度的数组`[open, close, lowest, highest]`
## `Serie-Gantt`
甘特图系列。支持类目轴和时间轴的甘特图,当 `X` 轴为类目轴时,数据为类目的索引,`X` 轴为时间轴时,数据为时间戳(秒为单位)。`Y` 轴默认为类目轴,显示的数据来源于`Serie``Data``Name`
甘特图默认支持开始和结束时间,也可以额外支持实际开始和结束时间。
* `show`:系列是否显示在图表上。
* `type``Gantt`
* `name`:系列名称。用于 `tooltip` 的显示,`legend` 的图例筛选。
* `xAxisIndex`使用的坐标轴X轴的 `index`,在单个图表实例中存在多个坐标轴的时候有用。
* `yAxisIndex`使用的坐标轴Y轴的 `index`,在单个图表实例中存在多个坐标轴的时候有用。
* `clip`:是否裁剪超出坐标系部分的图形。
* `large`:是否开启大数据量优化,在数据图形特别多而出现卡顿时候可以开启。开启后配合 largeThreshold 在数据量大于指定阈值的时候对绘制进行优化。缺点优化后不能自定义设置单个数据项的样式不能显示Label折线图不绘制Symbol。
* `largeThreshold`开启大数量优化的阈值。只有当开启了large并且数据量大于该阀值时才进入性能模式。
* `itemStyle`:甘特图的柱条样式,包括设置背景颜色和边框等 [ItemStyle](#ItemStyle)。
* `emphasis`:高亮样式 [Emphasis](#Emphasis)。
* `animation`:起始动画 [SerieAnimation](#SerieAnimation)。
* `data`:系列中的数据项 [SerieData](#SerieData) 数组甘特图至少需要2个维度的数组`[start, end]`也支持4个维度的数组`[start, end, actualStart, actualEnd]`。当 X 轴为类目轴时数据为类目的索引X 轴为时间轴时,数据为时间戳(秒为单位)。
## `Settings` ## `Settings`
全局参数设置组件。一般情况下可使用默认值,当有需要时可进行调整。 全局参数设置组件。一般情况下可使用默认值,当有需要时可进行调整。

View File

@@ -19,6 +19,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (BarChart)target; m_Chart = (BarChart)target;
} }

View File

@@ -123,7 +123,7 @@ namespace XCharts
BlockEnd(); BlockEnd();
BlockStart(); BlockStart();
m_BaseFoldout = EditorGUILayout.Foldout(m_BaseFoldout, "Base"); m_BaseFoldout = EditorGUILayout.Foldout(m_BaseFoldout, "Base", true);
if (m_BaseFoldout) if (m_BaseFoldout)
{ {
EditorGUILayout.PropertyField(m_Script); EditorGUILayout.PropertyField(m_Script);
@@ -196,7 +196,7 @@ namespace XCharts
if (all) if (all)
{ {
var flag = m_Flodouts.ContainsKey(prop.displayName) && m_Flodouts[prop.displayName]; var flag = m_Flodouts.ContainsKey(prop.displayName) && m_Flodouts[prop.displayName];
m_Flodouts[prop.displayName] = EditorGUILayout.Foldout(flag, prop.displayName); m_Flodouts[prop.displayName] = EditorGUILayout.Foldout(flag, prop.displayName, true);
if (m_Flodouts[prop.displayName]) if (m_Flodouts[prop.displayName])
{ {
EditorGUI.indentLevel++; EditorGUI.indentLevel++;

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (CandlestickChart)target; m_Chart = (CandlestickChart)target;
} }
} }

View File

@@ -27,6 +27,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (CoordinateChart)target; m_Chart = (CoordinateChart)target;
m_Grids = serializedObject.FindProperty("m_Grids"); m_Grids = serializedObject.FindProperty("m_Grids");
m_XAxes = serializedObject.FindProperty("m_XAxes"); m_XAxes = serializedObject.FindProperty("m_XAxes");

View File

@@ -0,0 +1,25 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEditor;
namespace XCharts
{
/// <summary>
/// Editor class used to edit UI GanttChart.
/// </summary>
[CustomEditor(typeof(GanttChart), false)]
public class GanttChartEditor : CoordinateChartEditor
{
protected override void OnEnable()
{
base.OnEnable();
if(target == null) return;
m_Chart = (GanttChart)target;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1b5a1dfca8e5476b98c807c66783d85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (GaugeChart)target; m_Chart = (GaugeChart)target;
} }
} }

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (HeatmapChart)target; m_Chart = (HeatmapChart)target;
} }
} }

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (LineChart)target; m_Chart = (LineChart)target;
} }
} }

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (PieChart)target; m_Chart = (PieChart)target;
} }
} }

View File

@@ -22,6 +22,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (PolarChart)target; m_Chart = (PolarChart)target;
m_Polars = serializedObject.FindProperty("m_Polars"); m_Polars = serializedObject.FindProperty("m_Polars");
m_RadiusAxes = serializedObject.FindProperty("m_RadiusAxes"); m_RadiusAxes = serializedObject.FindProperty("m_RadiusAxes");

View File

@@ -42,7 +42,7 @@ namespace XCharts
} }
EditorGUI.EndChangeCheck(); EditorGUI.EndChangeCheck();
} }
if (type == Axis.AxisType.Value) if (type == Axis.AxisType.Value || type == Axis.AxisType.Time)
{ {
PropertyField(prop, "m_MinMaxType"); PropertyField(prop, "m_MinMaxType");
Axis.AxisMinMaxType minMaxType = (Axis.AxisMinMaxType)m_MinMaxType.enumValueIndex; Axis.AxisMinMaxType minMaxType = (Axis.AxisMinMaxType)m_MinMaxType.enumValueIndex;
@@ -60,8 +60,11 @@ namespace XCharts
break; break;
} }
PropertyField(prop, "m_CeilRate"); PropertyField(prop, "m_CeilRate");
if (type == Axis.AxisType.Value)
{
PropertyField(prop, "m_Inverse"); PropertyField(prop, "m_Inverse");
} }
}
PropertyField(prop, "m_SplitNumber"); PropertyField(prop, "m_SplitNumber");
if (type == Axis.AxisType.Category) if (type == Axis.AxisType.Category)
{ {

View File

@@ -197,6 +197,17 @@ namespace XCharts
PropertyField(prop, "m_Label"); PropertyField(prop, "m_Label");
PropertyField(prop, "m_Emphasis"); PropertyField(prop, "m_Emphasis");
break; break;
case SerieType.Gantt:
PropertyField(prop, "m_XAxisIndex");
PropertyField(prop, "m_YAxisIndex");
PropertyField(prop, "m_BarWidth");
PropertyField(prop, "m_Clip");
PropertyField(prop, "m_Large");
PropertyField(prop, "m_LargeThreshold");
PropertyField(prop, "m_ItemStyle");
PropertyField(prop, "m_Label");
PropertyField(prop, "m_Emphasis");
break;
} }
PropertyField(prop, "m_Animation"); PropertyField(prop, "m_Animation");
DrawData(pos, prop, serieType, ref m_DrawRect); DrawData(pos, prop, serieType, ref m_DrawRect);
@@ -340,7 +351,7 @@ namespace XCharts
var startX = drawRect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * 15 + gap; var startX = drawRect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * 15 + gap;
var dataWidTotal = (currentWidth - (startX + 20.5f + 1)); var dataWidTotal = (currentWidth - (startX + 20.5f + 1));
var dataWid = dataWidTotal / fieldCount; var dataWid = dataWidTotal / fieldCount;
var xWid = dataWid - 4; var xWid = dataWid - 2;
for (int i = 0; i < dimension; i++) for (int i = 0; i < dimension; i++)
{ {
var dataCount = i < 1 ? 2 : i + 1; var dataCount = i < 1 ? 2 : i + 1;
@@ -407,7 +418,7 @@ namespace XCharts
var str = prop.propertyPath.Substring(sindex + 1, eindex - sindex - 1); var str = prop.propertyPath.Substring(sindex + 1, eindex - sindex - 1);
int.TryParse(str, out index); int.TryParse(str, out index);
} }
if (index >= m_DataFoldout.Count) while (index >= m_DataFoldout.Count)
{ {
m_DataFoldout.Add(false); m_DataFoldout.Add(false);
} }

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (RingChart)target; m_Chart = (RingChart)target;
} }
} }

View File

@@ -18,6 +18,7 @@ namespace XCharts
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();
if(target == null) return;
m_Chart = (ScatterChart)target; m_Chart = (ScatterChart)target;
} }
} }

View File

@@ -146,11 +146,11 @@ namespace XCharts
AddChart<LiquidChart>("LiquidChart"); AddChart<LiquidChart>("LiquidChart");
} }
[MenuItem("XCharts/CandlestickChart", priority = 54)] [MenuItem("XCharts/GanttChart", priority = 54)]
[MenuItem("GameObject/XCharts/CandlestickChart", priority = 54)] [MenuItem("GameObject/XCharts/GanttChart", priority = 54)]
public static void AddCandlestickChart() public static void AddGanttChart()
{ {
AddChart<CandlestickChart>("CandlestickChart"); AddChart<GanttChart>("GanttChart");
} }
[MenuItem("XCharts/Themes Reload")] [MenuItem("XCharts/Themes Reload")]

View File

@@ -0,0 +1,80 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts.Examples
{
[DisallowMultipleComponent]
[ExecuteInEditMode]
public class Example100_Gantt_Category : MonoBehaviour
{
private GanttChart chart;
private float updateTime;
public int dayCount = 10;
public int taskCount = 5;
void Awake()
{
chart = gameObject.GetComponent<GanttChart>();
if (chart == null)
{
chart = gameObject.AddComponent<GanttChart>();
}
GenerateCategoryData();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
AddData();
}
}
void AddData()
{
for (int i = 0; i < taskCount; i++)
{
var taskName = "task-" + (i + 1);
var startIndex = Random.Range(0, (int)(dayCount * 2.0f / 3));
var endIndex = Random.Range(startIndex, dayCount);
chart.UpdateData(0, i, 0, startIndex);
chart.UpdateData(0, i, 1, endIndex);
}
}
void GenerateCategoryData()
{
chart.RemoveData();
chart.grid.left = 100;
chart.xAxis0.type = Axis.AxisType.Category;
chart.xAxis0.boundaryGap = false;
chart.xAxis0.splitNumber = dayCount;
chart.yAxis0.type = Axis.AxisType.Category;
chart.yAxis0.boundaryGap = true;
chart.yAxis0.splitNumber = 0;
for (int i = 0; i < dayCount; i++)
{
chart.AddXAxisData("day" + (i + 1));
}
var serie = chart.AddSerie(SerieType.Gantt, "任务进度表");
for (int i = 0; i < taskCount; i++)
{
var taskName = "task-" + (i + 1);
var startIndex = Random.Range(0, (int)(dayCount * 2.0f / 3));
var endIndex = Random.Range(startIndex, dayCount);
chart.AddData(0, startIndex, endIndex, taskName);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c383c3eae67ed461693e18a807b2e599
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,99 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts.Examples
{
[DisallowMultipleComponent]
[ExecuteInEditMode]
public class Example101_Gantt_Time : MonoBehaviour
{
private GanttChart chart;
private float updateTime;
public int taskCount = 5;
void Awake()
{
chart = gameObject.GetComponent<GanttChart>();
if (chart == null)
{
chart = gameObject.AddComponent<GanttChart>();
}
GenerateTimeData();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
AddData();
}
}
void AddData()
{
chart.ClearData();
for (int i = 0; i < taskCount; i++)
{
var taskName = "张三-任务-" + (i + 1);
var nowTimestamp = DateTimeUtil.GetTimestamp();
var startTimestamp = nowTimestamp + Random.Range(1, 6) * 3600 * 24;
var endTimestamp = startTimestamp + Random.Range(1, 10) * 3600 * 24;
chart.AddData(0, startTimestamp, endTimestamp, taskName);
}
var serie2 = chart.AddSerie(SerieType.Gantt, "李四");
for (int i = 0; i < taskCount; i++)
{
var taskName = "李四-任务-" + (i + 1);
var nowTimestamp = DateTimeUtil.GetTimestamp();
var startTimestamp = nowTimestamp + Random.Range(1, 6) * 3600 * 24;
var endTimestamp = startTimestamp + Random.Range(1, 10) * 3600 * 24;
chart.AddData(1, startTimestamp, endTimestamp, taskName);
}
}
void GenerateTimeData()
{
chart.RemoveData();
chart.grid.left = 100;
chart.xAxis0.type = Axis.AxisType.Time;
chart.xAxis0.boundaryGap = false;
chart.xAxis0.splitNumber = 5;
chart.xAxis0.axisLabel.numericFormatter = "HH:mm:ss";
chart.xAxis0.axisLabel.formatter = "time:{value}";
chart.yAxis0.type = Axis.AxisType.Category;
chart.yAxis0.boundaryGap = true;
chart.yAxis0.splitNumber = 0;
var serie1 = chart.AddSerie(SerieType.Gantt, "张三");
serie1.label.show = true;
for (int i = 0; i < taskCount; i++)
{
var taskName = "张三-任务-" + (i + 1);
var nowTimestamp = DateTimeUtil.GetTimestamp();
var startTimestamp = nowTimestamp + Random.Range(1, 6) * 3600 * 24;
var endTimestamp = startTimestamp + Random.Range(1, 10) * 3600 * 24;
chart.AddData(0, startTimestamp, endTimestamp, taskName);
}
var serie2 = chart.AddSerie(SerieType.Gantt, "李四");
for (int i = 0; i < taskCount; i++)
{
var taskName = "李四-任务-" + (i + 1);
var nowTimestamp = DateTimeUtil.GetTimestamp();
var startTimestamp = nowTimestamp + Random.Range(1, 6) * 3600 * 24;
var endTimestamp = startTimestamp + Random.Range(1, 10) * 3600 * 24;
chart.AddData(1, startTimestamp, endTimestamp, taskName);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d546ff7dfa6104a739c1accdb415ef54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -45,7 +45,6 @@ namespace XCharts.Examples
chart.ClearData(); chart.ClearData();
var xValue = System.DateTime.Now; var xValue = System.DateTime.Now;
var minute = 60 * 1000;
var baseValue = Random.Range(0f, 1f) * 12000; var baseValue = Random.Range(0f, 1f) * 12000;
var boxVals = new float[4]; var boxVals = new float[4];
var dayRange = 12; var dayRange = 12;

View File

@@ -134,6 +134,7 @@ namespace XCharts
public void RefreshAllComponent() public void RefreshAllComponent()
{ {
SetAllComponentDirty(); SetAllComponentDirty();
RefreshGraph();
} }
/// <summary> /// <summary>

View File

@@ -89,8 +89,16 @@ namespace XCharts
/// </summary> /// </summary>
public void ClearAxisData() public void ClearAxisData()
{ {
foreach (var item in m_XAxes) item.data.Clear(); foreach (var axis in m_XAxes)
foreach (var item in m_YAxes) item.data.Clear(); {
axis.data.Clear();
axis.SetAllDirty();
}
foreach (var axis in m_YAxes)
{
axis.data.Clear();
axis.SetAllDirty();
}
} }
/// <summary> /// <summary>

View File

@@ -39,7 +39,12 @@ namespace XCharts
/// Log axis, suitable for log data. /// Log axis, suitable for log data.
/// 对数轴。适用于对数数据。 /// 对数轴。适用于对数数据。
/// </summary> /// </summary>
Log Log,
/// <summary>
/// Time axis, suitable for continuous time series data.
/// 时间轴。适用于连续的时序数据。
/// </summary>
Time
} }
/// <summary> /// <summary>
@@ -408,6 +413,7 @@ namespace XCharts
public int runtimeMaxLogIndex { get { return logBaseE ? (int)Mathf.Log(runtimeMaxValue) : (int)Mathf.Log(runtimeMaxValue, logBase); } } public int runtimeMaxLogIndex { get { return logBaseE ? (int)Mathf.Log(runtimeMaxValue) : (int)Mathf.Log(runtimeMaxValue, logBase); } }
internal bool runtimeLastCheckInverse { get; set; } internal bool runtimeLastCheckInverse { get; set; }
internal float runtimeMinMaxRange { get { return m_MinMaxValueRange; } set { m_MinMaxValueRange = value; } } internal float runtimeMinMaxRange { get { return m_MinMaxValueRange; } set { m_MinMaxValueRange = value; } }
internal List<string> runtimeData { get { return m_RuntimeData; } }
private int filterStart; private int filterStart;
private int filterEnd; private int filterEnd;
private int filterMinShow; private int filterMinShow;
@@ -426,6 +432,7 @@ namespace XCharts
private float m_RuntimeMaxValueUpdateTime; private float m_RuntimeMaxValueUpdateTime;
private bool m_RuntimeMinValueFirstChanged = true; private bool m_RuntimeMinValueFirstChanged = true;
private bool m_RuntimeMaxValueFirstChanged = true; private bool m_RuntimeMaxValueFirstChanged = true;
protected List<string> m_RuntimeData = new List<string>();
public Axis Clone() public Axis Clone()
{ {
@@ -484,6 +491,7 @@ namespace XCharts
public void ClearData() public void ClearData()
{ {
m_Data.Clear(); m_Data.Clear();
m_RuntimeData.Clear();
SetAllDirty(); SetAllDirty();
} }
@@ -574,10 +582,14 @@ namespace XCharts
} }
else else
{ {
return m_Data; return m_Data.Count > 0 ? m_Data : m_RuntimeData;
} }
} }
internal List<string> GetDataList(){
return m_Data.Count > 0 ? m_Data : m_RuntimeData;
}
private List<string> emptyFliter = new List<string>(); private List<string> emptyFliter = new List<string>();
/// <summary> /// <summary>
/// 更新dataZoom对应的类目数据列表 /// 更新dataZoom对应的类目数据列表
@@ -596,24 +608,25 @@ namespace XCharts
filterEnd = endIndex; filterEnd = endIndex;
filterMinShow = dataZoom.minShowNum; filterMinShow = dataZoom.minShowNum;
m_NeedUpdateFilterData = false; m_NeedUpdateFilterData = false;
if (m_Data.Count > 0) var data = GetDataList();
if (data.Count > 0)
{ {
var count = endIndex == startIndex ? 1 : endIndex - startIndex + 1; var count = endIndex == startIndex ? 1 : endIndex - startIndex + 1;
if (count < dataZoom.minShowNum) if (count < dataZoom.minShowNum)
{ {
if (dataZoom.minShowNum > m_Data.Count) count = m_Data.Count; if (dataZoom.minShowNum > data.Count) count = data.Count;
else count = dataZoom.minShowNum; else count = dataZoom.minShowNum;
} }
if (startIndex + count > m_Data.Count) if (startIndex + count > data.Count)
{ {
int start = endIndex - count; int start = endIndex - count;
filterData = m_Data.GetRange(start < 0 ? 0 : start, count); filterData = data.GetRange(start < 0 ? 0 : start, count);
} }
else filterData = m_Data.GetRange(startIndex, count); else filterData = data.GetRange(startIndex, count);
} }
else else
{ {
filterData = m_Data; filterData = data;
} }
} }
else if (endIndex == 0) else if (endIndex == 0)

View File

@@ -64,6 +64,10 @@ namespace XCharts
/// K线图。K线图的data至少包含四个数据[open, close, lowest, highest] /// K线图。K线图的data至少包含四个数据[open, close, lowest, highest]
/// </summary> /// </summary>
Candlestick, Candlestick,
/// <summary>
/// 甘特图。甘特图的data至少包含两个数据[start, end]
/// </summary>
Gantt,
} }
/// <summary> /// <summary>
@@ -781,7 +785,7 @@ namespace XCharts
/// <summary> /// <summary>
/// 数据项里的数据维数。 /// 数据项里的数据维数。
/// </summary> /// </summary>
public int showDataDimension { get { return m_ShowDataDimension; } } public int showDataDimension { get { return m_ShowDataDimension; } internal set { m_ShowDataDimension = value; } }
/// <summary> /// <summary>
/// 在Editor的inpsector上是否显示name参数 /// 在Editor的inpsector上是否显示name参数
/// </summary> /// </summary>
@@ -1234,6 +1238,7 @@ namespace XCharts
{ {
CheckMaxCache(); CheckMaxCache();
var serieData = SerieDataPool.Get(); var serieData = SerieDataPool.Get();
serieData.data.Clear();
serieData.data.Add(xValue); serieData.data.Add(xValue);
serieData.data.Add(yValue); serieData.data.Add(yValue);
serieData.name = dataName; serieData.name = dataName;
@@ -1245,10 +1250,20 @@ namespace XCharts
return serieData; return serieData;
} }
/// <summary>
/// 添加 (open, close, lowest, heighest) 数据
/// </summary>
/// <param name="open"></param>
/// <param name="close"></param>
/// <param name="lowest"></param>
/// <param name="heighest"></param>
/// <param name="dataName"></param>
/// <returns></returns>
public SerieData AddData(float open, float close, float lowest, float heighest, string dataName = null) public SerieData AddData(float open, float close, float lowest, float heighest, string dataName = null)
{ {
CheckMaxCache(); CheckMaxCache();
var serieData = SerieDataPool.Get(); var serieData = SerieDataPool.Get();
serieData.data.Clear();
serieData.data.Add(open); serieData.data.Add(open);
serieData.data.Add(close); serieData.data.Add(close);
serieData.data.Add(lowest); serieData.data.Add(lowest);
@@ -1678,7 +1693,9 @@ namespace XCharts
return type == SerieType.Line return type == SerieType.Line
|| type == SerieType.Bar || type == SerieType.Bar
|| type == SerieType.Scatter || type == SerieType.Scatter
|| type == SerieType.Heatmap; || type == SerieType.Heatmap
|| type == SerieType.Gantt
|| type == SerieType.Candlestick;
} }
/// <summary> /// <summary>

View File

@@ -188,9 +188,8 @@ namespace XCharts
} }
else else
{ {
var content = m_Formatter.Replace("{value}", category); var content = m_Formatter;
content = content.Replace("\\n", "\n"); FormatterHelper.ReplaceAxisLabelContent(ref content, category);
content = content.Replace("<br/>", "\n");
return m_TextLimit.GetLimitContent(content); return m_TextLimit.GetLimitContent(content);
} }
} }
@@ -224,5 +223,21 @@ namespace XCharts
return content; return content;
} }
} }
public string GetFormatterDateTime(DateTime dateTime)
{
var format = string.IsNullOrEmpty(numericFormatter) ? "yyyy/M/d" : numericFormatter;
if (!string.IsNullOrEmpty(m_Formatter))
{
var content = m_Formatter;
FormatterHelper.ReplaceAxisLabelContent(ref content, dateTime.ToString(format));
return m_TextLimit.GetLimitContent(content);
}
else
{
var content = dateTime.ToString(format);
return m_TextLimit.GetLimitContent(content);
}
}
} }
} }

View File

@@ -5,11 +5,8 @@
/* */ /* */
/************************************************/ /************************************************/
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using System;
namespace XCharts namespace XCharts
{ {
@@ -191,6 +188,10 @@ namespace XCharts
/// </summary> /// </summary>
public float runtimePieOffsetRadius { get; internal set; } public float runtimePieOffsetRadius { get; internal set; }
public Vector3 runtimePosition { get; internal set; } public Vector3 runtimePosition { get; internal set; }
/// <summary>
/// 绘制区域。
/// </summary>
public Rect runtimeRect { get; internal set; }
public float runtimeAngle { get; internal set; } public float runtimeAngle { get; internal set; }
public Vector3 runtiemPieOffsetCenter { get; internal set; } public Vector3 runtiemPieOffsetCenter { get; internal set; }
public float runtimeStackHig { get; internal set; } public float runtimeStackHig { get; internal set; }

View File

@@ -85,5 +85,13 @@ namespace XCharts
runtimeText.SetText(text); runtimeText.SetText(text);
} }
} }
public void SetColor(Color color)
{
if (runtimeText != null)
{
runtimeText.SetColor(color);
}
}
} }
} }

View File

@@ -0,0 +1,137 @@

/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
[AddComponentMenu("XCharts/GanttChart", 22)]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
[DisallowMultipleComponent]
public partial class GanttChart : CoordinateChart
{
#if UNITY_EDITOR
protected override void Reset()
{
base.Reset();
title.text = "GanttChart";
var xCount = 5;
var yCount = 5;
m_Grids[0].left = 60;
m_Grids[0].right = 50;
m_XAxes[0].type = Axis.AxisType.Time;
m_XAxes[0].boundaryGap = false;
m_XAxes[0].splitNumber = xCount;
m_YAxes[0].type = Axis.AxisType.Category;
m_YAxes[0].boundaryGap = true;
m_YAxes[0].splitNumber = 0;
RemoveData();
SerieTemplate.AddDefaultTimeGanttSerie(this, "task", yCount);
}
#endif
protected override void GetSeriesMinMaxValue(Axis axis, int axisIndex, out float tempMinValue, out float tempMaxValue)
{
tempMinValue = int.MaxValue;
tempMaxValue = int.MinValue;
foreach (var serie in m_Series.list)
{
if (serie.type != SerieType.Gantt) continue;
if (serie.xAxisIndex != axis.index) continue;
foreach (var serieData in serie.data)
{
if (serieData.data.Count >= 2)
{
var xData = serieData.data[0];
var yData = serieData.data[1];
if (xData < tempMinValue) tempMinValue = xData;
if (yData > tempMaxValue) tempMaxValue = yData;
}
}
}
if (tempMinValue == int.MaxValue) tempMinValue = 0;
if (tempMaxValue == int.MinValue) tempMaxValue = 0;
//AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true, 60);
}
protected override void OnRefreshLabel()
{
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.GetSerie(i);
if (serie.IsPerformanceMode()) continue;
if (serie.type != SerieType.Gantt) continue;
foreach (var serieData in serie.data)
{
if (serieData.labelObject == null) continue;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
var labelShow = serie.show && serieLabel.show;
serieData.SetLabelActive(labelShow);
if (labelShow)
{
var labelColor = serieLabel.textStyle.GetColor(m_Theme.axis.textColor);
var labelPos = serieData.runtimePosition;
SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, m_Theme, i);
serieData.labelObject.SetPosition(labelPos);
serieData.labelObject.SetLabelColor(labelColor);
serieData.labelObject.SetText(serieData.name);
}
}
}
}
protected override void UpdateTooltipValue(Vector2 local)
{
var grid = GetGrid(tooltip.runtimeGridIndex);
if (grid == null) return;
tooltip.runtimeDataIndex.Clear();
foreach (var serie in m_Series.list)
{
var serieGrid = GetSerieGridOrDefault(serie);
if (grid.index != serieGrid.index) continue;
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.GetSerieData(i);
var highlight = serieData.runtimeRect.Contains(local);
serieData.highlighted = highlight;
if (highlight)
{
tooltip.runtimeDataIndex.Add(serie.index);
tooltip.runtimeDataIndex.Add(i);
return;
}
}
}
}
protected override void UpdateTooltip()
{
if (tooltip.runtimeDataIndex.Count == 0)
{
if (tooltip.IsActive())
{
tooltip.SetActive(false);
RefreshChart();
}
return;
}
var serieIndex = tooltip.runtimeDataIndex[0];
var dataIndex = tooltip.runtimeDataIndex[1];
var serie = m_Series.GetSerie(serieIndex);
if (serie == null) return;
var serieData = serie.GetSerieData(dataIndex);
var category = serieData == null ? serie.name : serieData.name;
TooltipHelper.SetContentAndPosition(tooltip, category, chartRect);
tooltip.SetActive(true);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d20186b31c74d4711870603e97fd65bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -198,6 +198,20 @@ namespace XCharts
content = TrimAndReplaceLine(content); content = TrimAndReplaceLine(content);
} }
public static void ReplaceAxisLabelContent(ref string content, string value)
{
var mc = s_RegexForAxisLabel.Matches(content);
foreach (var m in mc)
{
var old = m.ToString();
var args = s_RegexSubForAxisLabel.Matches(m.ToString());
var argsCount = args.Count;
if (argsCount <= 0) continue;
content = content.Replace(old, value);
}
content = TrimAndReplaceLine(content);
}
public static void ReplaceSerieLabelContent(ref string content, string numericFormatter, float value, float total, public static void ReplaceSerieLabelContent(ref string content, string numericFormatter, float value, float total,
string serieName, string dataName) string serieName, string dataName)
{ {

View File

@@ -284,6 +284,7 @@ namespace XCharts
foreach (var component in m_Radars) component.SetAllDirty(); foreach (var component in m_Radars) component.SetAllDirty();
m_ReinitLabel = true; m_ReinitLabel = true;
m_ReinitTitle = true; m_ReinitTitle = true;
m_RefreshChart = true;
} }
protected override void OnDestroy() protected override void OnDestroy()

View File

@@ -178,6 +178,9 @@ namespace XCharts
case SerieType.Candlestick: case SerieType.Candlestick:
DrawCandlestickSerie(vh, colorIndex, serie); DrawCandlestickSerie(vh, colorIndex, serie);
break; break;
case SerieType.Gantt:
DrawGanttSerie(vh, colorIndex, serie);
break;
} }
} }
@@ -240,7 +243,7 @@ namespace XCharts
} }
} }
protected void UpdateTooltipValue(Vector2 local) protected virtual void UpdateTooltipValue(Vector2 local)
{ {
var isCartesian = IsValue(); var isCartesian = IsValue();
var dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoom).Count : 0; var dataCount = m_Series.list.Count > 0 ? m_Series.list[0].GetDataList(dataZoom).Count : 0;
@@ -495,6 +498,7 @@ namespace XCharts
yAxis.painter = m_Painter; yAxis.painter = m_Painter;
yAxis.refreshComponent = delegate () yAxis.refreshComponent = delegate ()
{ {
InitAxisRuntimeData(yAxis);
string objName = ChartCached.GetYAxisName(yAxisIndex); string objName = ChartCached.GetYAxisName(yAxisIndex);
var axisObj = ChartHelper.AddObject(objName, transform, graphAnchorMin, var axisObj = ChartHelper.AddObject(objName, transform, graphAnchorMin,
graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight)); graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
@@ -593,6 +597,26 @@ namespace XCharts
yAxis.refreshComponent(); yAxis.refreshComponent();
} }
private void InitAxisRuntimeData(Axis axis)
{
if (axis.type != Axis.AxisType.Category) return;
if (axis.data.Count > 0) return;
var isYAxis = axis is YAxis;
if (this is GanttChart)
{
axis.runtimeData.Clear();
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.GetSerie(i);
if(serie.yAxisIndex != axis.index) continue;
for (int j = serie.data.Count - 1; j >= 0; j--)
{
axis.runtimeData.Add(serie.data[j].name);
}
}
}
}
private void InitAxisX() private void InitAxisX()
{ {
for (int i = 0; i < m_XAxes.Count; i++) for (int i = 0; i < m_XAxes.Count; i++)
@@ -782,7 +806,7 @@ namespace XCharts
return new Vector3(grid.runtimeX + scaleWid, posY); return new Vector3(grid.runtimeX + scaleWid, posY);
} }
private void CheckMinMaxValue() protected virtual void CheckMinMaxValue()
{ {
if (m_XAxes == null || m_YAxes == null) return; if (m_XAxes == null || m_YAxes == null) return;
for (int i = 0; i < m_XAxes.Count; i++) for (int i = 0; i < m_XAxes.Count; i++)
@@ -806,23 +830,7 @@ namespace XCharts
} }
float tempMinValue = 0; float tempMinValue = 0;
float tempMaxValue = 0; float tempMaxValue = 0;
GetSeriesMinMaxValue(axis, axisIndex, out tempMinValue, out tempMaxValue);
if (IsValue())
{
if (axis is XAxis)
{
SeriesHelper.GetXMinMaxValue(m_Series, null, axisIndex, true, axis.inverse, out tempMinValue, out tempMaxValue);
}
else
{
SeriesHelper.GetYMinMaxValue(m_Series, null, axisIndex, true, axis.inverse, out tempMinValue, out tempMaxValue);
}
}
else
{
SeriesHelper.GetYMinMaxValue(m_Series, null, axisIndex, false, axis.inverse, out tempMinValue, out tempMaxValue);
}
AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true);
if (tempMinValue != axis.runtimeMinValue || tempMaxValue != axis.runtimeMaxValue) if (tempMinValue != axis.runtimeMinValue || tempMaxValue != axis.runtimeMaxValue)
{ {
m_IsPlayingAnimation = true; m_IsPlayingAnimation = true;
@@ -866,6 +874,26 @@ namespace XCharts
} }
} }
protected virtual void GetSeriesMinMaxValue(Axis axis, int axisIndex, out float tempMinValue, out float tempMaxValue)
{
if (IsValue())
{
if (axis is XAxis)
{
SeriesHelper.GetXMinMaxValue(m_Series, null, axisIndex, true, axis.inverse, out tempMinValue, out tempMaxValue);
}
else
{
SeriesHelper.GetYMinMaxValue(m_Series, null, axisIndex, true, axis.inverse, out tempMinValue, out tempMaxValue);
}
}
else
{
SeriesHelper.GetYMinMaxValue(m_Series, null, axisIndex, false, axis.inverse, out tempMinValue, out tempMaxValue);
}
AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true);
}
protected void UpdateAxisLabelText(Axis axis) protected void UpdateAxisLabelText(Axis axis)
{ {
var grid = GetAxisGridOrDefault(axis); var grid = GetAxisGridOrDefault(axis);
@@ -1571,6 +1599,7 @@ namespace XCharts
{ {
base.OnRefreshLabel(); base.OnRefreshLabel();
var anyPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar); var anyPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
for (int i = 0; i < m_Series.Count; i++) for (int i = 0; i < m_Series.Count; i++)
{ {
var serie = m_Series.GetSerie(i); var serie = m_Series.GetSerie(i);
@@ -1578,6 +1607,7 @@ namespace XCharts
if (!serie.IsCoordinateSerie()) continue; if (!serie.IsCoordinateSerie()) continue;
var total = serie.yTotal; var total = serie.yTotal;
var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar); var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar);
for (int j = 0; j < serie.data.Count; j++) for (int j = 0; j < serie.data.Count; j++)
{ {
var serieData = serie.data[j]; var serieData = serie.data[j];
@@ -1602,7 +1632,7 @@ namespace XCharts
dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count); dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count);
} }
SerieLabelHelper.ResetLabel(serieData, serieLabel, theme, i); SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, theme, i);
value = serieData.data[dimension]; value = serieData.data[dimension];
var content = ""; var content = "";

View File

@@ -0,0 +1,178 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public partial class CoordinateChart
{
protected void DrawGanttSerie(VertexHelper vh, int colorIndex, Serie serie)
{
if (!IsActive(serie.index)) return;
if (serie.animation.HasFadeOut()) return;
var showData = serie.GetDataList(null);
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
var grid = GetSerieGridOrDefault(serie);
var xCategoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
var yCategoryWidth = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, showData.Count, dataZoom);
var barGap = GetBarGap();
var barWidth = serie.GetBarWidth(yCategoryWidth);
var space = (yCategoryWidth - barWidth) / 2;
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var minValue = xAxis.GetCurrMinValue(dataChangeDuration);
var maxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
var pX = grid.runtimeX + (xAxis.boundaryGap ? xCategoryWidth / 2 : 0);
var pY = 0f;
var startY = grid.runtimeY - (yAxis.boundaryGap ? 0 : yCategoryWidth / 2);
var isTime = xAxis.type == Axis.AxisType.Time;
var categoryIndex = GetGanttSerieCategoryIndex(serie, grid.index);
var dataCount = serie.data.Count;
for (int i = 0; i < dataCount; i++)
{
var serieData = serie.data[i];
pY = startY + (categoryIndex - 1 - i) * yCategoryWidth;
DrawSerieData(vh, grid, serie, serieData, colorIndex, pX, pY, space, barWidth, isTime, minValue,
maxValue, xCategoryWidth);
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
private void DrawSerieData(VertexHelper vh, Grid grid, Serie serie, SerieData serieData, int colorIndex,
float pX, float pY, float space, float barWidth, bool isTime, float minValue, float maxValue,
float xCategoryWidth)
{
var xStart = 0f;
var xEnd = 0f;
var xActualStart = 0f;
var xActualEnd = 0f;
var start = (int)serieData.GetData(0);
var end = (int)serieData.GetData(1);
var actualStart = (int)serieData.GetData(2);
var actualEnd = (int)serieData.GetData(3);
var enableActual = actualStart > 0 && actualEnd > 0;
if (isTime)
{
var valueTotal = maxValue - minValue;
xStart = pX + (start - minValue) / valueTotal * grid.runtimeWidth;
xEnd = pX + (end - minValue) / valueTotal * grid.runtimeWidth;
if (enableActual)
{
xActualStart = pX + (actualStart - minValue) / valueTotal * grid.runtimeWidth;
xActualEnd = pX + (actualEnd - minValue) / valueTotal * grid.runtimeWidth;
}
}
else
{
xStart = pX + start * xCategoryWidth;
xEnd = pX + end * xCategoryWidth;
if (enableActual)
{
xActualStart = pX + actualStart * xCategoryWidth;
xActualEnd = pX + actualEnd * xCategoryWidth;
}
}
var highlight = (serieData != null && serieData.highlighted)
|| serie.highlighted;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
var color = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
var borderWidth = itemStyle.borderWidth;
var rect = DrawGanttBar(vh, grid, serie, serieData, itemStyle, color, pY, pY, space, barWidth, xStart,
xEnd);
if (enableActual)
{
var defaultActualColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, true);
var actualColor = SerieHelper.GetItemColor0(serie, serieData, m_Theme, highlight, defaultActualColor);
var rect2 = DrawGanttBar(vh, grid, serie, serieData, itemStyle, actualColor, pY, pY, space, barWidth,
xActualStart, xActualEnd);
var rect3X = Mathf.Min(rect.x, rect2.x);
var rect3Width = Mathf.Max(rect.x + rect.width, rect2.x + rect2.width) - rect3X;
var rect3 = new Rect(rect3X, rect.y, rect3Width, rect.height);
serie.dataPoints.Add(rect3.center);
serieData.runtimePosition = rect3.center;
serieData.labelPosition = rect3.center;
serieData.runtimeRect = rect3;
}
else
{
serie.dataPoints.Add(rect.center);
serieData.runtimePosition = rect.center;
serieData.labelPosition = rect.center;
serieData.runtimeRect = rect;
}
}
private Rect DrawGanttBar(VertexHelper vh, Grid grid, Serie serie, SerieData serieData, ItemStyle itemStyle,
Color32 color, float pX, float pY, float space, float barWidth, float xStart, float xEnd)
{
var borderWidth = itemStyle.borderWidth;
var plb = new Vector3(xStart + borderWidth, pY + space + borderWidth);
var plt = new Vector3(xStart + borderWidth, pY + space + barWidth - borderWidth);
var prt = new Vector3(xEnd - borderWidth, pY + space + barWidth - borderWidth);
var prb = new Vector3(xEnd - borderWidth, pY + space + borderWidth);
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
var itemWidth = Mathf.Abs(prt.x - plb.x);
var itemHeight = Mathf.Abs(plt.y - prb.y);
if (serie.clip)
{
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
prb = ClampInGrid(grid, prb);
center = ClampInGrid(grid, center);
}
if (ItemStyleHelper.IsNeedCorner(itemStyle))
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, color, color, 0,
itemStyle.cornerRadius, true, 0.5f);
}
else
{
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, color, color,
serie.clip, grid);
}
if (borderWidth != 0)
{
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor, 0,
itemStyle.cornerRadius, true, 0.5f);
}
return new Rect(plb.x, plb.y, xEnd - xStart, barWidth);
}
private int GetGanttSerieCategoryIndex(Serie currSerie, int gridIndex)
{
var count = m_Series.Count;
var index = 0;
for (int i = 0; i < count; i++)
{
var serie = m_Series.GetSerie(i);
if (serie.type != SerieType.Gantt) continue;
var grid = GetSerieGridOrDefault(serie);
if (grid.index != gridIndex) continue;
foreach (var serieData in serie.data)
{
index++;
}
if (serie.index == currSerie.index)
{
return index;
}
}
return index;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 81895b3c97e684e8090572c7e64b396e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -99,7 +99,7 @@ namespace XCharts
{ {
var value = serieData.GetCurrData(1); var value = serieData.GetCurrData(1);
var max = radar.GetIndicatorMax(n); var max = radar.GetIndicatorMax(n);
SerieLabelHelper.ResetLabel(serieData, serieLabel, chart.theme, i); SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, chart.theme, i);
serieData.SetLabelActive(serieData.labelPosition != Vector3.zero); serieData.SetLabelActive(serieData.labelPosition != Vector3.zero);
serieData.labelObject.SetLabelPosition(serieLabel.offset); serieData.labelObject.SetLabelPosition(serieLabel.offset);
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, max, serieLabel); var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, max, serieLabel);

View File

@@ -53,6 +53,25 @@ namespace XCharts
return axis.splitNumber > 0 ? axis.splitNumber : 4; return axis.splitNumber > 0 ? axis.splitNumber : 4;
} }
} }
else if (axis.type == Axis.AxisType.Time)
{
if (axis.interval > 0)
{
if (coordinateWid <= 0) return 0;
int num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
int maxNum = Mathf.CeilToInt(coordinateWid / 15);
if (num > maxNum)
{
axis.interval *= 2;
num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
}
return num;
}
else
{
return axis.splitNumber > 0 ? axis.splitNumber : 4;
}
}
else if (axis.type == Axis.AxisType.Log) else if (axis.type == Axis.AxisType.Log)
{ {
return axis.splitNumber > 0 ? axis.splitNumber : 4; return axis.splitNumber > 0 ? axis.splitNumber : 4;
@@ -146,6 +165,23 @@ namespace XCharts
} }
return axis.axisLabel.GetFormatterContent(value, minValue, maxValue, true); return axis.axisLabel.GetFormatterContent(value, minValue, maxValue, true);
} }
else if (axis.type == Axis.AxisType.Time)
{
if (minValue == 0 && maxValue == 0) return string.Empty;
var value = 0f;
if (axis.interval > 0)
{
if (index == split) value = maxValue;
else value = minValue + index * axis.interval;
}
else
{
value = minValue + (maxValue - minValue) * index / split;
}
var timestamp = (int)value;
var dateTime = DateTimeUtil.GetDateTime(timestamp);
return axis.axisLabel.GetFormatterDateTime(dateTime);
}
var showData = axis.GetDataList(dataZoom); var showData = axis.GetDataList(dataZoom);
int dataCount = showData.Count; int dataCount = showData.Count;
if (dataCount <= 0) return ""; if (dataCount <= 0) return "";
@@ -177,11 +213,12 @@ namespace XCharts
int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom); int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);
if (axis.IsCategory()) if (axis.IsCategory())
{ {
int tick = Mathf.RoundToInt(axis.data.Count * 1f / splitNum); var data = axis.GetDataList();
int tick = Mathf.RoundToInt(data.Count * 1f / splitNum);
if (axis.boundaryGap) if (axis.boundaryGap)
return Mathf.CeilToInt(axis.data.Count * 1.0f / tick) + 1; return Mathf.CeilToInt(data.Count * 1.0f / tick) + 1;
else else
return Mathf.CeilToInt(axis.data.Count * 1.0f / tick); return Mathf.CeilToInt(data.Count * 1.0f / tick);
} }
else else
{ {
@@ -209,10 +246,11 @@ namespace XCharts
} }
else else
{ {
if (axis.IsCategory() && axis.data.Count > 0) var data = axis.GetDataList();
if (axis.IsCategory() && data.Count > 0)
{ {
int tick = Mathf.RoundToInt(axis.data.Count * 1f / splitNum); int tick = Mathf.RoundToInt(data.Count * 1f / splitNum);
var count = axis.boundaryGap ? axis.data.Count : axis.data.Count - 1; var count = axis.boundaryGap ? data.Count : data.Count - 1;
if (count <= 0) return 0; if (count <= 0) return 0;
var each = coordinateWidth / count; var each = coordinateWidth / count;
if (index >= num - 1) if (index >= num - 1)
@@ -232,9 +270,10 @@ namespace XCharts
internal static float GetEachWidth(Axis axis, float coordinateWidth, DataZoom dataZoom = null) internal static float GetEachWidth(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
{ {
if (axis.data.Count > 0) var data = axis.GetDataList();
if (data.Count > 0)
{ {
var count = axis.boundaryGap ? axis.data.Count : axis.data.Count - 1; var count = axis.boundaryGap ? data.Count : data.Count - 1;
return count > 0 ? coordinateWidth / count : coordinateWidth; return count > 0 ? coordinateWidth / count : coordinateWidth;
} }
else else
@@ -249,7 +288,7 @@ namespace XCharts
/// </summary> /// </summary>
/// <param name="minValue"></param> /// <param name="minValue"></param>
/// <param name="maxValue"></param> /// <param name="maxValue"></param>
internal static void AdjustMinMaxValue(Axis axis, ref float minValue, ref float maxValue, bool needFormat) internal static void AdjustMinMaxValue(Axis axis, ref float minValue, ref float maxValue, bool needFormat, int ceilRate = 0)
{ {
if (axis.type == Axis.AxisType.Log) if (axis.type == Axis.AxisType.Log)
{ {
@@ -278,6 +317,7 @@ namespace XCharts
} }
else else
{ {
if (ceilRate == 0) ceilRate = axis.ceilRate;
switch (axis.minMaxType) switch (axis.minMaxType)
{ {
case Axis.AxisMinMaxType.Default: case Axis.AxisMinMaxType.Default:
@@ -287,22 +327,22 @@ namespace XCharts
else if (minValue > 0 && maxValue > 0) else if (minValue > 0 && maxValue > 0)
{ {
minValue = 0; minValue = 0;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, axis.ceilRate) : maxValue; maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
} }
else if (minValue < 0 && maxValue < 0) else if (minValue < 0 && maxValue < 0)
{ {
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, axis.ceilRate) : minValue; minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
maxValue = 0; maxValue = 0;
} }
else else
{ {
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, axis.ceilRate) : minValue; minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, axis.ceilRate) : maxValue; maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
} }
break; break;
case Axis.AxisMinMaxType.MinMax: case Axis.AxisMinMaxType.MinMax:
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, axis.ceilRate) : minValue; minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, axis.ceilRate) : maxValue; maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
break; break;
} }
} }
@@ -320,7 +360,7 @@ namespace XCharts
internal static bool NeedShowSplit(Axis axis) internal static bool NeedShowSplit(Axis axis)
{ {
if (!axis.show) return false; if (!axis.show) return false;
if (axis.IsCategory() && axis.data.Count <= 0) return false; if (axis.IsCategory() && axis.GetDataList().Count <= 0) return false;
else if (axis.IsValue() && axis.runtimeMinValue == 0 && axis.runtimeMaxValue == 0) return false; else if (axis.IsValue() && axis.runtimeMinValue == 0 && axis.runtimeMaxValue == 0) return false;
else return true; else return true;
} }

View File

@@ -70,6 +70,32 @@ namespace XCharts
return color; return color;
} }
} }
internal static Color32 GetItemColor0(Serie serie, SerieData serieData, ChartTheme theme, bool highlight, Color32 defaultColor)
{
if (serie == null) return ChartConst.clearColor32;
if (highlight)
{
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
{
var color = itemStyleEmphasis.color0;
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
return color;
}
}
var itemStyle = GetItemStyle(serie, serieData);
if (!ChartHelper.IsClearColor(itemStyle.color0))
{
return itemStyle.GetColor0();
}
else
{
var color = defaultColor;
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
}
internal static Color32 GetItemToColor(Serie serie, SerieData serieData, ChartTheme theme, int index, bool highlight) internal static Color32 GetItemToColor(Serie serie, SerieData serieData, ChartTheme theme, int index, bool highlight)
{ {

View File

@@ -75,14 +75,13 @@ namespace XCharts
} }
} }
public static void ResetLabel(SerieData serieData, SerieLabel label, ChartTheme theme, int colorIndex) public static void ResetLabel(ChartText labelObject, SerieLabel label, ChartTheme theme, int colorIndex)
{ {
if (serieData.labelObject == null) return; if (labelObject == null) return;
if (serieData.labelObject.label == null) return; labelObject.SetColor(!ChartHelper.IsClearColor(label.textStyle.color) ? label.textStyle.color :
serieData.labelObject.label.SetColor(!ChartHelper.IsClearColor(label.textStyle.color) ? label.textStyle.color :
(Color)theme.GetColor(colorIndex)); (Color)theme.GetColor(colorIndex));
serieData.labelObject.label.SetFontSize(label.textStyle.GetFontSize(theme.common)); labelObject.SetFontSize(label.textStyle.GetFontSize(theme.common));
serieData.labelObject.label.SetFontStyle(label.textStyle.fontStyle); labelObject.SetFontStyle(label.textStyle.fontStyle);
} }
public static bool CanShowLabel(Serie serie, SerieData serieData, SerieLabel label, int dimesion) public static bool CanShowLabel(Serie serie, SerieData serieData, SerieLabel label, int dimesion)

View File

@@ -232,6 +232,14 @@ namespace XCharts
} }
} }
private static void InitGanttTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme, string category)
{
//if (tooltip.runtimeGridIndex >= 0) return;
//if (serie.index != index || serie.type != SerieType.Gantt) return;
sb.Append(serie.name);
}
private static void InitDefaultContent(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index, private static void InitDefaultContent(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
string category, ChartTheme theme = null, DataZoom dataZoom = null, bool isCartesian = false, string category, ChartTheme theme = null, DataZoom dataZoom = null, bool isCartesian = false,
Radar radar = null) Radar radar = null)
@@ -261,6 +269,9 @@ namespace XCharts
case SerieType.Gauge: case SerieType.Gauge:
InitGaugeTooltip(ref sb, tooltip, serie, index, theme); InitGaugeTooltip(ref sb, tooltip, serie, index, theme);
break; break;
case SerieType.Gantt:
InitGanttTooltip(ref sb, tooltip, serie, index, theme, category);
break;
} }
} }

View File

@@ -28,6 +28,7 @@ namespace XCharts
case SerieType.Gauge: AddDefaultGaugeSerie(chart, serieName); break; case SerieType.Gauge: AddDefaultGaugeSerie(chart, serieName); break;
case SerieType.Ring: AddDefaultRingSerie(chart, serieName); break; case SerieType.Ring: AddDefaultRingSerie(chart, serieName); break;
case SerieType.Candlestick: AddDefaultCandlestickSerie(chart, serieName); break; case SerieType.Candlestick: AddDefaultCandlestickSerie(chart, serieName); break;
case SerieType.Gantt: AddDefaultCategoryGanttSerie(chart, serieName); break;
default: Debug.LogError("AddDefaultSerie: not support serieType yet:" + serieType); break; default: Debug.LogError("AddDefaultSerie: not support serieType yet:" + serieType); break;
} }
} }
@@ -183,5 +184,35 @@ namespace XCharts
} }
return defaultDataCount; return defaultDataCount;
} }
public static Serie AddDefaultCategoryGanttSerie(BaseChart chart, string serieName, int dataCount = 0, int min = 0, int max = 0)
{
var serie = chart.AddSerie(SerieType.Gantt, serieName);
serie.showDataName = true;
serie.showDataDimension = 2;
for (int i = 0; i < dataCount; i++)
{
var start = Random.Range(min, max);
var end = Random.Range(start + 1, max);
serie.AddXYData(start, end, "task-" + (i + 1));
}
return serie;
}
public static Serie AddDefaultTimeGanttSerie(BaseChart chart, string serieName, int dataCount = 0)
{
var serie = chart.AddSerie(SerieType.Gantt, serieName);
serie.showDataName = true;
serie.showDataDimension = 2;
var timestamp = DateTimeUtil.GetTimestamp();
var now = DateTimeUtil.GetDateTime(timestamp);
for (int i = 0; i < dataCount; i++)
{
var start = timestamp + Random.Range(1, 6) * 3600 * 24;
var end = start + Random.Range(1, 10) * 3600 * 24;
serie.AddXYData(start, end, "task-" + (i + 1));
}
return serie;
}
} }
} }

View File

@@ -0,0 +1,33 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System;
using UnityEngine;
namespace XCharts
{
public static class DateTimeUtil
{
private static readonly DateTime k_DateTime1970 = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
public static int GetTimestamp()
{
return (int)(DateTime.Now - k_DateTime1970).TotalSeconds;
}
public static int GetTimestamp(DateTime time)
{
return (int)(time - k_DateTime1970).TotalSeconds;
}
public static DateTime GetDateTime(int timestamp)
{
long span = ((long)timestamp) * 10000000;
return k_DateTime1970.Add(new TimeSpan(span));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f0ac80f189a04b5c826f40c8bc8af64
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -5,14 +5,24 @@
/* */ /* */
/************************************************/ /************************************************/
using System.Collections.Generic;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace XChartsDemo namespace XChartsDemo
{ {
[CustomPropertyDrawer(typeof(ChartModule), true)] [CustomPropertyDrawer(typeof(ChartModule), true)]
public class ChartModuleDrawer : PropertyDrawer internal class ChartModuleDrawer : PropertyDrawer
{ {
public class Styles
{
public static readonly GUIContent iconAdd = new GUIContent("+", "Add");
public static readonly GUIContent iconRemove = new GUIContent("-", "Remove");
public static readonly GUIContent iconUp = new GUIContent("↑", "Up");
public static readonly GUIContent iconDown = new GUIContent("↓", "Down");
public static readonly GUIStyle invisibleButton = "InvisibleButton";
}
public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label) public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label)
{ {
Rect drawRect = pos; Rect drawRect = pos;
@@ -25,9 +35,29 @@ namespace XChartsDemo
SerializedProperty m_Title = prop.FindPropertyRelative("m_Title"); SerializedProperty m_Title = prop.FindPropertyRelative("m_Title");
SerializedProperty m_Selected = prop.FindPropertyRelative("m_Selected"); SerializedProperty m_Selected = prop.FindPropertyRelative("m_Selected");
SerializedProperty m_Panel = prop.FindPropertyRelative("m_Panel"); SerializedProperty m_Panel = prop.FindPropertyRelative("m_Panel");
var fieldWid = EditorGUIUtility.currentViewWidth - 30 - 5 - 40 - 80 - 50 - 100 - 6 * 2; var fieldWid = EditorGUIUtility.currentViewWidth - 30 - 5 - 40 - 80 - 50 - 100 - 6 * 2 - 70;
drawRect.width = 15; drawRect.width = 15;
EditorGUI.BeginChangeCheck();
var oldFlag = m_Selected.boolValue;
EditorGUI.PropertyField(drawRect, m_Selected, GUIContent.none); EditorGUI.PropertyField(drawRect, m_Selected, GUIContent.none);
if (EditorGUI.EndChangeCheck())
{
var demo = prop.serializedObject.targetObject as Demo;
var index = GetIndex(prop);
var selectedIndex = demo.GetSelectedModule();
if (selectedIndex != index)
{
for (int i = 0; i < demo.chartModules.Count; i++)
{
demo.chartModules[i].select = i == index && m_Selected.boolValue;
}
demo.InitModuleButton();
}
else
{
m_Selected.boolValue = oldFlag;
}
}
drawRect.x += 17; drawRect.x += 17;
drawRect.width = 80; drawRect.width = 80;
EditorGUI.PropertyField(drawRect, m_Name, GUIContent.none); EditorGUI.PropertyField(drawRect, m_Name, GUIContent.none);
@@ -43,11 +73,83 @@ namespace XChartsDemo
drawRect.x += 102; drawRect.x += 102;
drawRect.width = 40; drawRect.width = 40;
EditorGUI.PropertyField(drawRect, m_Column, GUIContent.none); EditorGUI.PropertyField(drawRect, m_Column, GUIContent.none);
var btnWidth = 12;
drawRect.x += 42;
drawRect.width = btnWidth;
if (GUI.Button(drawRect, Styles.iconUp, Styles.invisibleButton))
{
var demo = prop.serializedObject.targetObject as Demo;
var index = GetIndex(prop);
if (index >= 0)
{
Swap(demo.chartModules, index, index - 1);
demo.InitModuleButton();
}
}
drawRect.x += btnWidth + 1;
if (GUI.Button(drawRect, Styles.iconDown, Styles.invisibleButton))
{
var demo = prop.serializedObject.targetObject as Demo;
var index = GetIndex(prop);
if (index >= 0)
{
Swap(demo.chartModules, index, index + 1);
demo.InitModuleButton();
}
}
drawRect.x += btnWidth + 1;
if (GUI.Button(drawRect, Styles.iconAdd, Styles.invisibleButton))
{
var demo = prop.serializedObject.targetObject as Demo;
var index = GetIndex(prop);
if (index >= 0)
{
demo.chartModules.Insert(index + 1, new ChartModule());
demo.InitModuleButton();
}
}
drawRect.x += 16;
if (GUI.Button(drawRect, Styles.iconRemove, Styles.invisibleButton))
{
var demo = prop.serializedObject.targetObject as Demo;
var index = GetIndex(prop);
if (index >= 0)
{
demo.chartModules.RemoveAt(index);
demo.InitModuleButton();
}
}
} }
public override float GetPropertyHeight(SerializedProperty prop, GUIContent label) public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
{ {
return 1 * EditorGUIUtility.singleLineHeight + 1 * EditorGUIUtility.standardVerticalSpacing; return 1 * EditorGUIUtility.singleLineHeight + 1 * EditorGUIUtility.standardVerticalSpacing;
} }
private int GetIndex(SerializedProperty prop)
{
int index = -1;
var sindex = prop.propertyPath.LastIndexOf('[');
var eindex = prop.propertyPath.LastIndexOf(']');
if (sindex >= 0 && eindex >= 0)
{
var str = prop.propertyPath.Substring(sindex + 1, eindex - sindex - 1);
int.TryParse(str, out index);
}
return index;
}
private static bool Swap<T>(List<T> list, int index1, int index2)
{
if (index1 < 0 || index1 >= list.Count) return false;
if (index2 < 0 || index2 >= list.Count) return false;
var temp = list[index1];
list[index1] = list[index2];
list[index2] = temp;
return true;
}
} }
} }

View File

@@ -15,7 +15,7 @@ namespace XChartsDemo
/// </summary> /// </summary>
[CustomEditor(typeof(Demo), false)] [CustomEditor(typeof(Demo), false)]
public class DemoEditor : Editor internal class DemoEditor : Editor
{ {
protected Demo m_Target; protected Demo m_Target;
protected SerializedProperty m_Script; protected SerializedProperty m_Script;

View File

@@ -16,11 +16,11 @@ namespace XChartsDemo
[System.Serializable] [System.Serializable]
public class ChartModule public class ChartModule
{ {
[SerializeField] private string m_Name; [SerializeField] private string m_Name = "Name";
[SerializeField] private string m_SubName; [SerializeField] private string m_SubName = "SubName";
[SerializeField] private int m_Column = 3; [SerializeField] private int m_Column = 3;
[SerializeField] private string m_Title; [SerializeField] private string m_Title = "Title";
[SerializeField] private bool m_Selected; [SerializeField] private bool m_Selected;
[SerializeField] private GameObject m_Panel; [SerializeField] private GameObject m_Panel;
@@ -31,6 +31,7 @@ namespace XChartsDemo
public bool select { get { return m_Selected; } set { m_Selected = value; } } public bool select { get { return m_Selected; } set { m_Selected = value; } }
public GameObject panel { get { return m_Panel; } set { m_Panel = value; } } public GameObject panel { get { return m_Panel; } set { m_Panel = value; } }
public Button button { get; set; } public Button button { get; set; }
public int index { get; internal set; }
} }
[DisallowMultipleComponent] [DisallowMultipleComponent]
@@ -44,6 +45,7 @@ namespace XChartsDemo
[SerializeField] private Color m_ButtonNormalColor; [SerializeField] private Color m_ButtonNormalColor;
[SerializeField] private Color m_ButtonSelectedColor; [SerializeField] private Color m_ButtonSelectedColor;
[SerializeField] private Color m_ButtonHighlightColor; [SerializeField] private Color m_ButtonHighlightColor;
[SerializeField] public int lastSelectedModuleIndex = -1;
[SerializeField] private List<ChartModule> m_ChartModule = new List<ChartModule>(); [SerializeField] private List<ChartModule> m_ChartModule = new List<ChartModule>();
private GameObject m_BtnClone; private GameObject m_BtnClone;
@@ -60,6 +62,8 @@ namespace XChartsDemo
private ScrollRect m_ScrollRect; private ScrollRect m_ScrollRect;
private Mask m_Mark; private Mask m_Mark;
public List<ChartModule> chartModules { get { return m_ChartModule; } }
void Awake() void Awake()
{ {
m_SelectedTheme = Theme.Default; m_SelectedTheme = Theme.Default;
@@ -118,6 +122,7 @@ namespace XChartsDemo
private void SetChartRootInfo(ChartModule module) private void SetChartRootInfo(ChartModule module)
{ {
var chartRoot = module.panel; var chartRoot = module.panel;
if (chartRoot == null) return;
var grid = chartRoot.GetComponent<GridLayoutGroup>(); var grid = chartRoot.GetComponent<GridLayoutGroup>();
var hig = Mathf.CeilToInt(chartRoot.transform.childCount * 1f / module.column) * (grid.cellSize.y + grid.spacing.y); var hig = Mathf.CeilToInt(chartRoot.transform.childCount * 1f / module.column) * (grid.cellSize.y + grid.spacing.y);
SetChartGridLayoutGroup(grid, module.column); SetChartGridLayoutGroup(grid, module.column);
@@ -137,23 +142,6 @@ namespace XChartsDemo
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
if (m_ChartModule.Count <= 0) return; if (m_ChartModule.Count <= 0) return;
int selectedModuleIndex = -1;
for (int i = 0; i < m_ChartModule.Count; i++)
{
if (selectedModuleIndex >= 0 && i > selectedModuleIndex)
{
m_ChartModule[i].select = false;
}
else if (m_ChartModule[i].select)
{
selectedModuleIndex = i;
}
}
if (selectedModuleIndex < 0) selectedModuleIndex = 0;
if (selectedModuleIndex != m_LastSelectedModuleIndex)
{
InitModuleButton();
}
if (!Application.isPlaying) m_Mark.enabled = false; if (!Application.isPlaying) m_Mark.enabled = false;
if (m_LastCheckLeftWidth != m_LeftWidth) if (m_LastCheckLeftWidth != m_LeftWidth)
@@ -164,14 +152,25 @@ namespace XChartsDemo
#endif #endif
} }
void InitModuleButton() public int GetSelectedModule()
{
for (int i = 0; i < m_ChartModule.Count; i++)
{
if (m_ChartModule[i].select) return i;
}
return -1;
}
public void InitModuleButton()
{ {
var btnPanel = transform.Find("chart_list"); var btnPanel = transform.Find("chart_list");
m_BtnClone = transform.Find("btn_clone").gameObject; m_BtnClone = transform.Find("btn_clone").gameObject;
m_BtnClone.SetActive(false); m_BtnClone.SetActive(false);
ChartHelper.HideAllObject(btnPanel); ChartHelper.DestroyAllChildren(btnPanel.transform);
foreach (var module in m_ChartModule) for (int i = 0; i < m_ChartModule.Count; i++)
{ {
var module = m_ChartModule[i];
module.index = i;
var btnName = "btn_" + module.name; var btnName = "btn_" + module.name;
GameObject btn; GameObject btn;
if (btnPanel.Find(btnName)) if (btnPanel.Find(btnName))
@@ -193,19 +192,19 @@ namespace XChartsDemo
module.button.transform.Find("Text").GetComponent<Text>().text = module.name.Replace("\\n", "\n"); module.button.transform.Find("Text").GetComponent<Text>().text = module.name.Replace("\\n", "\n");
module.button.transform.Find("SubText").GetComponent<Text>().text = module.subName.Replace("\\n", "\n"); module.button.transform.Find("SubText").GetComponent<Text>().text = module.subName.Replace("\\n", "\n");
ChartHelper.ClearEventListener(btn.gameObject);
ChartHelper.AddEventListener(btn.gameObject, EventTriggerType.PointerDown, (data) => ChartHelper.AddEventListener(btn.gameObject, EventTriggerType.PointerDown, (data) =>
{ {
ClickModule(module); ClickModule(module);
}); });
} }
for (int i = 0; i < m_ChartModule.Count; i++) for (int i = 0; i < m_ChartModule.Count; i++)
{ {
var module = m_ChartModule[i]; var module = m_ChartModule[i];
module.index = i;
if (module.select) if (module.select)
{ {
ClickModule(module); ClickModule(module);
m_LastSelectedModuleIndex = i;
break; break;
} }
} }
@@ -213,27 +212,37 @@ namespace XChartsDemo
void ClickModule(ChartModule selectedModule) void ClickModule(ChartModule selectedModule)
{ {
if (lastSelectedModuleIndex >= 0)
{
m_ChartModule[lastSelectedModuleIndex].select = false;
}
lastSelectedModuleIndex = selectedModule.index;
foreach (var module in m_ChartModule) foreach (var module in m_ChartModule)
{ {
if (selectedModule != module) if (module.index != lastSelectedModuleIndex)
{ {
var block = module.button.colors; var block = module.button.colors;
block.highlightedColor = m_ButtonHighlightColor; block.highlightedColor = m_ButtonHighlightColor;
block.selectedColor = m_ButtonNormalColor;
block.normalColor = m_ButtonNormalColor; block.normalColor = m_ButtonNormalColor;
module.button.colors = block; module.button.colors = block;
if (module.panel != null)
module.panel.SetActive(false); module.panel.SetActive(false);
module.select = false; //module.select = false;
} }
else else
{ {
var block = module.button.colors; var block = module.button.colors;
block.highlightedColor = m_ButtonSelectedColor; block.highlightedColor = m_ButtonSelectedColor;
block.selectedColor = m_ButtonSelectedColor;
block.normalColor = m_ButtonSelectedColor; block.normalColor = m_ButtonSelectedColor;
module.button.colors = block; module.button.colors = block;
if (module.panel != null)
module.panel.SetActive(true); module.panel.SetActive(true);
module.select = true; // module.select = true;
} }
} }
if (selectedModule.panel != null)
m_ScrollRect.content = selectedModule.panel.GetComponent<RectTransform>(); m_ScrollRect.content = selectedModule.panel.GetComponent<RectTransform>();
SetChartRootInfo(selectedModule); SetChartRootInfo(selectedModule);
m_Title.text = string.IsNullOrEmpty(selectedModule.title) ? m_Title.text = string.IsNullOrEmpty(selectedModule.title) ?

View File

@@ -14,7 +14,7 @@ namespace XChartsDemo
{ {
[DisallowMultipleComponent] [DisallowMultipleComponent]
[ExecuteInEditMode] [ExecuteInEditMode]
public class Demo_Animation : MonoBehaviour internal class Demo_Animation : MonoBehaviour
{ {
[SerializeField] private int m_FadeInDuration = 1000; [SerializeField] private int m_FadeInDuration = 1000;
[SerializeField] private int m_FadeOutDuration = 1000; [SerializeField] private int m_FadeOutDuration = 1000;

View File

@@ -14,7 +14,7 @@ namespace XChartsDemo
{ {
[DisallowMultipleComponent] [DisallowMultipleComponent]
[ExecuteInEditMode] [ExecuteInEditMode]
public class Demo_Performance : MonoBehaviour internal class Demo_Performance : MonoBehaviour
{ {
[SerializeField] private float fps = 0; [SerializeField] private float fps = 0;
[SerializeField] private int m_MaxCacheDataNumber = 3000; [SerializeField] private int m_MaxCacheDataNumber = 3000;

View File

@@ -10,7 +10,7 @@ using UnityEngine.UI;
namespace XChartsDemo namespace XChartsDemo
{ {
public static class UIUtil internal static class UIUtil
{ {
public static RectTransform GetRectTransform(Transform transform, string path) public static RectTransform GetRectTransform(Transform transform, string path)

File diff suppressed because it is too large Load Diff