很多更新,服务端连接,新UI和系统
This commit is contained in:
@@ -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];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user