修改本体,添加CrossTrackPoint兼容层,兼容StaticTrack Hold,为难度选项扩增全屏可选,添加和调整某些谱面

Signed-off-by: TRADER_FOER <lhf190@outlook.com>
This commit is contained in:
2026-07-18 11:39:55 +08:00
parent 40fa80cd70
commit db5dbe246a
125 changed files with 1510 additions and 1571 deletions

View File

@@ -18,13 +18,13 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
#region [] Core Effect Implementation
public sealed override void Recover()
{
noteVisual.noteMain.SetActive(false);
SetVisualShown(false);
noteVisual.noteMain.transform.localScale = Vector3.zero;
}
public override void PreExecute()
{
noteVisual.noteMain.SetActive(true);
SetVisualShown(true);
}
public override void Execute()
@@ -35,9 +35,20 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
public override void Adjust()
{
SetVisualShown(true);
noteVisual.noteMain.transform.localScale = Vector3.one;
}
private void SetVisualShown(bool isShown)
{
if (noteVisual is DTMNoteVisualHold holdVisual)
{
holdVisual.SetHoldVisualShown(isShown);
return;
}
noteVisual.noteMain.SetActive(isShown);
}
#endregion
}
}
}

View File

@@ -26,30 +26,32 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
#region [] Core Effect Logic
private void UpdateHold()
{
hold.trackPositioner.SetPercent(startPercent);
noteVisualHold.meshGenerator.SetClipRange(startPercent, endPercent);
//noteVisualHold.extrude.Range = new Vector2(startPercent, endPercent);
noteVisualHold.headPoint.SetPercent(startPercent);
noteVisualHold.tailPoint.SetPercent(endPercent);
noteVisualHold.SetHoldPercentRange(startPercent, endPercent, true);
}
private void UpdateTargetPercents(float songTime)
{
targetStartPercent = noteVisualHold.GetTrackPercent(hold.exactJudgeTime, songTime);
targetEndPercent = noteVisualHold.GetTrackPercent(hold.holdEndTime, songTime);
}
public override void Recover()
{
noteVisualHold.noteMain.SetActive(false);
noteVisualHold.SetHoldVisualShown(false);
}
public override void PreExecute()
{
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = hold.track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
targetStartPercent = trackTimeSubmoduleMovable.GetTrackPercent(hold.exactJudgeTime);
targetEndPercent = trackTimeSubmoduleMovable.GetTrackPercent(hold.holdEndTime);
UpdateTargetPercents(CoreServices.TimeProvider?.SongTime ?? 0f);
startPercent = targetStartPercent;
endPercent = targetStartPercent;
noteVisual.noteMain.SetActive(true);
noteVisualHold.SetHoldVisualShown(true);
UpdateHold();
}
public override void Execute()
{
UpdateTargetPercents(CoreServices.TimeProvider?.SongTime ?? 0f);
float e = AnimationCurveEvaluator.Evaluate(AnimationCurveType.OutQuad, effectProgressPercent);
startPercent = targetStartPercent;
endPercent = Mathf.Lerp(targetStartPercent, targetEndPercent, e);
@@ -58,11 +60,12 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
public override void Adjust()
{
UpdateTargetPercents(CoreServices.TimeProvider?.SongTime ?? 0f);
startPercent = targetStartPercent;
endPercent = targetEndPercent;
noteVisualHold.SetHoldVisualShown(true);
UpdateHold();
}
#endregion
}
}
}

View File

@@ -45,8 +45,16 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
this.hold.trackPositioner.autoUpdate = false;
headPoint.spline = hold.track.trackPathSubmodule.path;
headPoint.autoUpdate = false;
meshGenerator.spline = hold.track.trackPathSubmodule.path;
tailPoint.spline = hold.track.trackPathSubmodule.path;
tailPoint.autoUpdate = false;
ConfigurePathNodeScaleIsolation();
startPercent = GetTrackPercent(hold.exactJudgeTime);
endPercent = GetTrackPercent(hold.holdEndTime);
ApplyHoldPositionOffset(GetCurrentPositionOffset());
SetHoldPercentRange(startPercent, endPercent, true);
//meshGenerator.enabled = false;
//extrude.Container = hold.track.trackPathSubmodule.container;
@@ -69,11 +77,11 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
{
rend.materials[0].SetFloat("_MainAlpha", 1f);
rend.materials[1].SetFloat("_MainAlpha", 1f);
note.track.trackPathSubmodule.path.RebuildImmediate();
note?.track?.trackPathSubmodule?.path?.RebuildImmediate();
}
}
foreach (EffectBase effect in effectSubmodule.effectCollection["Generate"])
foreach (EffectBase effect in GetEffects("Generate"))
{
effect.Recover();
}
@@ -85,41 +93,279 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
{
#region [] Hold Updates
private float startPercent, endPercent;
private Vector2 positionOffset;
private SplineSample offsetSample = new();
private Transform hitPointTransform;
private Vector3 hitPointBaseLocalScale = Vector3.one;
private bool isHoldVisualShown = true;
public float holdThickness => Mathf.Max(0f, transformSubmodule?.currentScale.x ?? 1f);
public void ApplyHoldThicknessFromScale()
{
if (meshGenerator == null) return;
meshGenerator.size = holdThickness;
}
private void ConfigurePathNodeScaleIsolation()
{
if (meshGenerator != null) meshGenerator.useSplineSize = false;
DisableSplineSizeScale(hold?.trackPositioner);
DisableSplineSizeScale(headPoint);
DisableSplineSizeScale(tailPoint);
ApplyHitPointScaleIsolation();
}
private void DisableSplineSizeScale(SplinePositioner positioner)
{
if (positioner == null) return;
positioner.motion.applyScaleX = false;
positioner.motion.applyScaleY = false;
positioner.motion.applyScaleZ = false;
}
private Vector2 GetCurrentPositionOffset()
{
if (transformSubmodule == null) return Vector2.zero;
return new Vector2(transformSubmodule.currentPosition.x, transformSubmodule.currentPosition.y);
}
private List<EffectBase> GetEffects(string key)
{
if (effectSubmodule?.effectCollection != null &&
effectSubmodule.effectCollection.TryGetValue(key, out List<EffectBase> effects))
{
return effects;
}
return new List<EffectBase>();
}
private bool IsGenerateEffectMiddle()
{
return GetEffects("Generate").Any(e => e.nowEffectState == EffectBase.EffectState.Middle);
}
private void ApplyHoldPositionOffset(Vector2 offset)
{
positionOffset = offset;
if (meshGenerator != null) meshGenerator.offset = offset;
ClearSplineSizeScaledOffset(hold?.trackPositioner);
ClearSplineSizeScaledOffset(headPoint);
ClearSplineSizeScaledOffset(tailPoint);
}
private void ClearSplineSizeScaledOffset(SplinePositioner positioner)
{
if (positioner == null) return;
positioner.motion.offset = Vector2.zero;
}
private void ApplyPositionerWorldOffset(SplinePositioner positioner, float percent)
{
if (positioner == null || positioner.targetObject == null || positionOffset == Vector2.zero) return;
if (positioner.sampleCount == 0) return;
positioner.Evaluate(percent, ref offsetSample);
positioner.targetObject.transform.position +=
offsetSample.right * positionOffset.x +
offsetSample.up * positionOffset.y;
}
public override void SetHighlight()
{
SetHitPointVisible(isHoldVisualShown);
}
public void SetHoldVisualShown(bool isShown)
{
isHoldVisualShown = isShown;
if (noteMain != null) noteMain.SetActive(isShown);
SetHitPointVisible(isShown);
}
private void SetHitPointVisible(bool isVisualShown)
{
if (extraPartList == null || extraPartList.Count == 0 || extraPartList[0] == null) return;
extraPartList[0].SetActive(isVisualShown && isHighlighted);
ApplyHitPointScaleIsolation();
}
private void CacheHitPointTransform()
{
if (hitPointTransform != null) return;
if (extraPartList == null || extraPartList.Count == 0 || extraPartList[0] == null) return;
hitPointTransform = extraPartList[0].transform;
hitPointBaseLocalScale = hitPointTransform.localScale;
}
private void ApplyHitPointScaleIsolation()
{
CacheHitPointTransform();
if (hitPointTransform == null) return;
Vector3 targetWorldScale = hitPointBaseLocalScale * holdThickness;
Transform parent = hitPointTransform.parent;
if (parent == null)
{
hitPointTransform.localScale = targetWorldScale;
return;
}
Vector3 parentScale = parent.lossyScale;
hitPointTransform.localScale = new Vector3(
DivideScaleAxis(targetWorldScale.x, parentScale.x),
DivideScaleAxis(targetWorldScale.y, parentScale.y),
DivideScaleAxis(targetWorldScale.z, parentScale.z)
);
}
private float DivideScaleAxis(float targetScale, float parentScale)
{
return Mathf.Approximately(parentScale, 0f) ? targetScale : targetScale / parentScale;
}
public float GetTrackPercent(float targetTime)
{
return GetTrackPercent(targetTime, CoreServices.TimeProvider?.SongTime ?? 0f);
}
public float GetTrackPercent(float targetTime, float songTime)
{
if (hold.track.trackTimeSubmodule is TrackTimeSubmoduleMovable trackTimeSubmoduleMovable)
{
return trackTimeSubmoduleMovable.GetTrackPercent(targetTime);
}
if (hold.track.trackTimeSubmodule is TrackTimeSubmoduleStatic trackTimeSubmoduleStatic)
{
float startMove = targetTime - trackTimeSubmoduleStatic.trackTotalTime;
float percent = AnimationCurveEvaluator.Evaluate(trackTimeSubmoduleStatic.animationCurveType,
(songTime - startMove) / trackTimeSubmoduleStatic.trackTotalTime);
return 1 - Mathf.Clamp01(percent);
}
throw new InvalidOperationException("Hold NoteVisual needs a TrackTimeSubmodule.");
}
public void UpdateHoldInMovableTrack()
{
if (effectSubmodule.effectCollection["Generate"].Any(e => e.nowEffectState == EffectBase.EffectState.Middle))
if (IsGenerateEffectMiddle())
{
return;
}
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = hold.track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
startPercent = trackTimeSubmoduleMovable.GetTrackPercent(hold.exactJudgeTime + hold.holdingTime);
endPercent = trackTimeSubmoduleMovable.GetTrackPercent(hold.holdEndTime);
startPercent = GetTrackPercent(hold.exactJudgeTime);
endPercent = GetTrackPercent(hold.holdEndTime);
hold.trackPositioner.SetPercent(startPercent);
meshGenerator.SetClipRange(startPercent, endPercent);
//Debug.Log("Range: " + startPercent + " - " + endPercent);
//extrude.Range = new Vector2(startPercent, endPercent);
headPoint.SetPercent(startPercent);
tailPoint.SetPercent(endPercent);
if (hold.isHolding)
{
startPercent = GetTrackPercent(hold.exactJudgeTime + hold.holdingTime);
endPercent = GetTrackPercent(hold.holdEndTime);
}
else if (hold.isFinalJudged)
{
startPercent = GetTrackPercent(hold.holdEndTime);
endPercent = GetTrackPercent(hold.holdEndTime);
}
SetHoldPercentRange(startPercent, endPercent, true);
}
public void UpdateHoldInStaticTrack()
public void UpdateHoldInStaticTrack(float songTime)
{
//throw new NotImplementedException();
if (IsGenerateEffectMiddle())
{
return;
}
startPercent = GetTrackPercent(hold.exactJudgeTime, songTime);
endPercent = GetTrackPercent(hold.holdEndTime, songTime);
if (hold.isHolding)
{
startPercent = GetTrackPercent(hold.exactJudgeTime + hold.holdingTime, songTime);
endPercent = GetTrackPercent(hold.holdEndTime, songTime);
}
else if (hold.isFinalJudged)
{
startPercent = GetTrackPercent(hold.holdEndTime, songTime);
endPercent = GetTrackPercent(hold.holdEndTime, songTime);
}
SetHoldPercentRange(startPercent, endPercent, true);
}
public void SetHoldPercentRange(float startPercent, float endPercent, bool rebuildImmediately)
{
this.startPercent = startPercent;
this.endPercent = endPercent;
if (rebuildImmediately)
{
hold.trackPositioner.RebuildImmediate();
}
ApplyHoldPositionOffset(positionOffset);
hold.trackPositioner.SetPercent(startPercent);
ApplyPositionerWorldOffset(hold.trackPositioner, startPercent);
meshGenerator.SetClipRange(startPercent, endPercent);
ApplyHoldThicknessFromScale();
if (rebuildImmediately)
{
meshGenerator.RebuildImmediate();
headPoint.RebuildImmediate();
}
headPoint.SetPercent(startPercent);
ApplyPositionerWorldOffset(headPoint, startPercent);
ApplyHitPointScaleIsolation();
if (rebuildImmediately)
{
tailPoint.RebuildImmediate();
}
tailPoint.SetPercent(endPercent);
ApplyPositionerWorldOffset(tailPoint, endPercent);
}
#endregion
#region [] Transform & Refresh Overrides
public void UpdateTransform(bool refreshAll = true)
{
if (transformSubmodule == null) return;
bool willRefresh = false;
if (transformSubmodule.scaleDirtyMark)
{
transformSubmodule.currentScale = transformSubmodule.originalScale + transformSubmodule.scaleOffset;
transform.localScale = Vector3.one;
ApplyHoldThicknessFromScale();
ApplyHitPointScaleIsolation();
transformSubmodule.scaleDirtyMark = false;
willRefresh = true;
transformSubmodule.scaleOffset = Vector3.zero;
}
if (!transformSubmodule.eulerAnglesOffsetLock && transformSubmodule.eulerAnglesDirtyMark)
{
transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + transformSubmodule.eulerAnglesOffset;
transform.localEulerAngles = transformSubmodule.currentEulerAngles;
transformSubmodule.eulerAnglesDirtyMark = false;
willRefresh = true;
transformSubmodule.eulerAnglesOffset = Vector3.zero;
}
if (transformSubmodule.positionDirtyMark)
{
transformSubmodule.currentPosition = transformSubmodule.originalPosition + transformSubmodule.positionOffset;
transform.localPosition = transformSubmodule.currentPosition;
ApplyHoldPositionOffset(GetCurrentPositionOffset());
transformSubmodule.positionDirtyMark = false;
willRefresh = true;
transformSubmodule.positionOffset = Vector3.zero;
@@ -137,13 +383,19 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
public override void Refresh()
{
base.Refresh();
Vector2 posOffset = new Vector2(transformSubmodule.currentPosition.x, transformSubmodule.currentPosition.y);
hold.trackPositioner.motion.offset = posOffset;
meshGenerator.offset = posOffset;
headPoint.motion.offset = posOffset;
tailPoint.motion.offset = posOffset;
foreach (EffectBase effect in GetEffects("Generate"))
{
if (effect.nowEffectState == EffectBase.EffectState.Middle)
{
effect.Recover();
}
}
ApplyHoldPositionOffset(GetCurrentPositionOffset());
ApplyHoldThicknessFromScale();
ApplyHitPointScaleIsolation();
}
#endregion
}
}
}