diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs index 2f269d9f5..97a7ce2d0 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs @@ -45,10 +45,9 @@ protected override void ParseStreamInto(LineBufferedReader stream, Beatmap outpu var startTime = timeTags.FirstOrDefault(x => x.Time > 0).Time; var duration = timeTags.LastOrDefault(x => x.Time > 0).Time - startTime; - var lyric = line.Text; - output.HitObjects.Add(new LyricLine + var lyric = new LyricLine { - Text = lyric, + Text = line.Text, // Start time and end time should be re-assigned StartTime = startTime, Duration = duration, @@ -59,13 +58,15 @@ protected override void ParseStreamInto(LineBufferedReader stream, Beatmap outpu return new TimeTagIndex(index, state); }, v => (double)v.Time), - RubyTags = result.QueryRubies(lyric).Select(ruby => new RubyTag + RubyTags = result.QueryRubies(line.Text).Select(ruby => new RubyTag { Text = ruby.Ruby.Ruby, StartIndex = ruby.StartIndex, EndIndex = ruby.EndIndex }).ToArray() - }); + }; + lyric.InitialWorkingTime(); + output.HitObjects.Add(lyric); } catch (Exception ex) { diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs index cc3ae0670..5c7422951 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Karaoke.Beatmaps.Patterns; using osu.Game.Rulesets.Karaoke.Objects; namespace osu.Game.Rulesets.Karaoke.Beatmaps @@ -24,73 +25,8 @@ public override void PostProcess() if (!lyrics.Any()) return; - // re-arrange layout - layoutArrangement(lyrics); - } - - /// - /// Calculate arrangement and assign layout number - /// - /// - /// Lyric | Anchor | LayoutIndex | - /// ---------------------------------------- - /// **** (left) 1 - /// ***** (right) 0 - /// ----------- - /// ******* (left) 3 - /// ***** (left) 4 - /// ***** (left) 5 - /// ----------- - /// ******* (left) 6 - /// ***** (left) 7 - /// ****** (right) 8 - /// **** (right) 9 - /// ----------- - /// ****** (left) 10 - /// ****** (right) 11 - /// ****** (left) 12 - /// ****** (right) 13 - /// - /// - /// - private void layoutArrangement(IList lyrics, bool bottomOnly = false) - { - // Force change to new line if lyric has long time - const int new_lyric_line_time = 15000; - const int number_of_line = 2; - - // Apply layout index - for (int i = 0; i < lyrics.Count; i++) - { - var previousCycleLyric = i >= number_of_line ? lyrics[i - number_of_line] : null; - var previousLyric = i >= 1 ? lyrics[i - 1] : null; - var lyric = lyrics[i]; - - // Force change layout - if (lyric.StartTime - previousLyric?.EndTime > new_lyric_line_time) - lyric.LayoutIndex = 1; - // Change to next layout - else if (previousLyric?.LayoutIndex == 1) - lyric.LayoutIndex = 0; - // Change to first layout index - else - lyric.LayoutIndex = 1; - } - - // Apply start time - for (int i = 0; i < lyrics.Count; i++) - { - var lastLyricLine = i >= number_of_line ? lyrics[i - number_of_line] : null; - var lyricLine = lyrics[i]; - - if (lastLyricLine != null) - { - // Adjust start time and end time - lyricLine.StartTime = lastLyricLine.EndTime + 1000; - } - } - - // TODO : Apply end time? + var pattern = new LegacyKaraokeLayoutGenerator(); + pattern.Generate(lyrics); } } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/IPatternGenerator.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/IPatternGenerator.cs new file mode 100644 index 000000000..7ac267fa7 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/IPatternGenerator.cs @@ -0,0 +1,12 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Patterns +{ + public interface IPatternGenerator + { + void Generate(IEnumerable hitObjects); + } +} diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/LegacyKaraokeLayoutGenerator.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/LegacyKaraokeLayoutGenerator.cs new file mode 100644 index 000000000..7b53464d0 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/LegacyKaraokeLayoutGenerator.cs @@ -0,0 +1,98 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Rulesets.Karaoke.Objects; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Patterns +{ + public class LegacyKaraokeLayoutGenerator : IPatternGenerator + { + private const int number_of_line = 2; + + public void Generate(IEnumerable hitObjects) + { + var lyrics = hitObjects.ToList(); + + // Re-arrange layout + assignLayoutArrangement(lyrics); + + // Re-assign time + assignLyricTime(lyrics); + } + + /// + /// Calculate arrangement and assign layout number + /// + /// + /// Lyric | Anchor | LayoutIndex | + /// ---------------------------------------- + /// **** (left) 1 + /// ***** (right) 0 + /// ----------- + /// ******* (left) 3 + /// ***** (left) 4 + /// ***** (left) 5 + /// ----------- + /// ******* (left) 6 + /// ***** (left) 7 + /// ****** (right) 8 + /// **** (right) 9 + /// ----------- + /// ****** (left) 10 + /// ****** (right) 11 + /// ****** (left) 12 + /// ****** (right) 13 + /// + /// + /// + private void assignLayoutArrangement(IList lyrics, bool bottomOnly = false) + { + // Force change to new line if lyric has long time + const int new_lyric_line_time = 15000; + + // Apply layout index + for (int i = 0; i < lyrics.Count; i++) + { + var previousCycleLyric = i >= number_of_line ? lyrics[i - number_of_line] : null; + var previousLyric = i >= 1 ? lyrics[i - 1] : null; + var lyric = lyrics[i]; + + // Force change layout + if (lyric.StartTime - previousLyric?.EndTime > new_lyric_line_time) + lyric.LayoutIndex = 1; + // Change to next layout + else if (previousLyric?.LayoutIndex == 1) + lyric.LayoutIndex = 0; + // Change to first layout index + else + lyric.LayoutIndex = 1; + } + } + + private void assignLyricTime(IList lyrics) + { + // Reset working time + lyrics.ForEach(h => h.InitialWorkingTime()); + + // Apply start time + for (int i = 0; i < lyrics.Count; i++) + { + var lastLyricLine = i >= number_of_line ? lyrics[i - number_of_line] : null; + var lyricLine = lyrics[i]; + + if (lastLyricLine != null) + { + // Adjust start time and end time + var lyricEndTime = lyricLine.EndTime; + lyricLine.StartTime = lastLyricLine.EndTime + 1000; + + // Should re-assign duration here + lyricLine.Duration = lyricEndTime - lyricLine.StartTime; + } + } + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Objects/LyricLine.cs b/osu.Game.Rulesets.Karaoke/Objects/LyricLine.cs index e2d63d8fc..78e720c50 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/LyricLine.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/LyricLine.cs @@ -7,7 +7,10 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Karaoke.Beatmaps; using osu.Game.Rulesets.Karaoke.Judgements; using osu.Game.Rulesets.Objects.Types; @@ -69,7 +72,12 @@ public RomajiTag[] RomajiTags } /// - /// Duration + /// Lyric's start time is created from and should not be saved. + /// + public override double StartTime { get => base.StartTime; set => base.StartTime = value; } + + /// + /// Lyric's duration is created from and should not be saved. /// public double Duration { get; set; } @@ -150,5 +158,22 @@ public IEnumerable CreateDefaultNotes() } public override Judgement CreateJudgement() => new KaraokeLyricJudgement(); + + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + + // Add because it will cause error on exit then enter gameplay. + StartTimeBindable.UnbindAll(); + + // Initial working start and end time. + InitialWorkingTime(); + } + + public void InitialWorkingTime() + { + StartTime = LyricStartTime; + Duration = LyricDuration; + } } }