UI update 02

This commit is contained in:
FloatGaming
2026-06-30 21:21:30 +08:00
parent b2a1e307a4
commit f62f643cfc
1666 changed files with 211081 additions and 22799 deletions
@@ -0,0 +1,275 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(CanvasRenderer))]
public class UIRadarGraphic : MaskableGraphic
{
private const float MainStrokeWidth = 2.5f;
private const float ReferenceStrokeWidth = 2f;
private const float MainPointSize = 8f;
private const float ReferencePointSize = 7f;
private readonly List<URadarAxisEntry> axisEntries = new List<URadarAxisEntry>();
private float minValue;
private float maxValue = 100f;
private int splitCount = 5;
private bool showReferenceSeries;
private Color gridLineColor = new Color32(255, 255, 255, 180);
private Color outerGridLineColor = Color.white;
private float gridLineWidth = 2f;
private Color mainStrokeColor = new Color32(82, 126, 255, 255);
private Color mainFillColor = new Color(82f / 255f, 126f / 255f, 255f / 255f, 0.28f);
private Color mainPointColor = Color.white;
private Color referenceStrokeColor = new Color32(72, 229, 229, 255);
private Color referenceFillColor = new Color(72f / 255f, 229f / 255f, 229f / 255f, 0.22f);
private Color referencePointColor = Color.white;
private float radarPlotPadding = 8f;
private float radarInnerRadius;
private float radarLabelRadialOffset;
public void SetData(
List<URadarAxisEntry> sourceAxes,
float sourceMinValue,
float sourceMaxValue,
int sourceSplitCount,
bool sourceShowReferenceSeries,
Color sourceGridLineColor,
Color sourceOuterGridLineColor,
float sourceGridLineWidth,
Color sourceMainStrokeColor,
Color sourceMainFillColor,
Color sourceMainPointColor,
Color sourceReferenceStrokeColor,
Color sourceReferenceFillColor,
Color sourceReferencePointColor,
float sourceRadarPlotPadding,
float sourceRadarInnerRadius,
float sourceRadarLabelRadialOffset)
{
axisEntries.Clear();
if (sourceAxes != null)
{
for (int i = 0; i < sourceAxes.Count; i++)
{
URadarAxisEntry source = sourceAxes[i];
if (source == null)
{
axisEntries.Add(new URadarAxisEntry());
continue;
}
axisEntries.Add(new URadarAxisEntry
{
label = source.label,
value = source.value,
referenceValue = source.referenceValue
});
}
}
minValue = sourceMinValue;
maxValue = Mathf.Max(sourceMinValue + 0.0001f, sourceMaxValue);
splitCount = Mathf.Max(2, sourceSplitCount);
showReferenceSeries = sourceShowReferenceSeries;
gridLineColor = sourceGridLineColor;
outerGridLineColor = sourceOuterGridLineColor;
gridLineWidth = Mathf.Max(0.1f, sourceGridLineWidth);
mainStrokeColor = sourceMainStrokeColor;
mainFillColor = sourceMainFillColor;
mainPointColor = sourceMainPointColor;
referenceStrokeColor = sourceReferenceStrokeColor;
referenceFillColor = sourceReferenceFillColor;
referencePointColor = sourceReferencePointColor;
radarPlotPadding = Mathf.Max(0f, sourceRadarPlotPadding);
radarInnerRadius = Mathf.Max(0f, sourceRadarInnerRadius);
radarLabelRadialOffset = sourceRadarLabelRadialOffset;
SetVerticesDirty();
}
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
if (axisEntries.Count < 3)
{
return;
}
Rect rect = GetPixelAdjustedRect();
Vector2 center = rect.center;
float maxRadius = Mathf.Max(0f, Mathf.Min(rect.width, rect.height) * 0.5f - radarPlotPadding - Mathf.Max(MainPointSize, ReferencePointSize));
float innerRadius = Mathf.Clamp(radarInnerRadius, 0f, maxRadius * 0.8f);
DrawGrid(vh, center, innerRadius, maxRadius);
List<Vector2> mainPoints = BuildSeriesPoints(center, innerRadius, maxRadius, false);
if (showReferenceSeries)
{
List<Vector2> referencePoints = BuildSeriesPoints(center, innerRadius, maxRadius, true);
DrawFilledPolygon(vh, center, referencePoints, referenceFillColor);
DrawPolyline(vh, referencePoints, true, ReferenceStrokeWidth, referenceStrokeColor);
DrawPointMarkers(vh, referencePoints, ReferencePointSize, referencePointColor);
}
DrawFilledPolygon(vh, center, mainPoints, mainFillColor);
DrawPolyline(vh, mainPoints, true, MainStrokeWidth, mainStrokeColor);
DrawPointMarkers(vh, mainPoints, MainPointSize, mainPointColor);
}
private void DrawGrid(VertexHelper vh, Vector2 center, float innerRadius, float maxRadius)
{
int axisCount = axisEntries.Count;
for (int ring = 1; ring <= splitCount; ring++)
{
float t = ring / (float)splitCount;
float radius = Mathf.Lerp(innerRadius, maxRadius, t);
List<Vector2> ringPoints = new List<Vector2>(axisCount);
for (int i = 0; i < axisCount; i++)
{
ringPoints.Add(GetAxisPoint(center, radius, i, axisCount));
}
DrawPolyline(vh, ringPoints, true, gridLineWidth, ring == splitCount ? outerGridLineColor : gridLineColor);
}
for (int i = 0; i < axisCount; i++)
{
Vector2 start = GetAxisPoint(center, innerRadius, i, axisCount);
Vector2 end = GetAxisPoint(center, maxRadius, i, axisCount);
DrawLine(vh, start, end, gridLineWidth, gridLineColor);
}
}
private List<Vector2> BuildSeriesPoints(Vector2 center, float innerRadius, float maxRadius, bool useReferenceValue)
{
int axisCount = axisEntries.Count;
List<Vector2> points = new List<Vector2>(axisCount);
for (int i = 0; i < axisCount; i++)
{
URadarAxisEntry entry = axisEntries[i];
float value = useReferenceValue ? entry.referenceValue : entry.value;
float normalized = Mathf.InverseLerp(minValue, maxValue, Mathf.Clamp(value, minValue, maxValue));
float radius = Mathf.Lerp(innerRadius, maxRadius, normalized);
points.Add(GetAxisPoint(center, radius, i, axisCount));
}
return points;
}
private static Vector2 GetAxisPoint(Vector2 center, float radius, int axisIndex, int axisCount)
{
float angle = Mathf.PI * 0.5f - (Mathf.PI * 2f / axisCount) * axisIndex;
return center + new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * radius;
}
private static void DrawFilledPolygon(VertexHelper vh, Vector2 center, List<Vector2> points, Color color)
{
if (points == null || points.Count < 3 || color.a <= 0f)
{
return;
}
int startIndex = vh.currentVertCount;
UIVertex centerVertex = UIVertex.simpleVert;
centerVertex.color = color;
centerVertex.position = center;
vh.AddVert(centerVertex);
for (int i = 0; i < points.Count; i++)
{
UIVertex vertex = UIVertex.simpleVert;
vertex.color = color;
vertex.position = points[i];
vh.AddVert(vertex);
}
for (int i = 0; i < points.Count; i++)
{
int current = startIndex + 1 + i;
int next = startIndex + 1 + ((i + 1) % points.Count);
vh.AddTriangle(startIndex, current, next);
}
}
private static void DrawPolyline(VertexHelper vh, List<Vector2> points, bool closed, float thickness, Color color)
{
if (points == null || points.Count < 2 || color.a <= 0f || thickness <= 0f)
{
return;
}
for (int i = 0; i < points.Count - 1; i++)
{
DrawLine(vh, points[i], points[i + 1], thickness, color);
}
if (closed)
{
DrawLine(vh, points[points.Count - 1], points[0], thickness, color);
}
}
private static void DrawLine(VertexHelper vh, Vector2 start, Vector2 end, float thickness, Color color)
{
Vector2 delta = end - start;
if (delta.sqrMagnitude <= 0.0001f)
{
return;
}
Vector2 normal = new Vector2(-delta.y, delta.x).normalized * (thickness * 0.5f);
int index = vh.currentVertCount;
UIVertex vertex = UIVertex.simpleVert;
vertex.color = color;
vertex.position = start - normal;
vh.AddVert(vertex);
vertex.position = start + normal;
vh.AddVert(vertex);
vertex.position = end + normal;
vh.AddVert(vertex);
vertex.position = end - normal;
vh.AddVert(vertex);
vh.AddTriangle(index, index + 1, index + 2);
vh.AddTriangle(index, index + 2, index + 3);
}
private static void DrawPointMarkers(VertexHelper vh, List<Vector2> points, float size, Color color)
{
if (points == null || color.a <= 0f || size <= 0f)
{
return;
}
float half = size * 0.5f;
for (int i = 0; i < points.Count; i++)
{
DrawQuad(vh, points[i], new Vector2(half, half), color);
}
}
private static void DrawQuad(VertexHelper vh, Vector2 center, Vector2 halfSize, Color color)
{
int index = vh.currentVertCount;
UIVertex vertex = UIVertex.simpleVert;
vertex.color = color;
vertex.position = new Vector2(center.x - halfSize.x, center.y - halfSize.y);
vh.AddVert(vertex);
vertex.position = new Vector2(center.x - halfSize.x, center.y + halfSize.y);
vh.AddVert(vertex);
vertex.position = new Vector2(center.x + halfSize.x, center.y + halfSize.y);
vh.AddVert(vertex);
vertex.position = new Vector2(center.x + halfSize.x, center.y - halfSize.y);
vh.AddVert(vertex);
vh.AddTriangle(index, index + 1, index + 2);
vh.AddTriangle(index, index + 2, index + 3);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a3ca4e8566bf67d45a1c44b84dbb88dd
@@ -1,12 +1,16 @@
using System.Collections.Generic;
using EasyChart;
using EasyChart.UGUI;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using XCharts.Runtime;
public class URadarChartController : MonoBehaviour
{
[Header("Chart")]
[Header("Legacy Compatibility")]
public UGUIChartBridge chartBridge;
[Header("Chart")]
public bool rebuildOnEnable = true;
public bool showReferenceSeries = false;
public int enforcedSortOrder = 0;
@@ -62,6 +66,11 @@ public class URadarChartController : MonoBehaviour
[Header("Style")]
public bool overrideSeriesStyle = true;
public bool overrideSymbolStyle = true;
public float mainSymbolSize = 8f;
public float referenceSymbolSize = 7f;
public SymbolType mainSymbolType = SymbolType.Circle;
public SymbolType referenceSymbolType = SymbolType.Circle;
public Color mainStrokeColor = new Color32(82, 126, 255, 255);
public Color mainFillColor = new Color(82f / 255f, 126f / 255f, 255f / 255f, 0.28f);
public Color mainPointColor = Color.white;
@@ -72,15 +81,34 @@ public class URadarChartController : MonoBehaviour
[Min(0f)] public float radarInnerRadius = 0f;
[Min(0f)] public float radarLabelRadialOffset = 0f;
private ChartProfile sourceProfile;
private ChartProfile runtimeProfile;
private ChartTheme runtimeTheme;
[Header("Legacy Serialized Fields")]
[SerializeField] private UIRadarGraphic radarGraphic;
[SerializeField] private RectTransform labelRoot;
[SerializeField] private bool autoCreateLabelRoot = true;
[SerializeField] private string labelRootName = "RadarLabels";
[Header("XCharts Runtime")]
[SerializeField] private RectTransform radarChartHost;
[SerializeField] private string radarChartHostName = "RadarChartHost";
[SerializeField] private RadarChart radarChart;
private bool rebuildQueued;
private bool chartInitialized;
public bool IsRendererReady
{
get
{
EnsureRenderer();
return radarChart != null;
}
}
private void Awake()
{
showReferenceSeries = false;
NormalizeAxes();
EnsureRenderer();
QueueRebuild();
}
@@ -88,6 +116,7 @@ public class URadarChartController : MonoBehaviour
{
showReferenceSeries = false;
NormalizeAxes();
EnsureRenderer();
if (rebuildOnEnable)
{
QueueRebuild();
@@ -111,27 +140,15 @@ public class URadarChartController : MonoBehaviour
gridLineWidth = Mathf.Max(0.1f, gridLineWidth);
radarInnerRadius = Mathf.Max(0f, radarInnerRadius);
radarLabelRadialOffset = Mathf.Max(0f, radarLabelRadialOffset);
mainSymbolSize = Mathf.Max(0f, mainSymbolSize);
referenceSymbolSize = Mathf.Max(0f, referenceSymbolSize);
tooltipBorderWidth = Mathf.Max(0f, tooltipBorderWidth);
tooltipCornerRadius = Mathf.Max(0f, tooltipCornerRadius);
axisCount = Mathf.Max(3, axisCount);
EnsureRenderer(false);
QueueRebuild();
}
private void OnDestroy()
{
if (runtimeProfile != null)
{
DestroyImmediate(runtimeProfile);
runtimeProfile = null;
}
if (runtimeTheme != null)
{
DestroyImmediate(runtimeTheme);
runtimeTheme = null;
}
}
public void QueueRebuild()
{
rebuildQueued = true;
@@ -203,6 +220,35 @@ public class URadarChartController : MonoBehaviour
NormalizeAxes();
}
public void EnsureRenderer(bool initializeChart = true)
{
DisableLegacyRenderer();
EnsureChartHost();
if (radarChart == null)
{
radarChart = radarChartHost != null ? radarChartHost.GetComponent<RadarChart>() : null;
}
if (radarChart == null && radarChartHost != null)
{
radarChart = radarChartHost.gameObject.AddComponent<RadarChart>();
}
if (radarChart != null)
{
radarChart.enabled = true;
radarChart.gameObject.SetActive(true);
}
if (initializeChart)
{
EnsureChartInitialized();
}
EnsureRuntimeChartStyle();
}
private bool TryGetAxis(int index, out URadarAxisEntry axis)
{
NormalizeAxes();
@@ -218,243 +264,368 @@ public class URadarChartController : MonoBehaviour
private void TryRebuild()
{
if (chartBridge == null || chartBridge.Profile == null)
EnsureRenderer();
if (radarChart == null)
{
return;
}
if (sourceProfile == null)
{
sourceProfile = chartBridge.Profile;
}
if (sourceProfile == null)
{
return;
}
EnsureRuntimeProfile();
EnsureBridgePriority();
ConfigureRuntimeProfile();
chartBridge.Refresh();
ApplyRuntimeTheme();
ApplyRendererState();
rebuildQueued = false;
}
private void EnsureRuntimeProfile()
{
if (runtimeProfile != null)
{
if (!ReferenceEquals(chartBridge.Profile, runtimeProfile))
{
chartBridge.Profile = runtimeProfile;
}
return;
}
runtimeProfile = Instantiate(sourceProfile);
runtimeProfile.name = sourceProfile.name + "_URadar_Runtime";
runtimeProfile.hideFlags = HideFlags.DontSave;
chartBridge.Profile = runtimeProfile;
}
private void EnsureBridgePriority()
{
if (chartBridge != null && chartBridge.SortOrder < enforcedSortOrder)
{
chartBridge.SortOrder = enforcedSortOrder;
}
}
private void ConfigureRuntimeProfile()
private void ApplyRendererState()
{
NormalizeAxes();
EnsureChartInitialized();
runtimeProfile.coordinateSystem = CoordinateSystemType.Polar2D;
runtimeProfile.EnsureRuntimeData();
radarChart.RemoveChartComponents<RadarCoord>();
radarChart.RemoveData();
runtimeProfile.polarAxes.angleAxis.labels = BuildLabels();
runtimeProfile.polarAxes.angleAxis.visible = true;
runtimeProfile.polarAxes.angleAxis.showLabels = true;
if (runtimeProfile.polarAxes.angleAxis.labelStyle == null)
RadarCoord radarCoord = radarChart.AddChartComponent<RadarCoord>();
if (radarCoord == null)
{
runtimeProfile.polarAxes.angleAxis.labelStyle = new LabelStyleSettings();
}
runtimeProfile.polarAxes.angleAxis.labelStyle.enabled = true;
runtimeProfile.polarAxes.radiusAxis.visible = true;
runtimeProfile.polarAxes.radiusAxis.autoRangeMin = false;
runtimeProfile.polarAxes.radiusAxis.autoRangeMax = false;
runtimeProfile.polarAxes.radiusAxis.minValue = minValue;
runtimeProfile.polarAxes.radiusAxis.maxValue = Mathf.Max(minValue + 1f, maxValue);
runtimeProfile.polarAxes.radiusAxis.splitCount = Mathf.Max(2, splitCount);
if (runtimeProfile.polarAxes.radiusAxis.labelStyle == null)
{
runtimeProfile.polarAxes.radiusAxis.labelStyle = new LabelStyleSettings();
}
runtimeProfile.polarAxes.radiusAxis.labelStyle.enabled = runtimeProfile.polarAxes.radiusAxis.showLabels;
if (overrideGridStyle)
{
runtimeProfile.polarAxes.angleAxis.color = gridLineColor;
runtimeProfile.polarAxes.angleAxis.width = gridLineWidth;
runtimeProfile.polarAxes.radiusAxis.color = gridLineColor;
runtimeProfile.polarAxes.radiusAxis.edgeColor = outerGridLineColor;
runtimeProfile.polarAxes.radiusAxis.width = gridLineWidth;
return;
}
if (overrideLabelStyle)
{
runtimeProfile.polarAxes.angleAxis.labelColor = axisLabelColor;
runtimeProfile.polarAxes.angleAxis.fontSize = axisLabelFontSize;
runtimeProfile.polarAxes.angleAxis.labelOffset = axisLabelOffset;
runtimeProfile.polarAxes.angleAxis.labelStyle.fontSize = axisLabelFontSize;
runtimeProfile.polarAxes.angleAxis.labelStyle.color = axisLabelColor;
runtimeProfile.polarAxes.angleAxis.labelStyle.offset = axisLabelOffset;
radarCoord.indicatorList.Clear();
runtimeProfile.polarAxes.radiusAxis.labelColor = axisLabelColor;
runtimeProfile.polarAxes.radiusAxis.fontSize = axisLabelFontSize;
runtimeProfile.polarAxes.radiusAxis.labelStyle.fontSize = axisLabelFontSize;
runtimeProfile.polarAxes.radiusAxis.labelStyle.color = axisLabelColor;
float clampedMin = Mathf.Min(minValue, maxValue - 0.0001f);
float clampedMax = Mathf.Max(minValue + 0.0001f, maxValue);
for (int i = 0; i < axes.Count; i++)
{
string label = string.IsNullOrWhiteSpace(axes[i].label) ? $"Axis {i + 1}" : axes[i].label.Trim();
radarCoord.AddIndicator(label, clampedMin, clampedMax);
}
if (runtimeProfile.series == null)
ConfigureRadarCoord(radarCoord);
Radar mainSerie = radarChart.AddSerie<Radar>(mainSeriesName);
if (mainSerie != null)
{
runtimeProfile.series = new List<Serie>();
mainSerie.radarIndex = radarCoord.index;
}
ConfigureSerie(mainSerie, true);
if (mainSerie != null)
{
radarChart.AddData(mainSerie.index, BuildDataValues(false), mainSeriesName);
}
int targetSeriesCount = 1;
while (runtimeProfile.series.Count < targetSeriesCount)
if (showReferenceSeries)
{
runtimeProfile.series.Add(new Serie());
Radar referenceSerie = radarChart.AddSerie<Radar>(referenceSeriesName);
if (referenceSerie != null)
{
referenceSerie.radarIndex = radarCoord.index;
}
ConfigureSerie(referenceSerie, false);
if (referenceSerie != null)
{
radarChart.AddData(referenceSerie.index, BuildDataValues(true), referenceSeriesName);
}
}
while (runtimeProfile.series.Count > targetSeriesCount)
{
runtimeProfile.series.RemoveAt(runtimeProfile.series.Count - 1);
}
ConfigureSeries(runtimeProfile.series[0], mainSeriesName, true);
runtimeProfile.EnsureRuntimeData();
RefreshLegendAndTooltip();
radarChart.RefreshChart();
}
private void ApplyRuntimeTheme()
private void ConfigureRadarCoord(RadarCoord radarCoord)
{
if (chartBridge == null || chartBridge.ChartElement == null)
RectTransform rectTransform = transform as RectTransform;
float minRectSize = rectTransform == null ? 0f : Mathf.Min(rectTransform.rect.width, rectTransform.rect.height);
float reservedRadius = Mathf.Max(0f, radarPlotPadding);
float computedRadius = minRectSize > 0f
? Mathf.Max(0f, (minRectSize * 0.5f) - reservedRadius - Mathf.Max(0f, radarLabelRadialOffset))
: 0f;
float xchartsRadius = minRectSize > 0f ? Mathf.Clamp01(computedRadius / minRectSize) : 0.35f;
if (xchartsRadius <= 0f)
{
return;
xchartsRadius = 0.35f;
}
bool useTooltipStyle = overrideTooltipStyle;
bool useTooltipFont = overrideTooltipFont && tooltipFont != null;
bool useLabelFont = overrideLabelFont && axisLabelFont != null;
radarCoord.show = true;
radarCoord.shape = RadarCoord.Shape.Polygon;
radarCoord.splitNumber = Mathf.Max(2, splitCount);
radarCoord.center[0] = 0.5f;
radarCoord.center[1] = 0.5f;
radarCoord.radius = xchartsRadius;
radarCoord.indicator = true;
radarCoord.indicatorGap = radarLabelRadialOffset;
radarCoord.positionType = RadarCoord.PositionType.Vertice;
radarCoord.isAxisTooltip = false;
radarCoord.startAngle = 0f;
if (!useLabelFont && !useTooltipFont && !useTooltipStyle)
{
chartBridge.ChartElement.Theme = null;
return;
}
Color innerGrid = overrideGridStyle ? gridLineColor : new Color32(255, 255, 255, 180);
Color outerGrid = overrideGridStyle ? outerGridLineColor : Color.white;
Color effectiveLabelColor = overrideLabelStyle ? axisLabelColor : Color.white;
Vector2 effectiveLabelOffset = overrideLabelStyle ? axisLabelOffset : Vector2.zero;
Font effectiveLabelFont = overrideLabelFont && axisLabelFont != null ? axisLabelFont : axisLabelFont;
if (runtimeTheme == null)
{
runtimeTheme = ScriptableObject.CreateInstance<ChartTheme>();
runtimeTheme.name = "URadar_RuntimeTheme";
runtimeTheme.hideFlags = HideFlags.DontSave;
}
radarCoord.axisLine.show = true;
radarCoord.axisLine.lineStyle.show = true;
radarCoord.axisLine.lineStyle.type = LineStyle.Type.Solid;
radarCoord.axisLine.lineStyle.width = gridLineWidth;
radarCoord.axisLine.lineStyle.color = innerGrid;
runtimeTheme.primaryFont = useLabelFont ? axisLabelFont : null;
runtimeTheme.axisFontSize = useLabelFont ? axisLabelFontSize : -1f;
runtimeTheme.tooltipFont = useTooltipFont ? tooltipFont : null;
runtimeTheme.tooltipFontSize = (useTooltipFont || useTooltipStyle) ? tooltipFontSize : -1f;
runtimeTheme.tooltipTextColor = useTooltipStyle ? tooltipTextColor : Color.white;
runtimeTheme.tooltipBackgroundColor = useTooltipStyle ? tooltipBackgroundColor : new Color(0f, 0f, 0f, 0.8f);
runtimeTheme.tooltipBorderColor = useTooltipStyle ? tooltipBorderColor : new Color(0f, 0f, 0f, 0f);
runtimeTheme.tooltipBorderWidth = useTooltipStyle ? tooltipBorderWidth : 0f;
runtimeTheme.tooltipCornerRadius = useTooltipStyle ? tooltipCornerRadius : 4f;
runtimeTheme.tooltipPadding = useTooltipStyle ? tooltipPadding : new Vector4(8f, 8f, 4f, 4f);
radarCoord.splitLine.show = true;
radarCoord.splitLine.lineStyle.show = true;
radarCoord.splitLine.lineStyle.type = LineStyle.Type.Solid;
radarCoord.splitLine.lineStyle.width = gridLineWidth;
radarCoord.splitLine.lineStyle.color = outerGrid;
// Force ChartElement.Theme setter to re-apply tooltip visuals even when reusing the same runtime theme instance.
chartBridge.ChartElement.Theme = null;
chartBridge.ChartElement.Theme = runtimeTheme;
radarCoord.splitArea.show = false;
radarCoord.axisName.show = true;
radarCoord.axisName.name = null;
radarCoord.axisName.labelStyle.show = true;
radarCoord.axisName.labelStyle.textStyle.autoColor = false;
radarCoord.axisName.labelStyle.textStyle.color = effectiveLabelColor;
radarCoord.axisName.labelStyle.textStyle.fontSize = axisLabelFontSize;
radarCoord.axisName.labelStyle.textStyle.font = effectiveLabelFont;
radarCoord.axisName.labelStyle.textStyle.autoAlign = false;
radarCoord.axisName.labelStyle.textStyle.alignment = TextAnchor.MiddleCenter;
radarCoord.axisName.labelStyle.offset = new Vector3(effectiveLabelOffset.x, effectiveLabelOffset.y, 0f);
radarCoord.axisName.labelStyle.width = 140f;
radarCoord.axisName.labelStyle.height = Mathf.Max(24f, axisLabelFontSize + 10f);
radarCoord.SetVerticesDirty();
}
private void ConfigureSeries(Serie serie, string serieName, bool isMainSeries)
private void ConfigureSerie(Radar serie, bool isMainSerie)
{
if (serie == null)
{
return;
}
serie.name = string.IsNullOrWhiteSpace(serieName) ? (isMainSeries ? "Player" : "Reference") : serieName.Trim();
serie.visible = true;
if (serie.type != SerieType.Radar)
serie.radarType = RadarType.Multiple;
serie.showDataName = false;
serie.symbol.show = true;
if (overrideSymbolStyle)
{
serie.SetType(SerieType.Radar);
}
if (!(serie.settings is RadarSettings radarSettings))
{
radarSettings = new RadarSettings();
serie.settings = radarSettings;
}
radarSettings.radar.innerRadius = radarInnerRadius;
radarSettings.radar.outerRadius = 0f;
radarSettings.radar.plot.padding = radarPlotPadding;
radarSettings.radar.plot.labelRadialOffset = radarLabelRadialOffset;
radarSettings.area.show = true;
radarSettings.point.show = true;
if (overrideSeriesStyle)
{
radarSettings.stroke.color = isMainSeries ? mainStrokeColor : referenceStrokeColor;
radarSettings.stroke.width = isMainSeries ? 2.5f : 2f;
radarSettings.area.textureFill.color = isMainSeries ? mainFillColor : referenceFillColor;
radarSettings.point.textureFill.color = isMainSeries ? mainPointColor : referencePointColor;
radarSettings.point.size = isMainSeries ? 8f : 7f;
}
if (serie.labelSettings != null)
{
serie.labelSettings.enabled = false;
}
if (serie.seriesData == null)
{
serie.seriesData = new List<SeriesData>();
serie.symbol.type = isMainSerie ? mainSymbolType : referenceSymbolType;
serie.symbol.size = isMainSerie ? mainSymbolSize : referenceSymbolSize;
serie.symbol.color = isMainSerie ? mainPointColor : referencePointColor;
}
else
{
serie.seriesData.Clear();
serie.symbol.type = SymbolType.Circle;
serie.symbol.size = isMainSerie ? 8f : 7f;
serie.symbol.color = Color.white;
}
for (int i = 0; i < axisCount; i++)
serie.lineStyle.show = true;
serie.lineStyle.type = LineStyle.Type.Solid;
serie.lineStyle.width = isMainSerie ? 2.5f : 2f;
serie.lineStyle.color = isMainSerie
? (overrideSeriesStyle ? mainStrokeColor : new Color32(82, 126, 255, 255))
: (overrideSeriesStyle ? referenceStrokeColor : new Color32(72, 229, 229, 255));
AreaStyle areaStyle = serie.EnsureComponent<AreaStyle>();
areaStyle.show = true;
areaStyle.color = isMainSerie
? (overrideSeriesStyle ? mainFillColor : new Color(82f / 255f, 126f / 255f, 1f, 0.28f))
: (overrideSeriesStyle ? referenceFillColor : new Color(72f / 255f, 229f / 255f, 229f / 255f, 0.22f));
areaStyle.toColor = Color.clear;
areaStyle.opacity = 1f;
LabelStyle labelStyle = serie.EnsureComponent<LabelStyle>();
labelStyle.show = false;
}
private List<double> BuildDataValues(bool useReferenceValue)
{
List<double> values = new List<double>(axes.Count);
for (int i = 0; i < axes.Count; i++)
{
URadarAxisEntry axis = axes[i];
float value = isMainSeries ? axis.value : axis.referenceValue;
serie.seriesData.Add(new SeriesData
float raw = useReferenceValue ? axes[i].referenceValue : axes[i].value;
values.Add(Mathf.Clamp(raw, minValue, maxValue));
}
return values;
}
private void RefreshLegendAndTooltip()
{
Legend legend = radarChart.GetChartComponent<Legend>();
if (legend != null)
{
legend.show = false;
legend.data.Clear();
}
Title title = radarChart.GetChartComponent<Title>();
if (title != null)
{
title.show = false;
title.text = string.Empty;
title.subText = string.Empty;
}
XCharts.Runtime.Background background = radarChart.GetChartComponent<XCharts.Runtime.Background>();
if (background != null)
{
background.show = false;
}
Tooltip tooltip = radarChart.GetChartComponent<Tooltip>();
if (tooltip == null)
{
return;
}
tooltip.show = false;
tooltip.showContent = false;
tooltip.type = Tooltip.Type.None;
tooltip.trigger = Tooltip.Trigger.None;
if (overrideTooltipStyle)
{
tooltip.backgroundColor = tooltipBackgroundColor;
tooltip.borderColor = tooltipBorderColor;
tooltip.borderWidth = tooltipBorderWidth;
tooltip.paddingLeftRight = Mathf.RoundToInt(Mathf.Max(0f, tooltipPadding.x));
tooltip.paddingTopBottom = Mathf.RoundToInt(Mathf.Max(0f, tooltipPadding.z));
}
if (overrideTooltipFont)
{
tooltip.titleLabelStyle.textStyle.font = tooltipFont;
tooltip.titleLabelStyle.textStyle.fontSize = tooltipFontSize;
tooltip.titleLabelStyle.textStyle.color = tooltipTextColor;
for (int i = 0; i < tooltip.contentLabelStyles.Count; i++)
{
id = (isMainSeries ? "main_" : "ref_") + i,
name = axis.label,
x = i,
value = Mathf.Clamp(value, minValue, maxValue)
});
tooltip.contentLabelStyles[i].textStyle.font = tooltipFont;
tooltip.contentLabelStyles[i].textStyle.fontSize = tooltipFontSize;
tooltip.contentLabelStyles[i].textStyle.color = tooltipTextColor;
}
}
}
private List<string> BuildLabels()
private void EnsureChartInitialized()
{
List<string> labels = new List<string>(axisCount);
for (int i = 0; i < axisCount; i++)
if (radarChart == null)
{
string label = axes[i] != null ? axes[i].label : null;
labels.Add(string.IsNullOrWhiteSpace(label) ? $"Axis {i + 1}" : label.Trim());
return;
}
return labels;
if (!chartInitialized)
{
radarChart.Init();
chartInitialized = true;
}
else
{
radarChart.EnsureChartComponent<Title>();
radarChart.EnsureChartComponent<Tooltip>();
radarChart.EnsureChartComponent<XCharts.Runtime.Background>();
radarChart.EnsureChartComponent<RadarCoord>();
}
}
private void EnsureRuntimeChartStyle()
{
if (radarChart == null)
{
return;
}
radarChart.raycastTarget = false;
CanvasRenderer canvasRenderer = radarChart.GetComponent<CanvasRenderer>();
if (canvasRenderer != null)
{
canvasRenderer.SetAlpha(1f);
}
}
private void EnsureChartHost()
{
if (radarChartHost == null)
{
Transform existing = transform.Find(radarChartHostName);
if (existing != null)
{
radarChartHost = existing as RectTransform;
}
}
if (radarChartHost == null)
{
GameObject host = new GameObject(radarChartHostName, typeof(RectTransform));
radarChartHost = host.GetComponent<RectTransform>();
radarChartHost.SetParent(transform, false);
}
radarChartHost.anchorMin = Vector2.zero;
radarChartHost.anchorMax = Vector2.one;
radarChartHost.pivot = new Vector2(0.5f, 0.5f);
radarChartHost.anchoredPosition = Vector2.zero;
radarChartHost.sizeDelta = Vector2.zero;
radarChartHost.offsetMin = Vector2.zero;
radarChartHost.offsetMax = Vector2.zero;
radarChartHost.localScale = Vector3.one;
radarChartHost.localRotation = Quaternion.identity;
radarChartHost.SetAsLastSibling();
radarChartHost.gameObject.SetActive(true);
}
private void DisableLegacyRenderer()
{
if (chartBridge == null)
{
chartBridge = GetComponent<UGUIChartBridge>();
}
if (chartBridge != null)
{
chartBridge.enabled = false;
}
UIDocument uiDocument = GetComponent<UIDocument>();
if (uiDocument != null)
{
uiDocument.enabled = false;
}
RawImage rawImage = GetComponent<RawImage>();
if (rawImage != null)
{
rawImage.enabled = false;
rawImage.texture = null;
rawImage.raycastTarget = false;
Color color = rawImage.color;
color.a = 0f;
rawImage.color = color;
}
if (radarGraphic == null)
{
radarGraphic = GetComponent<UIRadarGraphic>();
}
if (radarGraphic != null)
{
radarGraphic.enabled = false;
radarGraphic.raycastTarget = false;
Color color = radarGraphic.color;
color.a = 0f;
radarGraphic.color = color;
radarGraphic.SetVerticesDirty();
}
if (labelRoot == null && autoCreateLabelRoot)
{
Transform existing = transform.Find(labelRootName);
if (existing != null)
{
labelRoot = existing as RectTransform;
}
}
if (labelRoot != null)
{
labelRoot.gameObject.SetActive(false);
}
}
private void NormalizeAxes()
@@ -99,8 +99,7 @@ public class uBehaviourRaderController : MonoBehaviour
ResolveDependencies();
if (radarChartController != null &&
chartBridge != null &&
chartBridge.Profile != null)
radarChartController.IsRendererReady)
{
ApplyOverlayVisibility(btmandtopController.CurrentOverlayPanelsVisible);
ApplySummary(BuildSummary(RecentPlayHistoryStore.GetRecords()));
@@ -145,6 +144,11 @@ public class uBehaviourRaderController : MonoBehaviour
}
}
if (chartBridge != null)
{
chartBridge.DisablePointerInteraction = true;
}
if (rankConfig == null)
{
RankConfig[] configs = Resources.LoadAll<RankConfig>(string.Empty);
@@ -232,6 +236,12 @@ public class uBehaviourRaderController : MonoBehaviour
bool shouldShow = !hideWhenOverlayVisible || !overlayVisible;
bool wasActive = uRaderObj.activeSelf;
if (!shouldShow && chartBridge != null)
{
chartBridge.ReleaseRuntimeResources();
}
uRaderObj.SetActive(shouldShow);
if (shouldShow && !wasActive)
@@ -242,14 +252,18 @@ public class uBehaviourRaderController : MonoBehaviour
private void ForceRefreshChartBridge()
{
if (chartBridge == null)
if (radarChartController == null)
{
return;
}
chartBridge.enabled = false;
chartBridge.enabled = true;
chartBridge.Refresh();
if (chartBridge != null)
{
chartBridge.DisablePointerInteraction = true;
chartBridge.ReleaseRuntimeResources();
}
radarChartController.RebuildNow();
}
private void ApplySummary(BehaviourRadarSummary summary)