很多更新,服务端连接,新UI和系统

This commit is contained in:
FloatGaming
2026-04-17 20:09:41 +08:00
parent 85dfff28dd
commit e0bc0bbf08
910 changed files with 65191 additions and 1291 deletions
@@ -0,0 +1,478 @@
using System;
using System.Collections;
using System.Collections.Generic;
using EasyChart;
using EasyChart.UGUI;
using UnityEngine;
using UnityEngine.UI;
public class settleChart : MonoBehaviour
{
[Header("Chart")]
[SerializeField] private ChartProfile sourceProfile;
[SerializeField] private UGUIChartBridge chartBridge;
[SerializeField] private RectTransform chartHost;
[Header("Paging")]
[SerializeField] private Button previousPageButton;
[SerializeField] private Button nextPageButton;
[SerializeField, Min(1)] private int notesPerPage = 100;
[Header("Build")]
[SerializeField, Min(1)] private int buildBatchSize = 64;
[SerializeField] private bool includeMissAsZero = true;
[SerializeField] private bool useHoldEndOffsetAsFallback = true;
private readonly List<float> allOffsets = new List<float>(1024);
private readonly List<string> allLabels = new List<string>(1024);
private ChartProfile runtimeProfile;
private Coroutine buildRoutine;
private int currentPageIndex;
private bool buttonsHooked;
private void Start()
{
HookButtons();
settlementController.OnSettlementCompleted += HandleSettlementCompleted;
}
private void OnEnable()
{
HookButtons();
}
private void OnDestroy()
{
settlementController.OnSettlementCompleted -= HandleSettlementCompleted;
UnhookButtons();
if (buildRoutine != null)
{
StopCoroutine(buildRoutine);
buildRoutine = null;
}
if (runtimeProfile != null)
{
Destroy(runtimeProfile);
runtimeProfile = null;
}
}
private void HandleSettlementCompleted()
{
if (buildRoutine != null)
{
StopCoroutine(buildRoutine);
}
buildRoutine = StartCoroutine(BuildChartAsync());
}
private IEnumerator BuildChartAsync()
{
ResolveReferences();
EnsureChartBridge();
if (chartBridge == null || sourceProfile == null)
{
yield break;
}
allOffsets.Clear();
allLabels.Clear();
currentPageIndex = 0;
UpdateButtonState();
yield return null;
BeatmapManager beatmapManager = BeatmapManager.Instance != null
? BeatmapManager.Instance
: FindAnyObjectByType<BeatmapManager>();
NoteData[] notes = beatmapManager != null && beatmapManager.beatmap != null
? beatmapManager.beatmap.notes
: null;
if (notes == null || notes.Length == 0)
{
ApplyPage(0);
buildRoutine = null;
yield break;
}
int visibleIndex = 0;
for (int i = 0; i < notes.Length; i++)
{
NoteData note = notes[i];
if (note == null)
{
continue;
}
if (!TryExtractSignedOffset(note, out float signedOffset))
{
continue;
}
visibleIndex++;
allOffsets.Add(signedOffset);
allLabels.Add(visibleIndex.ToString());
if ((i + 1) % buildBatchSize == 0)
{
yield return null;
}
}
ApplyPage(0);
buildRoutine = null;
}
private bool TryExtractSignedOffset(NoteData note, out float signedOffset)
{
if (!float.IsNaN(note.judgeOffsetMs))
{
signedOffset = note.judgeOffsetMs;
return true;
}
if (useHoldEndOffsetAsFallback && !float.IsNaN(note.judgeOffsetMsEnd))
{
signedOffset = note.judgeOffsetMsEnd;
return true;
}
bool isMiss = string.Equals(note.judgeResult, "Miss", StringComparison.OrdinalIgnoreCase)
|| string.Equals(note.judgeResultEnd, "Miss", StringComparison.OrdinalIgnoreCase);
if (includeMissAsZero && isMiss)
{
signedOffset = 0f;
return true;
}
signedOffset = 0f;
return false;
}
public void ShowPreviousPage()
{
if (currentPageIndex <= 0)
{
return;
}
ApplyPage(currentPageIndex - 1);
}
public void ShowNextPage()
{
int totalPages = GetTotalPages();
if (currentPageIndex >= totalPages - 1)
{
return;
}
ApplyPage(currentPageIndex + 1);
}
private void ApplyPage(int pageIndex)
{
EnsureChartBridge();
if (chartBridge == null || sourceProfile == null)
{
UpdateButtonState();
return;
}
EnsureRuntimeProfile();
if (runtimeProfile == null)
{
UpdateButtonState();
return;
}
int totalPages = Mathf.Max(1, GetTotalPages());
currentPageIndex = Mathf.Clamp(pageIndex, 0, totalPages - 1);
AxisConfig xAxis = FindAxis(runtimeProfile, runtimeProfile.xAxisId);
AxisConfig yAxis = FindAxis(runtimeProfile, runtimeProfile.yAxisId);
Serie targetSeries = FindPrimaryBarSeries(runtimeProfile);
if (xAxis == null || yAxis == null || targetSeries == null)
{
UpdateButtonState();
return;
}
int start = currentPageIndex * notesPerPage;
int remaining = Mathf.Max(0, allOffsets.Count - start);
int count = Mathf.Min(notesPerPage, remaining);
List<string> labels = new List<string>(Mathf.Max(1, count));
List<SeriesData> seriesData = new List<SeriesData>(Mathf.Max(1, count));
float maxAbs = 1f;
if (count <= 0)
{
labels.Add("-");
seriesData.Add(new SeriesData
{
id = Guid.NewGuid().ToString("N"),
x = 0f,
value = 0f,
name = "-"
});
}
else
{
for (int i = 0; i < count; i++)
{
int globalIndex = start + i;
float value = allOffsets[globalIndex];
maxAbs = Mathf.Max(maxAbs, Mathf.Abs(value));
string label = allLabels[globalIndex];
labels.Add(label);
seriesData.Add(new SeriesData
{
id = Guid.NewGuid().ToString("N"),
x = i,
value = value,
name = label
});
}
}
float roundedRange = Mathf.Max(1f, Mathf.Ceil(maxAbs / 5f) * 5f);
xAxis.axisType = AxisType.Category;
xAxis.labels = labels;
xAxis.showLabels = true;
xAxis.labelPlacement = CategoryLabelPlacement.Tick;
yAxis.axisType = AxisType.Value;
yAxis.autoRangeMin = false;
yAxis.autoRangeMax = false;
yAxis.autoTicks = false;
yAxis.minValue = -roundedRange;
yAxis.maxValue = roundedRange;
yAxis.splitCount = 4;
targetSeries.visible = true;
targetSeries.type = SerieType.Bar;
targetSeries.seriesData = seriesData;
targetSeries.EnsureIntegrity();
for (int i = 0; i < runtimeProfile.series.Count; i++)
{
if (!ReferenceEquals(runtimeProfile.series[i], targetSeries))
{
runtimeProfile.series[i].visible = false;
}
}
chartBridge.Profile = runtimeProfile;
chartBridge.Refresh();
UpdateButtonState();
}
private void EnsureRuntimeProfile()
{
if (runtimeProfile != null)
{
if (!ReferenceEquals(chartBridge.Profile, runtimeProfile))
{
chartBridge.Profile = runtimeProfile;
}
return;
}
runtimeProfile = Instantiate(sourceProfile);
runtimeProfile.name = sourceProfile.name + "_Runtime";
runtimeProfile.hideFlags = HideFlags.DontSave;
chartBridge.Profile = runtimeProfile;
}
private void EnsureChartBridge()
{
ResolveReferences();
if (chartBridge != null)
{
return;
}
RectTransform host = chartHost != null ? chartHost : transform as RectTransform;
if (host == null)
{
return;
}
chartBridge = host.GetComponent<UGUIChartBridge>();
if (chartBridge == null)
{
chartBridge = host.gameObject.AddComponent<UGUIChartBridge>();
}
if (chartBridge != null && sourceProfile != null)
{
chartBridge.Profile = runtimeProfile != null ? runtimeProfile : sourceProfile;
}
}
private void ResolveReferences()
{
if (chartHost == null)
{
Transform host = transform.Find("btm");
chartHost = host as RectTransform;
if (chartHost == null)
{
chartHost = GetComponentInChildren<RectTransform>(true);
}
}
if (chartBridge == null && chartHost != null)
{
chartBridge = chartHost.GetComponent<UGUIChartBridge>();
}
TryAutoBindButtons();
}
private void HookButtons()
{
if (buttonsHooked)
{
return;
}
ResolveReferences();
if (previousPageButton != null)
{
previousPageButton.onClick.AddListener(ShowPreviousPage);
}
if (nextPageButton != null)
{
nextPageButton.onClick.AddListener(ShowNextPage);
}
buttonsHooked = true;
UpdateButtonState();
}
private void UnhookButtons()
{
if (!buttonsHooked)
{
return;
}
if (previousPageButton != null)
{
previousPageButton.onClick.RemoveListener(ShowPreviousPage);
}
if (nextPageButton != null)
{
nextPageButton.onClick.RemoveListener(ShowNextPage);
}
buttonsHooked = false;
}
private void TryAutoBindButtons()
{
if (previousPageButton != null && nextPageButton != null)
{
return;
}
Button[] buttons = FindObjectsByType<Button>(FindObjectsInactive.Include, FindObjectsSortMode.None);
for (int i = 0; i < buttons.Length; i++)
{
Button button = buttons[i];
if (button == null)
{
continue;
}
string lowerName = button.name.ToLowerInvariant();
if (previousPageButton == null && (lowerName.Contains("prev") || lowerName.Contains("previous") || lowerName.Contains("lastpage") || lowerName.Contains("uppage") || lowerName.Contains("ÉÏÒ»")))
{
previousPageButton = button;
continue;
}
if (nextPageButton == null && (lowerName.Contains("next") || lowerName.Contains("downpage") || lowerName.Contains("nextpage") || lowerName.Contains("ÏÂÒ»")))
{
nextPageButton = button;
}
}
}
private void UpdateButtonState()
{
int totalPages = GetTotalPages();
if (previousPageButton != null)
{
previousPageButton.interactable = currentPageIndex > 0;
}
if (nextPageButton != null)
{
nextPageButton.interactable = currentPageIndex < totalPages - 1;
}
}
private int GetTotalPages()
{
if (allOffsets.Count <= 0)
{
return 1;
}
return Mathf.CeilToInt(allOffsets.Count / (float)Mathf.Max(1, notesPerPage));
}
private static AxisConfig FindAxis(ChartProfile profile, AxisId axisId)
{
if (profile == null || profile.axes == null)
{
return null;
}
for (int i = 0; i < profile.axes.Count; i++)
{
AxisConfig axis = profile.axes[i];
if (axis != null && axis.id == axisId)
{
return axis;
}
}
return null;
}
private static Serie FindPrimaryBarSeries(ChartProfile profile)
{
if (profile == null || profile.series == null || profile.series.Count == 0)
{
return null;
}
for (int i = 0; i < profile.series.Count; i++)
{
Serie serie = profile.series[i];
if (serie != null && serie.type == SerieType.Bar)
{
return serie;
}
}
return profile.series[0];
}
}