@@ -288,7 +288,7 @@ namespace Dreamteck.Splines
|
||||
float anglePercent = (float)lon / sides;
|
||||
int index = bodyVertexCount + lon + (lat-1) * (sides + 1);
|
||||
Quaternion rot = Quaternion.AngleAxis(_revolve * anglePercent + rotation + 180f, -Vector3.forward) * Quaternion.AngleAxis(latAngle, Vector3.up);
|
||||
_tsMesh.vertices[index] = center + lookRot * rot * -Vector3.right * (size * 0.5f * evalResult.size);
|
||||
_tsMesh.vertices[index] = center + lookRot * rot * -Vector3.right * (size * 0.5f * resultSize);
|
||||
_tsMesh.colors[index] = vertexColor;
|
||||
_tsMesh.normals[index] = (_tsMesh.vertices[index] - center).normalized;
|
||||
float baseV = startV + capLengthPercent * latitudePercent;
|
||||
@@ -348,7 +348,7 @@ namespace Dreamteck.Splines
|
||||
float anglePercent = (float)lon / sides;
|
||||
int index = bodyVertexCount + capVertexCount + lon + (lat - 1) * (sides + 1);
|
||||
Quaternion rot = Quaternion.AngleAxis(_revolve * anglePercent + rotation + 180f, Vector3.forward) * Quaternion.AngleAxis(latAngle, -Vector3.up);
|
||||
_tsMesh.vertices[index] = center + lookRot * rot * Vector3.right * size * 0.5f * evalResult.size;
|
||||
_tsMesh.vertices[index] = center + lookRot * rot * Vector3.right * size * 0.5f * resultSize;
|
||||
_tsMesh.normals[index] = (_tsMesh.vertices[index] - center).normalized;
|
||||
_tsMesh.colors[index] = vertexColor;
|
||||
float baseV = startV + capLengthPercent * latitudePercent;
|
||||
|
||||
@@ -59,15 +59,20 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
meshGenerator.spline = hold.track.trackPathSubmodule.path;
|
||||
tailPoint.spline = hold.track.trackPathSubmodule.path;
|
||||
tailPoint.autoUpdate = false; // 由调度器 Phase 6 通过 RebuildImmediate 手动刷新
|
||||
ConfigurePathNodeScaleIsolation();
|
||||
|
||||
float startPercent = GetTrackPercent(hold.exactJudgeTime);
|
||||
float endPercent = GetTrackPercent(hold.holdEndTime);
|
||||
startPercent = GetTrackPercent(hold.exactJudgeTime);
|
||||
endPercent = GetTrackPercent(hold.holdEndTime);
|
||||
ApplyHoldPositionOffset(GetCurrentPositionOffset());
|
||||
|
||||
hold.trackPositioner.SetPercent(startPercent);
|
||||
ApplyPositionerWorldOffset(hold.trackPositioner, startPercent);
|
||||
meshGenerator.SetClipRange(startPercent, endPercent);
|
||||
ApplyHoldThicknessFromScale();
|
||||
headPoint.SetPercent(startPercent);
|
||||
ApplyPositionerWorldOffset(headPoint, startPercent);
|
||||
tailPoint.SetPercent(endPercent);
|
||||
ApplyPositionerWorldOffset(tailPoint, endPercent);
|
||||
|
||||
if (isFirstGenerated)
|
||||
{
|
||||
@@ -94,15 +99,15 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
{
|
||||
materialPropertyBlock.SetFloat("_MainAlpha", 1f);
|
||||
rend.SetPropertyBlock(materialPropertyBlock);
|
||||
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();
|
||||
}
|
||||
foreach (EffectBase effect in effectSubmodule.effectCollection["Holding"])
|
||||
foreach (EffectBase effect in GetEffects("Holding"))
|
||||
{
|
||||
effect.Recover();
|
||||
}
|
||||
@@ -110,7 +115,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
foreach (EffectBase effect in effectSubmodule.effectCollection["Generate"])
|
||||
foreach (EffectBase effect in GetEffects("Generate"))
|
||||
{
|
||||
if (effect.nowEffectState == EffectBase.EffectState.Middle)
|
||||
{
|
||||
@@ -118,11 +123,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
ApplyHoldPositionOffset(GetCurrentPositionOffset());
|
||||
ApplyHoldThicknessFromScale();
|
||||
}
|
||||
#endregion
|
||||
@@ -140,14 +141,84 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
|
||||
#region [位移更新逻辑] Positional Updates
|
||||
private float startPercent, endPercent;
|
||||
private Vector2 positionOffset;
|
||||
private SplineSample offsetSample = new();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 void UpdateTransform(bool refreshAll = true)
|
||||
{
|
||||
if (transformSubmodule == null) return;
|
||||
@@ -177,6 +248,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
{
|
||||
transformSubmodule.currentPosition = transformSubmodule.originalPosition + transformSubmodule.positionOffset;
|
||||
transform.localPosition = transformSubmodule.currentPosition;
|
||||
ApplyHoldPositionOffset(GetCurrentPositionOffset());
|
||||
transformSubmodule.positionDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.positionOffset = Vector3.zero;
|
||||
@@ -214,7 +286,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
|
||||
public void UpdateHoldInMovableTrack()
|
||||
{
|
||||
if (effectSubmodule.effectCollection["Generate"].Any(e => e.nowEffectState == EffectBase.EffectState.Middle))
|
||||
if (IsGenerateEffectMiddle())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -239,7 +311,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
|
||||
public void UpdateHoldInStaticTrack(float songTime)
|
||||
{
|
||||
if (effectSubmodule.effectCollection["Generate"].Any(e => e.nowEffectState == EffectBase.EffectState.Middle))
|
||||
if (IsGenerateEffectMiddle())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -263,13 +335,18 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
|
||||
public void SetHoldPercentRange(float startPercent, float endPercent, bool rebuildImmediately)
|
||||
{
|
||||
this.startPercent = startPercent;
|
||||
this.endPercent = endPercent;
|
||||
|
||||
if (rebuildImmediately)
|
||||
{
|
||||
// autoUpdate=false 的 SplineUser 不会自行刷新,必须手动 RebuildImmediate。
|
||||
hold.trackPositioner.RebuildImmediate();
|
||||
}
|
||||
|
||||
ApplyHoldPositionOffset(positionOffset);
|
||||
hold.trackPositioner.SetPercent(startPercent);
|
||||
ApplyPositionerWorldOffset(hold.trackPositioner, startPercent);
|
||||
meshGenerator.SetClipRange(startPercent, endPercent);
|
||||
ApplyHoldThicknessFromScale();
|
||||
|
||||
@@ -280,6 +357,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
}
|
||||
|
||||
headPoint.SetPercent(startPercent);
|
||||
ApplyPositionerWorldOffset(headPoint, startPercent);
|
||||
|
||||
if (rebuildImmediately)
|
||||
{
|
||||
@@ -287,6 +365,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
}
|
||||
|
||||
tailPoint.SetPercent(endPercent);
|
||||
ApplyPositionerWorldOffset(tailPoint, endPercent);
|
||||
}
|
||||
|
||||
public void SetTransformObserver()
|
||||
@@ -303,11 +382,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
if (transformSubmodule.positionDirtyMark)
|
||||
{
|
||||
transformSubmodule.currentPosition = transformSubmodule.originalPosition + transformSubmodule.positionOffset;
|
||||
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;
|
||||
ApplyHoldPositionOffset(GetCurrentPositionOffset());
|
||||
transformSubmodule.positionDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.positionOffset = Vector3.zero;
|
||||
|
||||
Reference in New Issue
Block a user