diff --git a/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs index 645536528..c6f57a537 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs @@ -90,7 +90,7 @@ public void TestDecodeStyle() // Check layout and font index Assert.AreEqual(lyric.LayoutIndex, 2); - Assert.AreEqual(lyric.FontIndex, 3); + Assert.AreEqual(lyric.Singers, new[] { 1, 2 }); } [Test] diff --git a/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricLineStyle.cs b/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricLineStyle.cs index 9f0a4c189..ade1b5c94 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricLineStyle.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricLineStyle.cs @@ -392,7 +392,7 @@ public TestDrawableLyricLine(TestSceneLyricLineStyle testCase, Lyric hitObject) protected override void ApplySkin(ISkinSource skin, bool allowFallback) { // Get layout - Font = skin?.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.LyricStyle, HitObject.FontIndex))?.Value; + Font = skin?.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.LyricStyle, HitObject.Singers))?.Value; base.ApplySkin(skin, allowFallback); } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Utils/SingerUtilsTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Utils/SingerUtilsTest.cs new file mode 100644 index 000000000..257b46011 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke.Tests/Utils/SingerUtilsTest.cs @@ -0,0 +1,31 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Karaoke.Utils; + +namespace osu.Game.Rulesets.Karaoke.Tests.Utils +{ + [TestFixture] + public class SingerUtilsTest + { + [TestCase(null, 0)] + [TestCase(new[] { 1 }, 1)] + [TestCase(new[] { 1, 2, 3 }, 7)] + [TestCase(new[] { 1, 4, 5 }, 25)] + public void TestGetShiftingStyleIndex(int[] singerIndexs, int styleIndex) + { + Assert.AreEqual(SingerUtils.GetShiftingStyleIndex(singerIndexs), styleIndex); + } + + [TestCase(-1, new int[] { })] + [TestCase(0, new int[] { })] + [TestCase(1, new[] { 1 })] + [TestCase(7, new[] { 1, 2, 3 })] + [TestCase(25, new[] { 1, 4, 5 })] + public void TestGetSingersIndex(int styleIndex, int[] singerIndexs) + { + Assert.AreEqual(SingerUtils.GetSingersIndex(styleIndex), singerIndexs); + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs index 77e835e5d..15ad6bd22 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps.Formats; using osu.Game.IO; using osu.Game.Rulesets.Karaoke.Objects; +using osu.Game.Rulesets.Karaoke.Utils; namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats { @@ -234,13 +235,13 @@ private void processStyle(Beatmap beatmap, IList styleLines) return; var layoutIndexStr = line.Split(',').FirstOrDefault(); - var fontIndexStr = line.Split(',').ElementAtOrDefault(1); + var styleIndexStr = line.Split(',').ElementAtOrDefault(1); if (int.TryParse(layoutIndexStr, out int layoutIndex)) lyric.LayoutIndex = layoutIndex; - if (int.TryParse(fontIndexStr, out int fontIndex)) - lyric.FontIndex = fontIndex; + if (int.TryParse(styleIndexStr, out int styleIndex)) + lyric.Singers = SingerUtils.GetSingersIndex(styleIndex); } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs index 774b19848..0416f2268 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs @@ -5,6 +5,7 @@ using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Karaoke.Objects; +using osu.Game.Rulesets.Karaoke.Utils; namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats { @@ -66,7 +67,9 @@ private IEnumerable encodeStyle(Beatmap output) for (var i = 0; i < lyrics.Count; i++) { var lyric = lyrics[i]; - yield return $"@style{i}={lyric.LayoutIndex},{lyric.FontIndex}"; + var layoutIndex = lyric.LayoutIndex; + var styleIndex = SingerUtils.GetShiftingStyleIndex(lyric.Singers); + yield return $"@style{i}={layoutIndex},{styleIndex}"; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs index 0db6913f1..75635fed9 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Karaoke.UI; using osu.Game.Rulesets.Karaoke.UI.Components; using osu.Game.Rulesets.Karaoke.UI.Position; +using osu.Game.Rulesets.Karaoke.Utils; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Skinning; @@ -124,8 +125,9 @@ private MenuItem createFontMenuItem() { ChangeHandler.BeginChange(); + // todo : SingerUtils not using in here, and this logic should be combined into siger manager. if (state == TernaryState.True) - EditorBeatmap.SelectedHitObjects.Cast().ForEach(l => l.FontIndex = x.Key); + EditorBeatmap.SelectedHitObjects.Cast().ForEach(l => l.Singers = SingerUtils.GetSingersIndex(x.Key)); ChangeHandler.EndChange(); })).ToArray() diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs index ee40d965a..85a6f31a3 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs @@ -28,7 +28,7 @@ public class LayoutManager : Component public readonly Bindable PreviewScreenRatio = new Bindable(); - public readonly Bindable PreviewSkinIndex = new Bindable(); + public readonly Bindable PreviewSingers = new Bindable(); [Resolved] private ISkinSource source { get; set; } @@ -69,10 +69,10 @@ public void ChangeCurrenyLayout(KaraokeLayout layout) EditLayout.Value = layout; } - public void ChangePrviewStyle(int styleIndex) + public void ChangePrviewSinger(int[] singers) { - if (styleIndex > 0) - PreviewSkinIndex.Value = styleIndex; + if (singers != null) + PreviewSingers.Value = singers; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs index 40f29ad5f..23b27df35 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs @@ -76,10 +76,10 @@ private void load(LayoutManager manager) Child = new PreviewDrawableLyric(e.NewValue); }, true); - manager.PreviewSkinIndex.BindValueChanged(v => + manager.PreviewSingers.BindValueChanged(v => { if (Child is PreviewDrawableLyric lyric) - lyric.HitObject.FontIndex = v.NewValue; + lyric.HitObject.Singers = v.NewValue; }, true); manager.EditLayout.BindValueChanged(v => diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs index 50eb8c14a..96cbf1b1a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Formats; using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Objects; +using osu.Game.Rulesets.Karaoke.Utils; using System; using System.Collections.Generic; using System.ComponentModel; @@ -80,7 +81,9 @@ private void load(LayoutManager manager) previewStyleDropdown.Current.BindValueChanged(e => { - manager.ChangePrviewStyle(e.NewValue.Key); + // todo : might use dropdown to assign singer, not style. + var singer = SingerUtils.GetSingersIndex(e.NewValue.Key); + manager.ChangePrviewSinger(singer); }, true); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/Components/Badges/StyleInfoBadge.cs b/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/Components/Badges/StyleInfoBadge.cs index 95bee6810..0e4a6b868 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/Components/Badges/StyleInfoBadge.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/Components/Badges/StyleInfoBadge.cs @@ -12,7 +12,7 @@ public class StyleInfoBadge : Badge public StyleInfoBadge(Lyric lyric) : base(lyric) { - lyric.FontIndexBindable.BindValueChanged(value => + lyric.SingersBindable.BindValueChanged(value => { var newStyleIndex = value.NewValue; BadgeText = $"Singer : {newStyleIndex}"; diff --git a/osu.Game.Rulesets.Karaoke/Edit/Singers/Components/Timeline/LyricTimelineHitObjectBlueprint.cs b/osu.Game.Rulesets.Karaoke/Edit/Singers/Components/Timeline/LyricTimelineHitObjectBlueprint.cs index 999b99c64..f9bbc5c37 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Singers/Components/Timeline/LyricTimelineHitObjectBlueprint.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Singers/Components/Timeline/LyricTimelineHitObjectBlueprint.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK.Graphics; +using System.Linq; namespace osu.Game.Rulesets.Karaoke.Edit.Singers.Components.Timeline { @@ -54,10 +55,10 @@ public LyricTimelineHitObjectBlueprint(HitObject hitObject, Singer singer) if (hitObject is Lyric lyric) { - lyric.FontIndexBindable.BindValueChanged(e => + lyric.SingersBindable.BindValueChanged(e => { - // todo : should use better way to check is singer sing this lyric - var isSingerMatch = e.NewValue == singer.ID; + // Check is lyric contains this singer, or default singer + var isSingerMatch = e.NewValue?.Contains(singer.ID) ?? singer.ID == 0; if (isSingerMatch) { Show(); diff --git a/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableLyric.cs b/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableLyric.cs index 0230fc5e1..b090371c9 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableLyric.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableLyric.cs @@ -53,7 +53,7 @@ public DrawableLyric(Lyric hitObject) hitObject.RomajiTagsBindable.BindValueChanged(romajiTags => { ApplyRomaji(); }, true); - hitObject.FontIndexBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); }, true); + hitObject.SingersBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); }, true); hitObject.LayoutIndexBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); }, true); @@ -83,7 +83,7 @@ protected override void ApplySkin(ISkinSource skin, bool allowFallback) if (CurrentSkin == null) return; - skin.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.LyricStyle, HitObject.FontIndex))?.BindValueChanged(karaokeFont => + skin.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.LyricStyle, HitObject.Singers))?.BindValueChanged(karaokeFont => { if (karaokeFont.NewValue != null) ApplyFont(karaokeFont.NewValue); diff --git a/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableNote.cs index 4e1fe94c7..9913ce984 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/Drawables/DrawableNote.cs @@ -35,7 +35,7 @@ public class DrawableNote : DrawableKaraokeScrollingHitObject, IKeyBinding public IBindable Display => HitObject.DisplayBindable; - public IBindable StyleIndex => HitObject.StyleIndexBindable; + public IBindable Singers => HitObject.SingersBindable; public DrawableNote(Note note) : base(note) @@ -62,7 +62,7 @@ public DrawableNote(Note note) note.AlternativeTextBindable.BindValueChanged(_ => { changeText(note); }, true); - note.StyleIndexBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); }, true); + note.SingersBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); }, true); } protected override void ApplySkin(ISkinSource skin, bool allowFallback) @@ -72,7 +72,7 @@ protected override void ApplySkin(ISkinSource skin, bool allowFallback) if (CurrentSkin == null) return; - var noteSkin = skin.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.NoteStyle, HitObject.StyleIndex))?.Value; + var noteSkin = skin.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.NoteStyle, HitObject.Singers))?.Value; if (noteSkin == null) return; diff --git a/osu.Game.Rulesets.Karaoke/Objects/Drawables/Pieces/DefaultBodyPiece.cs b/osu.Game.Rulesets.Karaoke/Objects/Drawables/Pieces/DefaultBodyPiece.cs index 8d0e9857a..707960512 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/Drawables/Pieces/DefaultBodyPiece.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/Drawables/Pieces/DefaultBodyPiece.cs @@ -27,7 +27,7 @@ public class DefaultBodyPiece : Container private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize); private readonly IBindable isHitting = new Bindable(); private readonly IBindable display = new Bindable(); - private readonly IBindable styleIndex = new Bindable(); + private readonly IBindable singer = new Bindable(); protected Drawable Background { get; private set; } protected Drawable Foreground { get; private set; } @@ -61,19 +61,19 @@ private void load([CanBeNull] DrawableHitObject drawableObject, ISkinSource skin isHitting.BindTo(holdNote.IsHitting); display.BindTo(holdNote.Display); - styleIndex.BindTo(holdNote.StyleIndex); + singer.BindTo(holdNote.Singers); } AccentColour.BindValueChanged(onAccentChanged); HitColour.BindValueChanged(onAccentChanged); isHitting.BindValueChanged(_ => onAccentChanged(), true); display.BindValueChanged(_ => onAccentChanged(), true); - styleIndex.BindValueChanged(value => applySkin(skin, value.NewValue), true); + singer.BindValueChanged(value => applySingerStyle(skin, value.NewValue), true); } - private void applySkin(ISkinSource skin, int styleIndex) + private void applySingerStyle(ISkinSource skin, int[] singers) { - var noteSkin = skin?.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.NoteStyle, styleIndex))?.Value; + var noteSkin = skin?.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.NoteStyle, singers))?.Value; if (noteSkin == null) return; diff --git a/osu.Game.Rulesets.Karaoke/Objects/Lyric.cs b/osu.Game.Rulesets.Karaoke/Objects/Lyric.cs index b3997be15..b576a5ee8 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/Lyric.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/Lyric.cs @@ -12,11 +12,12 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Karaoke.Beatmaps; using osu.Game.Rulesets.Karaoke.Judgements; +using osu.Game.Rulesets.Karaoke.Objects.Types; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Karaoke.Objects { - public class Lyric : KaraokeHitObject, IHasDuration + public class Lyric : KaraokeHitObject, IHasDuration, IHasSingers { public readonly Bindable TextBindable = new Bindable(); @@ -91,15 +92,15 @@ public override double StartTime public double EndTime => StartTime + Duration; [JsonIgnore] - public readonly Bindable FontIndexBindable = new Bindable(); + public readonly Bindable SingersBindable = new Bindable(); /// - /// Font index + /// Singers /// - public int FontIndex + public int[] Singers { - get => FontIndexBindable.Value; - set => FontIndexBindable.Value = value; + get => SingersBindable.Value; + set => SingersBindable.Value = value; } [JsonIgnore] diff --git a/osu.Game.Rulesets.Karaoke/Objects/Note.cs b/osu.Game.Rulesets.Karaoke/Objects/Note.cs index c1f75615b..6a336a6cb 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/Note.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/Note.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Karaoke.Objects { - public class Note : KaraokeHitObject, IHasDuration, IHasText + public class Note : KaraokeHitObject, IHasDuration, IHasText, IHasSingers { public readonly Bindable TextBindable = new Bindable(); @@ -36,12 +36,16 @@ public string AlternativeText set => AlternativeTextBindable.Value = value; } - public readonly Bindable StyleIndexBindable = new Bindable(); + [JsonIgnore] + public readonly Bindable SingersBindable = new Bindable(); - public int StyleIndex + /// + /// Singers + /// + public int[] Singers { - get => StyleIndexBindable.Value; - set => StyleIndexBindable.Value = value; + get => SingersBindable.Value; + set => SingersBindable.Value = value; } public readonly Bindable DisplayBindable = new Bindable(); @@ -107,7 +111,7 @@ public Note CopyByTime(double startTime, double duration) StartIndex = StartIndex, EndIndex = EndIndex, Text = Text, - StyleIndex = StyleIndex, + Singers = Singers, Display = Display, Tone = Tone, ParentLyric = ParentLyric diff --git a/osu.Game.Rulesets.Karaoke/Objects/Types/IHasSingers.cs b/osu.Game.Rulesets.Karaoke/Objects/Types/IHasSingers.cs new file mode 100644 index 000000000..4bc6988ca --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Objects/Types/IHasSingers.cs @@ -0,0 +1,10 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Karaoke.Objects.Types +{ + public interface IHasSingers + { + int[] Singers { get; } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Skinning/KaraokeSkinLookup.cs b/osu.Game.Rulesets.Karaoke/Skinning/KaraokeSkinLookup.cs index 653d36698..c19ae5d05 100644 --- a/osu.Game.Rulesets.Karaoke/Skinning/KaraokeSkinLookup.cs +++ b/osu.Game.Rulesets.Karaoke/Skinning/KaraokeSkinLookup.cs @@ -1,10 +1,25 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Karaoke.Utils; +using System.IO; + namespace osu.Game.Rulesets.Karaoke.Skinning { public readonly struct KaraokeSkinLookup { + /// + /// Ctor for and + /// + /// + /// + public KaraokeSkinLookup(KaraokeSkinConfiguration config, int[] singers) + : this(config, SingerUtils.GetShiftingStyleIndex(singers)) + { + if (config != KaraokeSkinConfiguration.LyricStyle && config != KaraokeSkinConfiguration.NoteStyle) + throw new InvalidDataException($"Only {KaraokeSkinConfiguration.LyricStyle} and {KaraokeSkinConfiguration.NoteStyle} can call this ctor."); + } + public KaraokeSkinLookup(KaraokeSkinConfiguration config, int lookup) { Config = config; diff --git a/osu.Game.Rulesets.Karaoke/Skinning/LegacyNotePiece.cs b/osu.Game.Rulesets.Karaoke/Skinning/LegacyNotePiece.cs index 7438a5790..2ea3bb9aa 100644 --- a/osu.Game.Rulesets.Karaoke/Skinning/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Karaoke/Skinning/LegacyNotePiece.cs @@ -32,7 +32,7 @@ public class LegacyNotePiece : LegacyKaraokeColumnElement private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize); private readonly IBindable isHitting = new Bindable(); private readonly IBindable display = new Bindable(); - private readonly IBindable styleIndex = new Bindable(); + private readonly IBindable singer = new Bindable(); public LegacyNotePiece() { @@ -66,14 +66,14 @@ private void load(DrawableHitObject drawableObject, ISkinSource skin, IScrolling isHitting.BindTo(holdNote.IsHitting); display.BindTo(holdNote.Display); - styleIndex.BindTo(holdNote.StyleIndex); + singer.BindTo(holdNote.Singers); } AccentColour.BindValueChanged(onAccentChanged); HitColour.BindValueChanged(onAccentChanged); isHitting.BindValueChanged(onIsHittingChanged, true); display.BindValueChanged(_ => onAccentChanged(), true); - styleIndex.BindValueChanged(value => applySkin(skin, value.NewValue), true); + singer.BindValueChanged(value => applySingerStyle(skin, value.NewValue), true); } private void onIsHittingChanged(ValueChangedEvent isHitting) @@ -102,9 +102,9 @@ private void onIsHittingChanged(ValueChangedEvent isHitting) } } - private void applySkin(ISkinSource skin, int styleIndex) + private void applySingerStyle(ISkinSource skin, int[] singers) { - var noteSkin = skin?.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.NoteStyle, styleIndex))?.Value; + var noteSkin = skin?.GetConfig(new KaraokeSkinLookup(KaraokeSkinConfiguration.NoteStyle, singers))?.Value; if (noteSkin == null) return; diff --git a/osu.Game.Rulesets.Karaoke/Utils/SingerUtils.cs b/osu.Game.Rulesets.Karaoke/Utils/SingerUtils.cs new file mode 100644 index 000000000..cf13d64ff --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Utils/SingerUtils.cs @@ -0,0 +1,25 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; + +namespace osu.Game.Rulesets.Karaoke.Utils +{ + public static class SingerUtils + { + public static int GetShiftingStyleIndex(int[] singerIds) + => singerIds?.Sum(x => (int)Math.Pow(2, x - 1)) ?? 0; + + public static int[] GetSingersIndex(int styleIndex) + { + if (styleIndex < 1) + return Array.Empty(); + + string binary = Convert.ToString(styleIndex, 2); + + return binary.Select((v, i) => new { value = v, singer = binary.Length - i }) + .Where(x => x.value == '1').Select(x => x.singer).OrderBy(x => x).ToArray(); + } + } +}