mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-30 05:08:48 +00:00
[feature][radar] support smooth line
This commit is contained in:
@@ -24,7 +24,7 @@ namespace XCharts.Editor
|
|||||||
PropertyField("m_AxisName");
|
PropertyField("m_AxisName");
|
||||||
PropertyField("m_SplitLine");
|
PropertyField("m_SplitLine");
|
||||||
PropertyField("m_SplitArea");
|
PropertyField("m_SplitArea");
|
||||||
PropertyField("m_IndicatorList");
|
PropertyListField("m_IndicatorList");
|
||||||
--EditorGUI.indentLevel;
|
--EditorGUI.indentLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace XCharts.Editor
|
|||||||
{
|
{
|
||||||
PropertyField("m_RadarType");
|
PropertyField("m_RadarType");
|
||||||
PropertyField("m_RadarIndex");
|
PropertyField("m_RadarIndex");
|
||||||
|
PropertyField("m_Smooth");
|
||||||
|
|
||||||
PropertyField("m_Symbol");
|
PropertyField("m_Symbol");
|
||||||
PropertyField("m_LineStyle");
|
PropertyField("m_LineStyle");
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace XCharts.Runtime
|
|||||||
|
|
||||||
if (!polar.context.isPointerEnter)
|
if (!polar.context.isPointerEnter)
|
||||||
{
|
{
|
||||||
axis.context.pointerValue = double.PositiveInfinity;
|
axis.context.pointerValue = double.NaN;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ namespace XCharts.Runtime
|
|||||||
private void SetTooltipIndicatorLabel(Tooltip tooltip, Axis axis, ChartLabel label)
|
private void SetTooltipIndicatorLabel(Tooltip tooltip, Axis axis, ChartLabel label)
|
||||||
{
|
{
|
||||||
if (label == null) return;
|
if (label == null) return;
|
||||||
if (double.IsPositiveInfinity(axis.context.pointerValue)) return;
|
if (double.IsNaN(axis.context.pointerValue)) return;
|
||||||
label.SetActive(true);
|
label.SetActive(true);
|
||||||
label.SetTextActive(true);
|
label.SetTextActive(true);
|
||||||
label.SetPosition(axis.context.pointerLabelPosition);
|
label.SetPosition(axis.context.pointerLabelPosition);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System;
|
|||||||
|
|
||||||
namespace XCharts.Runtime
|
namespace XCharts.Runtime
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
|
||||||
public class Since : Attribute
|
public class Since : Attribute
|
||||||
{
|
{
|
||||||
public readonly string version;
|
public readonly string version;
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ namespace XCharts.Runtime
|
|||||||
DrawParallelSerie(vh, serie);
|
DrawParallelSerie(vh, serie);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSerieContext()
|
private void UpdateSerieContext() { }
|
||||||
{ }
|
|
||||||
|
|
||||||
private void DrawParallelSerie(VertexHelper vh, Parallel serie)
|
private void DrawParallelSerie(VertexHelper vh, Parallel serie)
|
||||||
{
|
{
|
||||||
@@ -116,7 +115,10 @@ namespace XCharts.Runtime
|
|||||||
lp = pos;
|
lp = pos;
|
||||||
}
|
}
|
||||||
if (isSmooth)
|
if (isSmooth)
|
||||||
UGL.DrawCurves(vh, m_Points, lineWidth, lineColor, chart.settings.lineSmoothness, currProgress, isHorizonal);
|
UGL.DrawCurves(vh, m_Points, lineWidth, lineColor,
|
||||||
|
chart.settings.lineSmoothStyle,
|
||||||
|
chart.settings.lineSmoothness,
|
||||||
|
UGL.Direction.XAxis, currProgress, isHorizonal);
|
||||||
else
|
else
|
||||||
UGL.DrawLine(vh, m_Points, lineWidth, lineColor, isSmooth);
|
UGL.DrawLine(vh, m_Points, lineWidth, lineColor, isSmooth);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,21 @@ namespace XCharts.Runtime
|
|||||||
[SerieDataExtraField()]
|
[SerieDataExtraField()]
|
||||||
public class Radar : Serie, INeedSerieContainer
|
public class Radar : Serie, INeedSerieContainer
|
||||||
{
|
{
|
||||||
|
[SerializeField][Since("3.2.0")] private bool m_Smooth = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether use smooth curve.
|
||||||
|
/// |是否平滑曲线。平滑曲线时不支持区域填充颜色。
|
||||||
|
/// </summary>
|
||||||
|
public bool smooth
|
||||||
|
{
|
||||||
|
get { return m_Smooth; }
|
||||||
|
set { if (PropertyUtil.SetStruct(ref m_Smooth, value)) { SetVerticesDirty(); } }
|
||||||
|
}
|
||||||
|
|
||||||
public int containerIndex { get; internal set; }
|
public int containerIndex { get; internal set; }
|
||||||
public int containterInstanceId { get; internal set; }
|
public int containterInstanceId { get; internal set; }
|
||||||
public override bool useDataNameForColor { get { return true; } }
|
public override bool useDataNameForColor { get { return radarType == RadarType.Multiple; } }
|
||||||
public override bool multiDimensionLabel { get { return radarType == RadarType.Multiple; } }
|
public override bool multiDimensionLabel { get { return radarType == RadarType.Multiple; } }
|
||||||
|
|
||||||
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
|
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
|
||||||
|
|||||||
@@ -262,11 +262,11 @@ namespace XCharts.Runtime
|
|||||||
{
|
{
|
||||||
toPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
|
toPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
|
||||||
centerPos.y + radius * Mathf.Cos(currAngle));
|
centerPos.y + radius * Mathf.Cos(currAngle));
|
||||||
if (areaStyle != null && areaStyle.show)
|
if (areaStyle != null && areaStyle.show && !serie.smooth)
|
||||||
{
|
{
|
||||||
UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
|
UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||||
}
|
}
|
||||||
if (lineStyle.show)
|
if (lineStyle.show && !serie.smooth)
|
||||||
{
|
{
|
||||||
ChartDrawer.DrawLineStyle(vh, lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
|
ChartDrawer.DrawLineStyle(vh, lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
|
||||||
}
|
}
|
||||||
@@ -274,14 +274,24 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
serieData.context.dataPoints.Add(startPoint);
|
serieData.context.dataPoints.Add(startPoint);
|
||||||
}
|
}
|
||||||
if (areaStyle != null && areaStyle.show)
|
if (areaStyle != null && areaStyle.show && !serie.smooth)
|
||||||
{
|
{
|
||||||
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||||
}
|
}
|
||||||
if (lineStyle.show)
|
if (lineStyle.show && !serie.smooth)
|
||||||
{
|
{
|
||||||
ChartDrawer.DrawLineStyle(vh, lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
|
ChartDrawer.DrawLineStyle(vh, lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (serie.smooth)
|
||||||
|
{
|
||||||
|
UGL.DrawCurves(vh, serieData.context.dataPoints, lineWidth, lineColor,
|
||||||
|
chart.settings.lineSmoothStyle,
|
||||||
|
chart.settings.lineSmoothness,
|
||||||
|
UGL.Direction.Random,
|
||||||
|
float.NaN, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (symbol.show && symbol.type != SymbolType.None)
|
if (symbol.show && symbol.type != SymbolType.None)
|
||||||
{
|
{
|
||||||
for (int m = 0; m < serieData.context.dataPoints.Count; m++)
|
for (int m = 0; m < serieData.context.dataPoints.Count; m++)
|
||||||
@@ -394,11 +404,11 @@ namespace XCharts.Runtime
|
|||||||
{
|
{
|
||||||
toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
|
toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
|
||||||
p.y + radius * Mathf.Cos(currAngle));
|
p.y + radius * Mathf.Cos(currAngle));
|
||||||
if (areaStyle != null && areaStyle.show)
|
if (areaStyle != null && areaStyle.show && !serie.smooth)
|
||||||
{
|
{
|
||||||
UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
|
UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
|
||||||
}
|
}
|
||||||
if (lineStyle.show)
|
if (lineStyle.show && !serie.smooth)
|
||||||
{
|
{
|
||||||
if (radar.connectCenter)
|
if (radar.connectCenter)
|
||||||
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, centerPos,
|
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, centerPos,
|
||||||
@@ -409,14 +419,15 @@ namespace XCharts.Runtime
|
|||||||
startPoint = toPoint;
|
startPoint = toPoint;
|
||||||
lastColor = lineColor;
|
lastColor = lineColor;
|
||||||
}
|
}
|
||||||
|
serie.context.dataPoints.Add(startPoint);
|
||||||
serieData.context.position = startPoint;
|
serieData.context.position = startPoint;
|
||||||
serieData.context.labelPosition = startPoint;
|
serieData.context.labelPosition = startPoint;
|
||||||
|
|
||||||
if (areaStyle != null && areaStyle.show && j == endIndex)
|
if (areaStyle != null && areaStyle.show && j == endIndex && !serie.smooth)
|
||||||
{
|
{
|
||||||
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||||
}
|
}
|
||||||
if (lineStyle.show && j == endIndex)
|
if (lineStyle.show && j == endIndex && !serie.smooth)
|
||||||
{
|
{
|
||||||
if (radar.connectCenter)
|
if (radar.connectCenter)
|
||||||
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, centerPos,
|
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, centerPos,
|
||||||
@@ -425,6 +436,16 @@ namespace XCharts.Runtime
|
|||||||
LineStyle.Type.Solid, lineColor, radar.lineGradient ? firstColor : lineColor);
|
LineStyle.Type.Solid, lineColor, radar.lineGradient ? firstColor : lineColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (serie.smooth)
|
||||||
|
{
|
||||||
|
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||||
|
var lineColor = SerieHelper.GetLineColor(serie, null, chart.theme, serie.context.colorIndex, false);
|
||||||
|
UGL.DrawCurves(vh, serie.context.dataPoints, lineWidth, lineColor,
|
||||||
|
chart.settings.lineSmoothStyle,
|
||||||
|
chart.settings.lineSmoothness,
|
||||||
|
UGL.Direction.Random,
|
||||||
|
float.NaN, true);
|
||||||
|
}
|
||||||
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
|
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < serie.data.Count; j++)
|
for (int j = 0; j < serie.data.Count; j++)
|
||||||
|
|||||||
@@ -10,6 +10,24 @@ namespace XUGL
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class UGL
|
public static class UGL
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 曲线方向
|
||||||
|
/// </summary>
|
||||||
|
public enum Direction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沿X轴方向
|
||||||
|
/// </summary>
|
||||||
|
XAxis,
|
||||||
|
/// <summary>
|
||||||
|
/// 沿Y轴方向
|
||||||
|
/// </summary>
|
||||||
|
YAxis,
|
||||||
|
/// <summary>
|
||||||
|
/// 随机无序的。如一个闭合的环状曲线。
|
||||||
|
/// </summary>
|
||||||
|
Random
|
||||||
|
}
|
||||||
private static readonly Color32 s_ClearColor32 = new Color32(0, 0, 0, 0);
|
private static readonly Color32 s_ClearColor32 = new Color32(0, 0, 0, 0);
|
||||||
private static readonly Vector2 s_ZeroVector2 = Vector2.zero;
|
private static readonly Vector2 s_ZeroVector2 = Vector2.zero;
|
||||||
private static UIVertex[] s_Vertex = new UIVertex[4];
|
private static UIVertex[] s_Vertex = new UIVertex[4];
|
||||||
@@ -134,7 +152,7 @@ namespace XUGL
|
|||||||
}
|
}
|
||||||
else if (smooth)
|
else if (smooth)
|
||||||
{
|
{
|
||||||
DrawCurves(vh, points, width, color, 2);
|
DrawCurves(vh, points, width, color, 2, 2, Direction.XAxis, float.NaN, closepath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1752,42 +1770,67 @@ namespace XUGL
|
|||||||
/// <param name="lineWidth">曲线宽</param>
|
/// <param name="lineWidth">曲线宽</param>
|
||||||
/// <param name="lineColor">曲线颜色</param>
|
/// <param name="lineColor">曲线颜色</param>
|
||||||
public static void DrawCurves(VertexHelper vh, Vector3 sp, Vector3 ep, Vector3 cp1, Vector3 cp2,
|
public static void DrawCurves(VertexHelper vh, Vector3 sp, Vector3 ep, Vector3 cp1, Vector3 cp2,
|
||||||
float lineWidth, Color32 lineColor, float smoothness)
|
float lineWidth, Color32 lineColor, float smoothness, Direction dire = Direction.XAxis)
|
||||||
{
|
{
|
||||||
var dist = Vector3.Distance(sp, ep);
|
var dist = Vector3.Distance(sp, ep);
|
||||||
var segment = (int) (dist / (smoothness <= 0 ? 2f : smoothness));
|
var segment = (int) (dist / (smoothness <= 0 ? 2f : smoothness));
|
||||||
UGLHelper.GetBezierList2(ref s_CurvesPosList, sp, ep, segment, cp1, cp2);
|
UGLHelper.GetBezierList2(ref s_CurvesPosList, sp, ep, segment, cp1, cp2);
|
||||||
DrawCurvesInternal(vh, s_CurvesPosList, lineWidth, lineColor);
|
DrawCurvesInternal(vh, s_CurvesPosList, lineWidth, lineColor, dire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 画贝塞尔曲线
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vh"></param>
|
||||||
|
/// <param name="points">坐标点列表</param>
|
||||||
|
/// <param name="width">曲线宽</param>
|
||||||
|
/// <param name="color">曲线颜色</param>
|
||||||
|
/// <param name="smoothStyle">曲线样式</param>
|
||||||
|
/// <param name="smoothness">平滑度</param>
|
||||||
|
/// <param name="dire">曲线方向</param>
|
||||||
|
/// <param name="currProgress">当前绘制进度</param>
|
||||||
|
/// <param name="closed">曲线是否闭合</param>
|
||||||
public static void DrawCurves(VertexHelper vh, List<Vector3> points, float width, Color32 color,
|
public static void DrawCurves(VertexHelper vh, List<Vector3> points, float width, Color32 color,
|
||||||
float smoothness, float currProgress = float.PositiveInfinity, bool isYAxis = false)
|
float smoothStyle, float smoothness, Direction dire, float currProgress = float.NaN,
|
||||||
|
bool closed = false)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < points.Count - 1; i++)
|
var count = points.Count;
|
||||||
|
var size = (closed?count : count - 1);
|
||||||
|
if (closed)
|
||||||
|
dire = Direction.Random;
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
var sp = points[i];
|
var sp = points[i];
|
||||||
var ep = points[i + 1];
|
var ep = closed?(i == size - 1 ? points[0] : points[i + 1]) : points[i + 1];
|
||||||
var lsp = i > 0 ? points[i - 1] : sp;
|
var lsp = i > 0 ? points[i - 1] : (closed?points[count - 1] : sp);
|
||||||
var nep = i < points.Count - 2 ? points[i + 2] : ep;
|
var nep = i < points.Count - 2 ? points[i + 2] : (closed?points[(i + 2) % count] : ep);
|
||||||
var smoothness2 = smoothness;
|
var smoothness2 = smoothness;
|
||||||
if (currProgress != float.PositiveInfinity)
|
if (currProgress != float.NaN)
|
||||||
{
|
{
|
||||||
if (isYAxis)
|
switch (dire)
|
||||||
smoothness2 = ep.y <= currProgress ? smoothness : smoothness * 0.5f;
|
{
|
||||||
else
|
case Direction.XAxis:
|
||||||
smoothness2 = ep.x <= currProgress ? smoothness : smoothness * 0.5f;
|
smoothness2 = ep.x <= currProgress ? smoothness : smoothness * 0.5f;
|
||||||
|
break;
|
||||||
|
case Direction.YAxis:
|
||||||
|
smoothness2 = ep.y <= currProgress ? smoothness : smoothness * 0.5f;
|
||||||
|
break;
|
||||||
|
case Direction.Random:
|
||||||
|
smoothness2 = smoothness * 0.5f;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (isYAxis)
|
}
|
||||||
UGLHelper.GetBezierListVertical(ref s_CurvesPosList, sp, ep, smoothness2);
|
if (dire == Direction.YAxis)
|
||||||
|
UGLHelper.GetBezierListVertical(ref s_CurvesPosList, sp, ep, smoothness2, smoothStyle);
|
||||||
else
|
else
|
||||||
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness2);
|
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness2, smoothStyle);
|
||||||
|
|
||||||
DrawCurvesInternal(vh, s_CurvesPosList, width, color, currProgress, isYAxis);
|
DrawCurvesInternal(vh, s_CurvesPosList, width, color, dire, currProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawCurvesInternal(VertexHelper vh, List<Vector3> curvesPosList, float lineWidth,
|
private static void DrawCurvesInternal(VertexHelper vh, List<Vector3> curvesPosList, float lineWidth,
|
||||||
Color32 lineColor, float currProgress = float.PositiveInfinity, bool isYAxis = false)
|
Color32 lineColor, Direction dire, float currProgress = float.NaN)
|
||||||
{
|
{
|
||||||
if (curvesPosList.Count > 1)
|
if (curvesPosList.Count > 1)
|
||||||
{
|
{
|
||||||
@@ -1805,11 +1848,11 @@ namespace XUGL
|
|||||||
for (int i = 1; i < curvesPosList.Count; i++)
|
for (int i = 1; i < curvesPosList.Count; i++)
|
||||||
{
|
{
|
||||||
to = curvesPosList[i];
|
to = curvesPosList[i];
|
||||||
if (currProgress != float.PositiveInfinity)
|
if (currProgress != float.NaN)
|
||||||
{
|
{
|
||||||
if (isYAxis && to.y > currProgress)
|
if (dire == Direction.YAxis && to.y > currProgress)
|
||||||
break;
|
break;
|
||||||
if (!isYAxis && to.x > currProgress)
|
if (dire == Direction.XAxis && to.x > currProgress)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,22 +110,21 @@ namespace XUGL
|
|||||||
public static void GetBezierList(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
|
public static void GetBezierList(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
|
||||||
Vector3 lsp, Vector3 nep, float smoothness = 2f, float k = 2.0f, bool limit = false)
|
Vector3 lsp, Vector3 nep, float smoothness = 2f, float k = 2.0f, bool limit = false)
|
||||||
{
|
{
|
||||||
float dist = Mathf.Abs(sp.x - ep.x);
|
var dist = Vector3.Distance(sp, ep);
|
||||||
Vector3 cp1, cp2;
|
Vector3 cp1, cp2;
|
||||||
var dir = (ep - sp).normalized;
|
var dir = (ep - sp).normalized;
|
||||||
var diff = dist / k;
|
var diff = dist / k;
|
||||||
if (lsp == sp)
|
if (lsp == sp)
|
||||||
{
|
{
|
||||||
cp1 = sp + dist / k * dir * 1;
|
cp1 = sp + (nep - ep).normalized * diff;
|
||||||
|
if (limit)
|
||||||
cp1.y = sp.y;
|
cp1.y = sp.y;
|
||||||
cp1 = sp;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cp1 = sp + (ep - lsp).normalized * diff;
|
cp1 = sp + (ep - lsp).normalized * diff;
|
||||||
if (limit)
|
if (limit)
|
||||||
cp1.y = sp.y;
|
cp1.y = sp.y;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (nep == ep)
|
if (nep == ep)
|
||||||
{
|
{
|
||||||
@@ -137,7 +136,6 @@ namespace XUGL
|
|||||||
if (limit)
|
if (limit)
|
||||||
cp2.y = ep.y;
|
cp2.y = ep.y;
|
||||||
}
|
}
|
||||||
dist = Vector3.Distance(sp, ep);
|
|
||||||
int segment = (int) (dist / (smoothness <= 0 ? 2f : smoothness));
|
int segment = (int) (dist / (smoothness <= 0 ? 2f : smoothness));
|
||||||
if (segment < 1) segment = (int) (dist / 0.5f);
|
if (segment < 1) segment = (int) (dist / 0.5f);
|
||||||
if (segment < 4) segment = 4;
|
if (segment < 4) segment = 4;
|
||||||
|
|||||||
Reference in New Issue
Block a user