Skip to content

Commit

Permalink
Merge pull request #2070 from andy840119/add-text-into-time-tag
Browse files Browse the repository at this point in the history
Add romaji text into time tag.
  • Loading branch information
andy840119 authored Jul 16, 2023
2 parents fed09e8 + 51859f5 commit e0ab86c
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 49 deletions.
6 changes: 3 additions & 3 deletions osu.Game.Rulesets.Karaoke.Tests/Objects/LyricTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void TestClone()
Assert.AreNotSame(clonedLyric.TextBindable, lyric.TextBindable);
Assert.AreEqual(clonedLyric.Text, lyric.Text);

Assert.AreNotSame(clonedLyric.TimeTagsVersion, lyric.TimeTagsVersion);
Assert.AreNotSame(clonedLyric.TimeTagsTimingVersion, lyric.TimeTagsTimingVersion);
Assert.AreNotSame(clonedLyric.TimeTagsBindable, lyric.TimeTagsBindable);
TimeTagAssert.ArePropertyEqual(clonedLyric.TimeTags, lyric.TimeTags);

Expand Down Expand Up @@ -202,7 +202,7 @@ public void TestReferenceLyricListPropertyChanged()
TextTagAssert.ArePropertyEqual(referencedLyric.RomajiTags, lyric.RomajiTags);

// and because there's no change inside the tag, so there's version change.
Assert.AreEqual(0, lyric.TimeTagsVersion.Value);
Assert.AreEqual(0, lyric.TimeTagsTimingVersion.Value);
Assert.AreEqual(0, lyric.RubyTagsVersion.Value);
Assert.AreEqual(0, lyric.RomajiTagsVersion.Value);

Expand All @@ -217,7 +217,7 @@ public void TestReferenceLyricListPropertyChanged()
TextTagAssert.ArePropertyEqual(referencedLyric.RomajiTags, lyric.RomajiTags);

// and note that because only one property is different, so version should change once.
Assert.AreEqual(1, lyric.TimeTagsVersion.Value);
Assert.AreEqual(1, lyric.TimeTagsTimingVersion.Value);
Assert.AreEqual(1, lyric.RubyTagsVersion.Value);
Assert.AreEqual(1, lyric.RomajiTagsVersion.Value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites;
private const int whole_chunk_index = -1;

private readonly IBindable<string> textBindable = new Bindable<string>();
private readonly IBindable<int> timeTagsVersion = new Bindable<int>();
private readonly IBindable<int> timeTagsTimingVersion = new Bindable<int>();
private readonly IBindableList<TimeTag> timeTagsBindable = new BindableList<TimeTag>();
private readonly IBindable<int> rubyTagsVersion = new Bindable<int>();
private readonly IBindableList<RubyTag> rubyTagsBindable = new BindableList<RubyTag>();
Expand All @@ -29,15 +29,15 @@ protected DrawableKaraokeSpriteText(Lyric lyric, int chunkIndex = whole_chunk_in
this.chunkIndex = chunkIndex;

textBindable.BindValueChanged(_ => UpdateText(), true);
timeTagsVersion.BindValueChanged(_ => UpdateTimeTags());
timeTagsTimingVersion.BindValueChanged(_ => UpdateTimeTags());
timeTagsBindable.BindCollectionChanged((_, _) => UpdateTimeTags());
rubyTagsVersion.BindValueChanged(_ => UpdateRubies());
rubyTagsBindable.BindCollectionChanged((_, _) => UpdateRubies());
romajiTagsVersion.BindValueChanged(_ => UpdateRomajies());
romajiTagsBindable.BindCollectionChanged((_, _) => UpdateRomajies());

textBindable.BindTo(lyric.TextBindable);
timeTagsVersion.BindTo(lyric.TimeTagsVersion);
timeTagsTimingVersion.BindTo(lyric.TimeTagsTimingVersion);
timeTagsBindable.BindTo(lyric.TimeTagsBindable);
rubyTagsVersion.BindTo(lyric.RubyTagsVersion);
rubyTagsBindable.BindTo(lyric.RubyTagsBindable);
Expand Down
25 changes: 0 additions & 25 deletions osu.Game.Rulesets.Karaoke/Objects/Lyric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ public string Text
set => TextBindable.Value = value;
}

[JsonIgnore]
public IBindable<int> TimeTagsVersion => timeTagsVersion;

private readonly Bindable<int> timeTagsVersion = new();

[JsonIgnore]
public readonly BindableList<TimeTag> TimeTagsBindable = new();

Expand All @@ -66,11 +61,6 @@ public IList<TimeTag> TimeTags
}
}

[JsonIgnore]
public IBindable<int> RubyTagsVersion => rubyTagsVersion;

private readonly Bindable<int> rubyTagsVersion = new();

[JsonIgnore]
public readonly BindableList<RubyTag> RubyTagsBindable = new();

Expand All @@ -87,11 +77,6 @@ public IList<RubyTag> RubyTags
}
}

[JsonIgnore]
public IBindable<int> RomajiTagsVersion => romajiTagsVersion;

private readonly Bindable<int> romajiTagsVersion = new();

[JsonIgnore]
public readonly BindableList<RomajiTag> RomajiTagsBindable = new();

Expand Down Expand Up @@ -188,11 +173,6 @@ public ElementId? ReferenceLyricId
}
}

[JsonIgnore]
public IBindable<int> ReferenceLyricConfigVersion => referenceLyricConfigVersion;

private readonly Bindable<int> referenceLyricConfigVersion = new();

[JsonIgnore]
public readonly Bindable<IReferenceLyricPropertyConfig?> ReferenceLyricConfigBindable = new();

Expand All @@ -205,11 +185,6 @@ public IReferenceLyricPropertyConfig? ReferenceLyricConfig
set => ReferenceLyricConfigBindable.Value = value;
}

[JsonIgnore]
public IBindable<int> LyricPropertyWritableVersion => lyricPropertyWritableVersion;

private readonly Bindable<int> lyricPropertyWritableVersion = new();

public Lyric()
{
workingPropertyValidator = new LyricWorkingPropertyValidator(this);
Expand Down
50 changes: 45 additions & 5 deletions osu.Game.Rulesets.Karaoke/Objects/Lyric_Binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Karaoke.Objects.Properties;
using osu.Game.Rulesets.Karaoke.Objects.Utils;
Expand All @@ -18,6 +19,36 @@ namespace osu.Game.Rulesets.Karaoke.Objects;
/// </summary>
public partial class Lyric
{
[JsonIgnore]
public IBindable<int> TimeTagsTimingVersion => timeTagsTimingVersion;

private readonly Bindable<int> timeTagsTimingVersion = new();

[JsonIgnore]
public IBindable<int> TimeTagsRomajiVersion => timeTagsRomajiVersion;

private readonly Bindable<int> timeTagsRomajiVersion = new();

[JsonIgnore]
public IBindable<int> RubyTagsVersion => rubyTagsVersion;

private readonly Bindable<int> rubyTagsVersion = new();

[JsonIgnore]
public IBindable<int> RomajiTagsVersion => romajiTagsVersion;

private readonly Bindable<int> romajiTagsVersion = new();

[JsonIgnore]
public IBindable<int> ReferenceLyricConfigVersion => referenceLyricConfigVersion;

private readonly Bindable<int> referenceLyricConfigVersion = new();

[JsonIgnore]
public IBindable<int> LyricPropertyWritableVersion => lyricPropertyWritableVersion;

private readonly Bindable<int> lyricPropertyWritableVersion = new();

private void initInternalBindingEvent()
{
TimeTagsBindable.CollectionChanged += (_, args) =>
Expand All @@ -28,24 +59,33 @@ private void initInternalBindingEvent()
Debug.Assert(args.NewItems != null);

foreach (var c in args.NewItems.Cast<TimeTag>())
c.Changed += invalidate;
{
c.TimingChanged += timingInvalidate;
c.RomajiChanged += romajiInvalidate;
}

break;

case NotifyCollectionChangedAction.Reset:
case NotifyCollectionChangedAction.Remove:
Debug.Assert(args.OldItems != null);

foreach (var c in args.OldItems.Cast<TimeTag>())
c.Changed -= invalidate;
{
c.TimingChanged -= timingInvalidate;
c.RomajiChanged -= romajiInvalidate;
}

break;
}

updateLyricTime();

void invalidate() => timeTagsVersion.Value++;
void timingInvalidate() => timeTagsTimingVersion.Value++;
void romajiInvalidate() => timeTagsRomajiVersion.Value++;
};

TimeTagsVersion.ValueChanged += _ =>
TimeTagsTimingVersion.ValueChanged += _ =>
{
updateLyricTime();
};
Expand Down Expand Up @@ -168,7 +208,7 @@ private void initReferenceLyricEvent()
}).ToArray();
});

bindValueChange(e, l => l.TimeTagsVersion, (_, config) =>
bindValueChange(e, l => l.TimeTagsTimingVersion, (_, config) =>
{
if (config is not SyncLyricConfig syncLyricConfig || !syncLyricConfig.SyncTimeTagProperty)
return;
Expand Down
6 changes: 3 additions & 3 deletions osu.Game.Rulesets.Karaoke/Objects/Note_Binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ private void initReferenceLyricEvent()
ReferenceLyricBindable.ValueChanged += e =>
{
if (e.OldValue != null)
e.OldValue.TimeTagsVersion.ValueChanged -= timeTagVersionChanged;
e.OldValue.TimeTagsTimingVersion.ValueChanged -= timeTagsTimingVersionChanged;

if (e.NewValue != null)
e.NewValue.TimeTagsVersion.ValueChanged += timeTagVersionChanged;
e.NewValue.TimeTagsTimingVersion.ValueChanged += timeTagsTimingVersionChanged;

syncStartTimeAndDurationFromTimeTag();
syncReferenceLyricSingers();
};

void timeTagVersionChanged(ValueChangedEvent<int> e) => syncStartTimeAndDurationFromTimeTag();
void timeTagsTimingVersionChanged(ValueChangedEvent<int> e) => syncStartTimeAndDurationFromTimeTag();
}

private void syncStartTimeAndDurationFromTimeTag()
Expand Down
47 changes: 44 additions & 3 deletions osu.Game.Rulesets.Karaoke/Objects/TimeTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@ namespace osu.Game.Rulesets.Karaoke.Objects;
public class TimeTag : IDeepCloneable<TimeTag>
{
/// <summary>
/// Invoked when any property of this <see cref="RubyTag"/> is changed.
/// Invoked when <see cref="Time"/> of this <see cref="TimeTag"/> is changed.
/// </summary>
public event Action? Changed;
public event Action? TimingChanged;

/// <summary>
/// Invoked when <see cref="InitialRomaji"/> or <see cref="RomajiText"/> of this <see cref="TimeTag"/> is changed.
/// </summary>
public event Action? RomajiChanged;

public TimeTag(TextIndex index, double? time = null)
{
Index = index;
Time = time;

TimeBindable.ValueChanged += _ => Changed?.Invoke();
TimeBindable.ValueChanged += _ => TimingChanged?.Invoke();
InitialRomajiBindable.ValueChanged += _ => RomajiChanged?.Invoke();
RomajiTextBindable.ValueChanged += _ => RomajiChanged?.Invoke();
}

/// <summary>
Expand All @@ -42,6 +49,40 @@ public double? Time
set => TimeBindable.Value = value;
}

[JsonIgnore]
public readonly Bindable<bool> InitialRomajiBindable = new();

/// <summary>
/// Mark if this romaji is the first letter of the romaji word.
/// </summary>
/// <example>
/// There's the Japanese lyric:
/// 枯れた世界に輝く
/// There's the Romaji:
/// kareta sekai ni kagayaku.
/// And it will be separated as:
/// ka|re|ta se|kai ni ka|ga|ya|ku.
/// If this is the first or(4th) time-tag, then this value should be true.
/// If this ts the 2th or 3th time-tag, then this value should be false.
/// </example>
public bool InitialRomaji
{
get => InitialRomajiBindable.Value;
set => InitialRomajiBindable.Value = value;
}

[JsonIgnore]
public readonly Bindable<string?> RomajiTextBindable = new();

/// <summary>
/// Romaji
/// </summary>
public string? RomajiText
{
get => RomajiTextBindable.Value;
set => RomajiTextBindable.Value = value;
}

public TimeTag DeepClone()
{
return new TimeTag(Index, Time);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public abstract partial class TimeTagScrollContainer : BindableScrollContainer
{
private readonly IBindable<Lyric?> bindableFocusedLyric = new Bindable<Lyric?>();

private readonly IBindable<int> timeTagsVersion = new Bindable<int>();
private readonly IBindable<int> timeTagsTimingVersion = new Bindable<int>();

[Cached]
private readonly BindableList<TimeTag> timeTagsBindable = new();
Expand All @@ -42,19 +42,19 @@ protected TimeTagScrollContainer()
{
RelativeSizeAxes = Axes.X;

timeTagsVersion.BindValueChanged(_ => updateTimeRange());
timeTagsTimingVersion.BindValueChanged(_ => updateTimeRange());
timeTagsBindable.BindCollectionChanged((_, _) => updateTimeRange());

bindableFocusedLyric.BindValueChanged(e =>
{
timeTagsVersion.UnbindBindings();
timeTagsTimingVersion.UnbindBindings();
timeTagsBindable.UnbindBindings();

var lyric = e.NewValue;
if (lyric == null)
return;

timeTagsVersion.BindTo(lyric.TimeTagsVersion);
timeTagsTimingVersion.BindTo(lyric.TimeTagsTimingVersion);
timeTagsBindable.BindTo(lyric.TimeTagsBindable);

Schedule(() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.LyricList.Rows.

public partial class TimeTagInfo : SubInfo
{
private readonly IBindable<int> bindableTimeTagsVersion;
private readonly IBindable<int> bindableTimeTagsTimingVersion;
private readonly IBindableList<TimeTag> bindableTimeTags;

public TimeTagInfo(Lyric lyric)
: base(lyric)
{
bindableTimeTagsVersion = lyric.TimeTagsVersion.GetBoundCopy();
bindableTimeTagsTimingVersion = lyric.TimeTagsTimingVersion.GetBoundCopy();
bindableTimeTags = lyric.TimeTagsBindable.GetBoundCopy();
}

Expand All @@ -26,7 +26,7 @@ private void load(OsuColour colours)
{
BadgeColour = colours.Green;

bindableTimeTagsVersion.BindValueChanged(_ => updateBadgeText());
bindableTimeTagsTimingVersion.BindValueChanged(_ => updateBadgeText());
bindableTimeTags.BindCollectionChanged((_, _) => updateBadgeText());

updateBadgeText();
Expand Down

0 comments on commit e0ab86c

Please sign in to comment.