@@ -276,19 +276,11 @@ private int ParseNoteLine(string[] lines, int idx, ChuChart chart, List<Alert> a
276276 break ;
277277
278278 case 'h' :
279- idx = ParseHoldNote ( false , lines , idx , code , note , alerts , chart ) ;
280- break ;
281279 case 'H' : // Air Hold
282- idx = ParseHoldNote ( true , lines , idx , code , note , alerts , chart ) ;
283- break ;
284-
285280 case 's' :
286- idx = ParseSlideNote ( false , lines , idx , code , note , alerts , chart ) ;
287- note = null ; // ParseSlideNote中,会自己构造note并自己添加进chart。因此这里默认的统一note不应被添加进chart。
288- break ;
289281 case 'S' : // Air Slide
290- idx = ParseSlideNote ( true , lines , idx , code , note , alerts , chart ) ;
291- note = null ;
282+ idx = ParseHoldOrSlideNote ( typeChar , lines , idx , code , note , alerts , chart ) ;
283+ note = null ; // ParseHoldOrSlideNote中,会自己构造note并自己添加进chart。因此这里默认的统一note不应被添加进chart。
292284 break ;
293285
294286 case 'a' :
@@ -382,33 +374,6 @@ private void ParseHeightAndColor(ChuNote n, string str, List<Alert> alerts, int
382374 else alerts . Add ( new Alert ( Warning , "解析Air系列音符的高度属性失败!" , n . Time , null , lineNum , FormatNoteRef ( n , str ) ) ) ;
383375 }
384376 }
385-
386- private int ParseHoldNote ( bool isAirHold , string [ ] lines , int idx , string code , ChuNote note , List < Alert > alerts , ChuChart chart )
387- {
388- note . Type = isAirHold ? "AHD" : "HLD" ;
389- ParseCellWidth ( code , 1 , note , alerts , idx + 1 , chart ) ;
390- if ( isAirHold ) ParseHeightAndColor ( note , code [ 3 ..] , alerts , idx + 1 , "H" ) ;
391-
392- bool foundFirst = false ;
393- while ( idx + 1 < lines . Length )
394- {
395- var nextLine = lines [ idx + 1 ] . Trim ( ) ;
396- if ( ! TryParseFollowerLine ( nextLine , out var marker , out var endTick , out _ , out _ , out _ , false ) )
397- {
398- if ( nextLine . StartsWith ( '\' ' ) || nextLine . StartsWith ( '@' ) ) { idx ++ ; continue ; }
399- break ;
400- }
401-
402- note . Duration = new Rational ( endTick , RSL ) ;
403- if ( isAirHold && marker == "c" ) note . Type = "AHX" ; // 可能是对应于UMIGURI文档中的 AirHold的 AIR-ACTION 无し终点
404- idx ++ ;
405- foundFirst = true ;
406- }
407-
408- if ( ! foundFirst )
409- alerts . Add ( new Alert ( Warning , $ "HLD 音符缺少时长跟随行") { Line = idx + 1 , RelevantNote = lines [ idx ] } ) ;
410- return idx ;
411- }
412377
413378 // UGC中约定Air系列音符都一定紧跟在其Previous的后面。
414379 // 所以我们直接用上一个解析出的note就可以立即确定前驱了,无需再等到最后集中FillPrevious,而且等到最后集中FillPrevious时的结果也可能是错的。
@@ -427,12 +392,14 @@ private bool AddAirPreviousFromLastNote(ChuNote note, ChuChart chart)
427392 return false ;
428393 }
429394
430- private int ParseSlideNote ( bool isAirSlide , string [ ] lines , int idx , string code , ChuNote previousNote , List < Alert > alerts , ChuChart chart )
395+ private int ParseHoldOrSlideNote ( char noteType , string [ ] lines , int idx , string code , ChuNote previousNote , List < Alert > alerts , ChuChart chart )
431396 {
397+ bool isAir = noteType is 'S' or 'H' ;
398+ bool isSlide = noteType is 'S' or 's' ;
432399 // 注:一开始从外面传进来的previousNote,最后并不会被添加进chart里,只是作为第一段的起点参照而已。
433400 var startTime = previousNote . Time ;
434401 ParseCellWidth ( code , 1 , previousNote , alerts , idx + 1 , chart ) ;
435- if ( isAirSlide ) ParseHeightAndColor ( previousNote , code [ 3 ..] , alerts , idx + 1 , "S" ) ;
402+ if ( isAir ) ParseHeightAndColor ( previousNote , code [ 3 ..] , alerts , idx + 1 , noteType . ToString ( ) ) ;
436403 previousNote . EndCell = previousNote . Cell ;
437404 previousNote . EndWidth = previousNote . Width ;
438405 previousNote . EndHeight = previousNote . Height ;
@@ -441,26 +408,42 @@ private int ParseSlideNote(bool isAirSlide, string[] lines, int idx, string code
441408 while ( idx + 1 < lines . Length )
442409 { // 循环处理所有的跟随行。idx始终指向上一条已经处理完的行。
443410 var nextLine = lines [ idx + 1 ] . Trim ( ) ;
444- if ( ! TryParseFollowerLine ( nextLine , out var marker , out var endTick , out var endCell , out var endWidth , out var endHeight , true ) )
411+ if ( ! TryParseFollowerLine ( nextLine , out var marker , out var endTick , out var endCell , out var endWidth , out var endHeight , isSlide ) )
445412 {
446413 if ( nextLine . StartsWith ( '\' ' ) || nextLine . StartsWith ( '@' ) ) { idx ++ ; continue ; }
447414 break ;
448415 }
449416
450- var type = isAirSlide ? ( marker == "s" ? "ASD" : "ASC" ) : ( marker == "s" ? "SLD" : "SLC" ) ;
417+ var type = noteType switch
418+ {
419+ 's' => marker == "s" ? "SLD" : "SLC" ,
420+ 'S' => marker == "s" ? "ASD" : "ASC" ,
421+ 'h' => "HLD" ,
422+ 'H' => marker == "s" ? "AHD" : "AHX" ,
423+ _ => throw new Exception ( $ "未知的noteType: { noteType } ") ,
424+ } ;
425+ if ( noteType == 'h' && marker == "c" ) alerts . Add ( new Alert ( Warning , $ "Hold不应有c类型的跟随行", ( chart , previousNote . Time ) , idx + 1 , lines [ idx ] ) ) ;
451426
452427 var segmentEnd = startTime + new Rational ( endTick , RSL ) ;
453428 var note = new ChuNote
454429 {
455430 Type = type , Time = previousNote . EndTime ,
456- Cell = previousNote . EndCell , Width = previousNote . EndWidth , Height = previousNote . EndHeight ,
431+ Cell = previousNote . EndCell , Width = previousNote . EndWidth ,
457432 Duration = segmentEnd - previousNote . EndTime , Tag = previousNote . Tag ,
458- EndCell = endCell ! . Value , EndWidth = endWidth ! . Value ,
459- EndHeight = endHeight != null ? U2C_Height ( endHeight . Value ) : previousNote . EndHeight ,
460433 Previous = foundFirst ? previousNote : null ,
461434 } ;
435+ if ( isSlide )
436+ {
437+ note . EndCell = endCell ! . Value ;
438+ note . EndWidth = endWidth ! . Value ;
439+ if ( isAir )
440+ {
441+ note . Height = previousNote . EndHeight ;
442+ note . EndHeight = endHeight != null ? U2C_Height ( endHeight . Value ) : note . Height ;
443+ }
444+ }
462445
463- if ( isAirSlide && ! foundFirst )
446+ if ( isAir && ! foundFirst )
464447 {
465448 if ( ! AddAirPreviousFromLastNote ( note , chart ) ) // 尝试直接从上一个note添加前驱。如果失败了报警告。
466449 alerts . Add ( new Alert ( Warning , $ "无法找到 Air Slide 的前驱音符", ( chart , note . Time ) , idx + 1 , lines [ idx ] ) ) ;
0 commit comments