note修复

Signed-off-by: TRADER_FOER <lhf190@outlook.com>
This commit is contained in:
2026-07-25 22:19:32 +08:00
parent eb7110ea77
commit c828389d0d
24 changed files with 60148 additions and 828818 deletions

View File

@@ -77,6 +77,65 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
return _previewRoot;
}
}
private float CurrentSongTime => CoreServices.TimeProvider?.SongTime ?? EditorManager.instance.songInformation.songTime;
private bool TryGetTrackContext(out SplineComputer spline, out TrackTimeSubmodule trackTime)
{
spline = null;
trackTime = null;
if (TrackedTrack?.trackPathSubmodule?.path == null) return false;
if (TrackedTrack.trackTimeSubmodule == null) return false;
spline = TrackedTrack.trackPathSubmodule.path;
trackTime = TrackedTrack.trackTimeSubmodule;
return true;
}
private bool TryGetBeatRange(out float beatStart, out float beatEnd)
{
beatStart = 0f;
beatEnd = 0f;
if (!TryGetTrackContext(out _, out TrackTimeSubmodule trackTime)) return false;
var beatManager = EditorManager.instance.songInformation.beatManager;
switch (trackTime)
{
case TrackTimeSubmoduleMovable movable:
beatStart = beatManager.GetBeatFromTime(movable.trackStartTime);
beatEnd = beatManager.GetBeatFromTime(movable.trackEndTime);
return true;
case TrackTimeSubmoduleStatic stat:
float songTime = CurrentSongTime;
beatStart = beatManager.GetBeatFromTime(songTime);
beatEnd = beatManager.GetBeatFromTime(songTime + stat.trackTotalTime);
return true;
default:
return false;
}
}
private bool TryGetTrackPercent(float noteTime, TrackTimeSubmodule trackTime, out float trackPercent)
{
trackPercent = 0f;
switch (trackTime)
{
case TrackTimeSubmoduleMovable movable:
trackPercent = Mathf.Clamp01(movable.GetTrackPercentRaw(noteTime));
return true;
case TrackTimeSubmoduleStatic stat:
float startMove = noteTime - stat.trackTotalTime;
float percent = AnimationCurveEvaluator.Evaluate(
stat.animationCurveType,
(CurrentSongTime - startMove) / stat.trackTotalTime);
trackPercent = 1f - Mathf.Clamp01(percent);
return true;
default:
return false;
}
}
private class NotePreviewData : MonoBehaviour
{
@@ -101,9 +160,8 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
});
}
public void Refresh(SplineComputer spline, TrackTimeSubmoduleMovable trackTime, float horizonWidth)
public void Refresh(SplineComputer spline, float trackPercent, float horizonWidth)
{
float trackPercent = Mathf.Clamp01(trackTime.GetTrackPercentRaw(noteTime));
SplineSample sample = spline.Evaluate(trackPercent);
Vector3 sideOffset = sample.rotation * (noteBase1.noteVisual != null ? noteBase1.noteVisual.transformSubmodule.originalPosition : Vector3.zero);
Vector3 worldPos = sample.position;
@@ -155,15 +213,17 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
}
}
// 刷新所有预览
SplineComputer spline = TrackedTrack.trackPathSubmodule.path;
var trackTime = TrackedTrack.trackTimeSubmodule as TrackTimeSubmoduleMovable;
if (!TryGetTrackContext(out SplineComputer spline, out TrackTimeSubmodule trackTime)) return;
foreach (var preview in NotePreviews.Values)
{
if (preview != null)
{
Observable.NextFrame().Subscribe(_ =>
{
preview.Refresh(spline, trackTime, horizonWidth);
if (TryGetTrackPercent(preview.noteTime, trackTime, out float trackPercent))
{
preview.Refresh(spline, trackPercent, horizonWidth);
}
});
}
}
@@ -256,16 +316,16 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
if (!_isEnabled) return;
// 获取数据源
SplineComputer splineComputer = TrackedTrack.trackPathSubmodule.path;
var trackTime = TrackedTrack.trackTimeSubmodule as TrackTimeSubmoduleMovable;
float beatStart = EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackStartTime);
float beatEnd = EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackEndTime);
if (!TryGetTrackContext(out SplineComputer splineComputer, out TrackTimeSubmodule trackTime)) return;
if (!TryGetBeatRange(out float beatStart, out float beatEnd)) return;
int beatDiver = Mathf.Max(1, BeatDiver);
float beatStep = 1f / beatDiver;
// 2. 批量生成
for (float b = beatStart - 1; b <= beatEnd + 1f / BeatDiver; b += 1f / BeatDiver)
for (float b = beatStart - 1; b <= beatEnd + beatStep; b += beatStep)
{
float timeAtBeat = EditorManager.instance.songInformation.beatManager.GetTimeFromBeat(b);
float trackPercent = Mathf.Clamp01(trackTime.GetTrackPercentRaw(timeAtBeat));
if (!TryGetTrackPercent(timeAtBeat, trackTime, out float trackPercent)) continue;
CalculateLinePositions(splineComputer.Evaluate(trackPercent), out Vector3 p0, out Vector3 p1);
@@ -275,7 +335,9 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
Color color = (Mathf.Abs(b - Mathf.Round(b)) <= 0.01f) ? Color.green : Color.cyan;
SetupLineRenderer(lr, p0, p1, color);
float bi = (trackPercent >= 1f) ? EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackEndTime) : b;
float bi = trackTime is TrackTimeSubmoduleMovable movable && trackPercent >= 1f
? EditorManager.instance.songInformation.beatManager.GetBeatFromTime(movable.trackEndTime)
: b;
Beats.Add(bi < 0 ? 0f : bi);
BeatLines.Add(lr);
}
@@ -292,19 +354,19 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
return;
}
SplineComputer splineComputer = TrackedTrack.trackPathSubmodule.path;
var trackTime = TrackedTrack.trackTimeSubmodule as TrackTimeSubmoduleMovable;
float beatStart = EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackStartTime);
float beatEnd = EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackEndTime);
if (!TryGetTrackContext(out SplineComputer splineComputer, out TrackTimeSubmodule trackTime)) return;
if (!TryGetBeatRange(out float beatStart, out float beatEnd)) return;
int beatDiver = Mathf.Max(1, BeatDiver);
float beatStep = 1f / beatDiver;
int index = 0;
// 重置 Beats 列表以匹配新的位置
Beats.Clear();
for (float b = beatStart - 1; b <= beatEnd + 1f / BeatDiver; b += 1f / BeatDiver)
for (float b = beatStart - 1; b <= beatEnd + beatStep; b += beatStep)
{
float timeAtBeat = EditorManager.instance.songInformation.beatManager.GetTimeFromBeat(b);
float trackPercent = Mathf.Clamp01(trackTime.GetTrackPercentRaw(timeAtBeat));
if (!TryGetTrackPercent(timeAtBeat, trackTime, out float trackPercent)) continue;
// 如果超出范围,跳过更新(除非你想一直显示)
// 这里沿用你 UpdateBeatLine 的逻辑
@@ -325,7 +387,9 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
Color color = (Mathf.Abs(b - Mathf.Round(b)) <= 0.01f) ? Color.green : Color.cyan;
SetupLineRenderer(lr, p0, p1, color, false);
float bi = (trackPercent >= 1f) ? EditorManager.instance.songInformation.beatManager.GetBeatFromTime(trackTime.trackEndTime) : b;
float bi = trackTime is TrackTimeSubmoduleMovable movable && trackPercent >= 1f
? EditorManager.instance.songInformation.beatManager.GetBeatFromTime(movable.trackEndTime)
: b;
Beats.Add(bi < 0 ? 0f : bi);
index++;
}
@@ -559,10 +623,11 @@ namespace ichni.RhythmGame // [修复] 修正命名空间首字母大写,符
return null;
}
fastNoteTracker.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
fastNoteTracker.IsEnabled = isEnabled;
fastNoteTracker.showNotePreview = showNotePreview;
fastNoteTracker.horizonWidth = horizonWidth;
fastNoteTracker.BeatDiver = beatDiver;
fastNoteTracker.BeatDiver = Mathf.Max(1, beatDiver);
fastNoteTracker._isEnabled = isEnabled;
fastNoteTracker._showNotePreview = showNotePreview;
fastNoteTracker.Refresh();
return fastNoteTracker;
}
@@ -615,12 +680,12 @@ namespace Ichni.RhythmGame.Beatmap
public override GameElement DuplicateBM(GameElement attached)
{
return FastNoteTracker.GenerateElement(elementName, Guid.NewGuid(), tags, false, attached);
return FastNoteTracker.GenerateElement(elementName, Guid.NewGuid(), tags, false, attached, IsEnabled, showNotePreview, horizonWidth, beatDiver);
}
public override void ExecuteBM()
{
FastNoteTracker.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid));
FastNoteTracker.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid), IsEnabled, showNotePreview, horizonWidth, beatDiver);
}
}
}
}

View File

@@ -66,7 +66,7 @@ namespace Ichni.RhythmGame
InspectorBuilder.For(this)
.Section("Note Info")
.InputField(nameof(exactJudgeTime), "exactJudgeTime")
.OnChanged(() => UpdateNoteInTrack(CoreServices.TimeProvider.SongTime))
.OnChanged(HandleExactJudgeTimeChanged)
.Mark("ExactJudgeTime")
.Button("Save Note Prefab", () =>
{
@@ -81,6 +81,14 @@ namespace Ichni.RhythmGame
.EnabledIf(() => noteVisual == null)
.Build();
}
private void HandleExactJudgeTimeChanged()
{
float songTime = CoreServices.TimeProvider?.SongTime ?? EditorManager.instance.songInformation.songTime;
UpdateNoteInTrack(songTime);
Refresh();
CoreServices.UpdateScheduler?.NoteScheduler.ManualTick(songTime);
}
#endregion
}
}

View File

@@ -99,10 +99,14 @@ namespace Ichni.RhythmGame
CommandManager.ExecuteCreate(() => TrackHeadPoint.GenerateElement("New Track Head Point", Guid.NewGuid(), new List<string>(), true, this, false, Vector3.zero));
})
.EnabledIf(() => trackTimeSubmodule is TrackTimeSubmoduleMovable)
.Button("Tap", () => CommandManager.ExecuteCreate(() => Tap.GenerateElement("New Tap", Guid.NewGuid(), new List<string>(), true, this, 0f)))
.Button("Stay", () => CommandManager.ExecuteCreate(() => Stay.GenerateElement("New Stay", Guid.NewGuid(), new List<string>(), true, this, 0f)))
.Button("Hold", () => CommandManager.ExecuteCreate(() => Hold.GenerateElement("New Hold", Guid.NewGuid(), new List<string>(), true, this, 0f, 1f)))
.Button("Flick", () => CommandManager.ExecuteCreate(() => Flick.GenerateElement("New Flick", Guid.NewGuid(), new List<string>(), true, this, 0f, new List<Vector2>())))
.Button("Tap", () => CommandManager.ExecuteCreate(() => PrepareGeneratedNote(Tap.GenerateElement("New Tap", Guid.NewGuid(), new List<string>(), true, this, GetDefaultNoteGenerateTime()))))
.Button("Stay", () => CommandManager.ExecuteCreate(() => PrepareGeneratedNote(Stay.GenerateElement("New Stay", Guid.NewGuid(), new List<string>(), true, this, GetDefaultNoteGenerateTime()))))
.Button("Hold", () => CommandManager.ExecuteCreate(() =>
{
float startTime = GetDefaultNoteGenerateTime();
return PrepareGeneratedNote(Hold.GenerateElement("New Hold", Guid.NewGuid(), new List<string>(), true, this, startTime, startTime + 1f));
}))
.Button("Flick", () => CommandManager.ExecuteCreate(() => PrepareGeneratedNote(Flick.GenerateElement("New Flick", Guid.NewGuid(), new List<string>(), true, this, GetDefaultNoteGenerateTime(), new List<Vector2>()))))
.Button("Particle Tracker", () =>
{
CommandManager.ExecuteCreate(() => ParticleTracker.GenerateElement("New Particle Tracker", Guid.NewGuid(), new List<string>(), true, this,
@@ -233,6 +237,17 @@ namespace Ichni.RhythmGame
#endregion
#region [] Tool Methods
private static float GetDefaultNoteGenerateTime()
{
return CoreServices.TimeProvider?.SongTime ?? EditorManager.instance.songInformation.songTime;
}
private static T PrepareGeneratedNote<T>(T note) where T : NoteBase
{
note.noteVisual?.transformSubmodule?.Refresh();
return note;
}
[Button("Test GetAllNotes")]
public List<NoteBase> GetAllNotes()
{

View File

@@ -11,7 +11,7 @@ namespace Ichni.RhythmGame
public GameCamera gameCamera;
public SceneCamera sceneCamera => EditorManager.instance.cameraManager.sceneCamera;
public float farClipRange = 1000f;
public float farClipRange = 2000f;
#endregion
#region [] Lifecycle & Factory

View File

@@ -67,7 +67,10 @@ namespace Ichni
finishTime = finishTime
};
_isDirty = true;
return;
}
RegisterNote(note, activationTime, finishTime);
}
/// <summary>手动触发排序(若需要在注册大批 Note 后一次性完成)</summary>