@@ -408,6 +408,23 @@ private int ParseHoldNote(bool isAirHold, string[] lines, int idx, string code,
408408 alerts . Add ( new Alert ( Warning , $ "HLD 音符缺少时长跟随行") { Line = idx + 1 , RelevantNote = lines [ idx ] } ) ;
409409 return idx ;
410410 }
411+
412+ // UGC中约定Air系列音符都一定紧跟在其Previous的后面。
413+ // 所以我们直接用上一个解析出的note就可以立即确定前驱了,无需再等到最后集中FillPrevious,而且等到最后集中FillPrevious时的结果也可能是错的。
414+ // 本函数作为一个工具函数干的就是这个事情。
415+ private bool AddAirPreviousFromLastNote ( ChuNote note , ChuChart chart )
416+ {
417+ if ( chart . Notes . Count > 0 )
418+ {
419+ var filtered = FilterPreviousCandidates ( note , [ chart . Notes . Last ( ) ] ) ; // 仅传入一个元素到FilterPreviousCandidates,因此返回结果最多一个元素
420+ if ( filtered . Count > 0 )
421+ {
422+ note . Previous = filtered [ 0 ] ;
423+ return true ;
424+ }
425+ }
426+ return false ;
427+ }
411428
412429 private int ParseSlideNote ( bool isAirSlide , string [ ] lines , int idx , string code , ChuNote previousNote , List < Alert > alerts , ChuChart chart )
413430 {
@@ -441,6 +458,12 @@ private int ParseSlideNote(bool isAirSlide, string[] lines, int idx, string code
441458 EndHeight = endHeight != null ? U2C_Height ( endHeight . Value ) : previousNote . EndHeight ,
442459 Previous = foundFirst ? previousNote : null ,
443460 } ;
461+
462+ if ( isAirSlide && ! foundFirst )
463+ {
464+ if ( ! AddAirPreviousFromLastNote ( note , chart ) ) // 尝试直接从上一个note添加前驱。如果失败了报警告。
465+ alerts . Add ( new Alert ( Warning , $ "无法找到 Air Slide 的前驱音符", ( chart , note . Time ) , idx + 1 , lines [ idx ] ) ) ;
466+ }
444467
445468 chart . Notes . Add ( note ) ;
446469 previousNote = note ;
@@ -508,34 +531,25 @@ private void ParseCellWidth(string code, int startIdx, ChuNote note, List<Alert>
508531
509532 private void ParseAirNote ( string code , ChuNote note , List < Alert > alerts , int lineNum , ChuChart chart )
510533 {
534+ note . Type = "AIR" ; // 出错情况下的缺省值
511535 if ( code . Length < 5 )
512536 {
513537 alerts . Add ( new Alert ( Warning , $ "AIR 音符代码过短: { code } ") { Line = lineNum } ) ;
514- note . Type = "AIR" ;
515538 return ;
516539 }
517540
518541 ParseCellWidth ( code , 1 , note , alerts , lineNum , chart ) ;
519542 var mainPart = code [ 3 ..] ;
520543
521- if ( mainPart . Length < 2 )
522- {
523- alerts . Add ( new Alert ( Warning , $ "AIR 音符方向代码过短: { code } ") { Line = lineNum } ) ;
524- note . Type = "AIR" ;
525- return ;
526- }
527-
528- var dir = mainPart [ ..2 ] ;
529- if ( U2C_AirDirections . TryGetValue ( dir , out var airType ) )
530- {
531- note . Type = airType ;
532- }
533- else
534- {
535- note . Type = "AIR" ;
536- alerts . Add ( new Alert ( Warning , $ "未知的 AIR 方向: { dir } ") { Line = lineNum , RelevantNote = FormatNoteRef ( note , code ) } ) ;
537- }
544+ // 解析方向
545+ var direction = mainPart [ ..2 ] ;
546+ if ( U2C_AirDirections . TryGetValue ( direction , out var airType ) ) note . Type = airType ;
547+ else alerts . Add ( new Alert ( Warning , $ "未知的 AIR 方向: { direction } ") { Line = lineNum , RelevantNote = FormatNoteRef ( note , code ) } ) ;
548+ // 解析颜色
538549 ParseHeightAndColor ( note , mainPart [ 2 ..] , alerts , lineNum , "a" ) ;
550+
551+ if ( ! AddAirPreviousFromLastNote ( note , chart ) ) // 尝试直接从上一个note添加前驱。如果失败了报警告。
552+ alerts . Add ( new Alert ( Warning , $ "无法找到 Air 的前驱音符", ( chart , note . Time ) , lineNum + 1 , code ) ) ;
539553 }
540554
541555 private int ParseAirCrushNote ( string [ ] lines , int idx , string code , ChuNote note , List < Alert > alerts , ChuChart chart )
0 commit comments