Skip to content

Commit

Permalink
Merge pull request #135 from andy840119/pattern-generator
Browse files Browse the repository at this point in the history
Fix lyric's start time issue.
  • Loading branch information
andy840119 authored Jul 5, 2020
2 parents 4534ba4 + 8566b15 commit 1d4adcc
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 73 deletions.
11 changes: 6 additions & 5 deletions osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
{
Expand Down
70 changes: 3 additions & 67 deletions osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -24,73 +25,8 @@ public override void PostProcess()
if (!lyrics.Any())
return;

// re-arrange layout
layoutArrangement(lyrics);
}

/// <summary>
/// Calculate arrangement and assign layout number
/// </summary>
/// <example>
/// 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
/// </example>
/// <param name="lyrics"></param>
/// <param name="bottomOnly"></param>
private void layoutArrangement(IList<LyricLine> 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);
}
}
}
12 changes: 12 additions & 0 deletions osu.Game.Rulesets.Karaoke/Beatmaps/Patterns/IPatternGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) andy840119 <[email protected]>. 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<T>
{
void Generate(IEnumerable<T> hitObjects);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) andy840119 <[email protected]>. 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<LyricLine>
{
private const int number_of_line = 2;

public void Generate(IEnumerable<LyricLine> hitObjects)
{
var lyrics = hitObjects.ToList();

// Re-arrange layout
assignLayoutArrangement(lyrics);

// Re-assign time
assignLyricTime(lyrics);
}

/// <summary>
/// Calculate arrangement and assign layout number
/// </summary>
/// <example>
/// 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
/// </example>
/// <param name="lyrics"></param>
/// <param name="bottomOnly"></param>
private void assignLayoutArrangement(IList<LyricLine> 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<LyricLine> 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;
}
}
}
}
}
27 changes: 26 additions & 1 deletion osu.Game.Rulesets.Karaoke/Objects/LyricLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -69,7 +72,12 @@ public RomajiTag[] RomajiTags
}

/// <summary>
/// Duration
/// Lyric's start time is created from <see cref="KaraokeBeatmapProcessor"/> and should not be saved.
/// </summary>
public override double StartTime { get => base.StartTime; set => base.StartTime = value; }

/// <summary>
/// Lyric's duration is created from <see cref="KaraokeBeatmapProcessor"/> and should not be saved.
/// </summary>
public double Duration { get; set; }

Expand Down Expand Up @@ -150,5 +158,22 @@ public IEnumerable<Note> 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;
}
}
}

0 comments on commit 1d4adcc

Please sign in to comment.