Skip to content

Commit 072a3e7

Browse files
committed
[O]当多段分别指定时间的星星,每一段都指定了bpm,如1-2[120#4:1]-3[120#4:1]-4[120#4:1]这种时,等待时间配置的修复与优化。
1 parent f471b98 commit 072a3e7

1 file changed

Lines changed: 14 additions & 11 deletions

File tree

parser/simai/SimaiParser.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public partial class SimaiParser : SimaiBaseVisitor<object>, IParser
2121

2222
private ParserRuleContext? currContext; // 供调试报错AddAlert函数使用
2323
private Note? currNote; // 用于在部分visitor之间传递额外的参数,如visitDuration、visitSlideBody等,都需要Note对象作为参数传入的情况
24+
private bool isRealExactWaitTime; // 用于在VisitSlideBody和VisitSlideDuration之间传递额外的参数
2425
private readonly List<string> extraModifiers = [];
2526
private bool absoluteTimeStepWarned; // 用于确保Warning只打印一次
2627

@@ -145,6 +146,7 @@ public string Preprocess(string text, bool tryFix = false)
145146
throw new ConversionException(alerts, e);
146147
}
147148

149+
chart.Sort();
148150
return (chart, alerts);
149151
}
150152

@@ -419,13 +421,15 @@ public sealed override object VisitSlideDuration(P.SlideDurationContext context)
419421
{
420422
var result = new Duration(currNote!);
421423
Duration? waitTime = null;
424+
isRealExactWaitTime = false;
422425

423426
if (context.waitTime() != null)
424427
{
425428
waitTime = new Duration(currNote!)
426429
{
427430
Seconds = (Rational)(decimal)VisitNumber(context.waitTime().number())
428431
};
432+
isRealExactWaitTime = true;
429433
}
430434
if (context.number() != null) result.Seconds = (Rational)(decimal)VisitNumber(context.number());
431435
else
@@ -437,10 +441,8 @@ public sealed override object VisitSlideDuration(P.SlideDurationContext context)
437441
// 根据强行指定的bpm换算为秒数
438442
var bpm = (Rational)(decimal)VisitNumber(context.asBpm().number());
439443
result.Seconds = value * (240 / bpm);
440-
waitTime ??= new Duration(currNote!)
441-
{
442-
Seconds = 60 / bpm
443-
};
444+
// 如果未显式指定waitTime,则waitTime也要变成强行指定的bpm下的一拍。不然就是音符所在时刻下的一拍了。
445+
waitTime ??= new Duration(currNote!) { Seconds = 60 / bpm };
444446
}
445447
}
446448
return (waitTime, result);
@@ -473,22 +475,23 @@ public sealed override object VisitSlideBody(P.SlideBodyContext context)
473475
}
474476
else if (durationCount == context.slideType().Length)
475477
{ // 第二种情况,每个上都有时间标记
476-
var waitTimeSet = false;
478+
var waitTimeSet = 0; // 0:waitTime还未被设置,1:waitTime已被隐式设置,2:waitTime已被显式设置
477479
for (int i = 0; i < durationCount; i++)
478480
{
479481
var C = context.slideDuration()[i];
480482
var (waitTime, duration) = ((Duration?, Duration))VisitSlideDuration(C);
481483
if (waitTime != null)
482484
{
483-
if (waitTimeSet || (i > 0 && i < durationCount - 1))
484-
{
485-
AddAlert(Warning, Locale.InvalidWaitTime);
486-
}
487-
else
485+
// 本次返回的waitTime的强度。用户显式设置的记为2,用户未显式设置、但是中括号中形如[190#8:3]这样指定了bpm、导致产生了一个隐式的waitTime的,记为1。
486+
var hereStrength = isRealExactWaitTime ? 2 : 1;
487+
// 采信这个waitTime的条件:必须在头尾,且强度更大
488+
if ((i == 0 || i == durationCount - 1) && hereStrength > waitTimeSet)
488489
{
489490
slide.WaitTime = waitTime;
490-
waitTimeSet = true;
491+
waitTimeSet = hereStrength;
491492
}
493+
// 给警告的条件:未被采信(即上一个分支没命中),且是显式设置的
494+
else if (isRealExactWaitTime) AddAlert(Warning, Locale.InvalidWaitTime);
492495
}
493496
slide.segments[i].Duration = duration;
494497
}

0 commit comments

Comments
 (0)