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;
+ }
}
}