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