@@ -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