From 5d8baad56391c16d48b42fb3b490af473820a71a Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 20:23:22 +0800 Subject: [PATCH 01/12] Add the region. merge. --- .../Edit/ChangeHandlers/Beatmaps/BeatmapPagesChangeHandler.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapPagesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapPagesChangeHandler.cs index b9bb04c94..1102730c9 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapPagesChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapPagesChangeHandler.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; public partial class BeatmapPagesChangeHandler : BeatmapPropertyChangeHandler, IBeatmapPagesChangeHandler { + #region Auto-Generate + [Resolved, AllowNull] private KaraokeRulesetEditGeneratorConfigManager generatorConfigManager { get; set; } @@ -51,6 +53,8 @@ public void AutoGenerate() private PageGeneratorConfig getGeneratorConfig() => generatorConfigManager.Get(); + #endregion + public void Add(Page page) { performPageInfoChanged(pageInfo => From 9a1fdb8f0970025af23adc7cefe100fc663d05d4 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 20:20:31 +0800 Subject: [PATCH 02/12] Implement the auto-generator interface for the lyric property. --- .../ILyricPropertyAutoGenerateChangeHandler.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyAutoGenerateChangeHandler.cs diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyAutoGenerateChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyAutoGenerateChangeHandler.cs new file mode 100644 index 000000000..c15ba30c0 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyAutoGenerateChangeHandler.cs @@ -0,0 +1,13 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Objects; + +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricPropertyAutoGenerateChangeHandler : IAutoGenerateChangeHandler +{ + IDictionary GetGeneratorNotSupportedLyrics(); +} From c97d3dddbbe173729eb783d71c1e92eda52d9bd8 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 21:10:35 +0800 Subject: [PATCH 03/12] Add auto-generator interface for those auto-generate change-handler. --- .../Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs | 2 +- .../Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs | 2 +- .../Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs | 2 +- .../Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs | 2 +- .../Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs index 84dc0bf22..cd994921c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { - public interface ILyricLanguageChangeHandler : ILyricPropertyChangeHandler + public interface ILyricLanguageChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler { void SetLanguage(CultureInfo? language); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs index 5e33bf45d..6abc4d9ee 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { - public interface ILyricReferenceChangeHandler : ILyricPropertyChangeHandler + public interface ILyricReferenceChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler { void UpdateReferenceLyric(Lyric? referenceLyric); diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs index 4094b85ee..18528be5d 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { - public interface ILyricRomajiTagsChangeHandler : ILyricTextTagsChangeHandler + public interface ILyricRomajiTagsChangeHandler : ILyricTextTagsChangeHandler, ILyricPropertyAutoGenerateChangeHandler { } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs index acd3d30bd..51c763a67 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { - public interface ILyricRubyTagsChangeHandler : ILyricTextTagsChangeHandler + public interface ILyricRubyTagsChangeHandler : ILyricTextTagsChangeHandler, ILyricPropertyAutoGenerateChangeHandler { } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs index 2759cb282..900725380 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { - public interface ILyricTimeTagsChangeHandler : ILyricListPropertyChangeHandler + public interface ILyricTimeTagsChangeHandler : ILyricListPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler { void SetTimeTagTime(TimeTag timeTag, double time); From 8b782a9ee681b5fe82a92ecca873da185f0bab3b Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 21:04:16 +0800 Subject: [PATCH 04/12] Add some methods in the base lyric change handler for able to fastly create the generator or detector. --- .../Lyrics/LyricPropertyChangeHandler.cs | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs index 011a6e9df..591a2ba82 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs @@ -1,11 +1,103 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Configuration; +using osu.Game.Rulesets.Karaoke.Edit.Generator; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; using osu.Game.Rulesets.Karaoke.Objects; namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { public abstract partial class LyricPropertyChangeHandler : HitObjectPropertyChangeHandler, ILyricPropertyChangeHandler { + #region Auto-Generate + + [Resolved] + private KaraokeRulesetEditGeneratorConfigManager? generatorConfigManager { get; set; } + + protected LyricPropertyDetector GetDetector() + where TConfig : GeneratorConfig, new() + { + // using reflection to get the detector. + var config = getGeneratorConfig(); + var detectorType = getChildType(typeof(LyricPropertyDetector<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); + var detector = Activator.CreateInstance(detectorType, config) as LyricPropertyDetector; + return detector ?? throw new InvalidOperationException(); + } + + protected LyricPropertyDetector GetDetector(IEnumerable lyrics) + where TConfig : GeneratorConfig, new() + { + // using reflection to get the detector. + var config = getGeneratorConfig(); + var detectorType = getChildType(typeof(LyricPropertyDetector<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); + var detector = Activator.CreateInstance(detectorType, lyrics, config) as LyricPropertyDetector; + return detector ?? throw new InvalidOperationException(); + } + + protected LyricPropertyGenerator GetGenerator() + where TConfig : GeneratorConfig, new() + { + // using reflection to get the generator. + var config = getGeneratorConfig(); + var generatorType = getChildType(typeof(LyricPropertyGenerator<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); + var generator = Activator.CreateInstance(generatorType, config) as LyricPropertyGenerator; + return generator ?? throw new InvalidOperationException(); + } + + protected LyricGeneratorSelector GetSelector() + where TBaseConfig : GeneratorConfig + { + // using reflection to get the selector. + var selectorType = getChildType(typeof(LyricGeneratorSelector<,>).MakeGenericType(typeof(TProperty), typeof(TBaseConfig))); + var selector = Activator.CreateInstance(selectorType, generatorConfigManager) as LyricGeneratorSelector; + return selector ?? throw new InvalidOperationException(); + } + + private Type getChildType(Type type) + { + // should get the assembly that the has the class GeneratorConfig. + var assembly = typeof(GeneratorConfig).Assembly; + return assembly.GetTypes() + .Single(x => type.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); + } + + private TConfig getGeneratorConfig() + where TConfig : GeneratorConfig, new() + { + if (generatorConfigManager == null) + throw new InvalidOperationException(); + + return generatorConfigManager.Get(); + } + + protected bool CanDetect(PropertyDetector detector) + => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(detector.CanDetect); + + protected bool CanGenerate(PropertyGenerator generator) + => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(generator.CanGenerate); + + protected IDictionary GetInvalidMessageFromDetector(PropertyDetector detector) + => HitObjects.Select(x => new KeyValuePair(x, detector.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) + .Where(x => x.Value != null) + .ToDictionary(k => k.Key, v => v.Value!.Value); + + protected IDictionary GetInvalidMessageFromGenerator(PropertyGenerator generator) + => HitObjects.Select(x => new KeyValuePair(x, generator.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) + .Where(x => x.Value != null) + .ToDictionary(k => k.Key, v => v.Value!.Value); + + private LocalisableString? getReferenceLyricInvalidMessage(Lyric lyric) + { + bool locked = IsWritePropertyLocked(lyric); + return locked ? "Cannot modify property because has reference lyric." : default(LocalisableString?); + } + + #endregion } } From 790c18a8b9c771663aa6b7bd7df3065bde444026 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 21:25:05 +0800 Subject: [PATCH 05/12] Implement the interface for the change handler. --- .../Lyrics/LyricLanguageChangeHandler.cs | 29 +++++++++++++++ .../Lyrics/LyricReferenceChangeHandler.cs | 36 +++++++++++++++++++ .../Lyrics/LyricRomajiTagsChangeHandler.cs | 29 +++++++++++++++ .../Lyrics/LyricRubyTagsChangeHandler.cs | 29 +++++++++++++++ .../Lyrics/LyricTimeTagsChangeHandler.cs | 28 +++++++++++++++ 5 files changed, 151 insertions(+) diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs index 9a69fb202..e6045ad3b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Globalization; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language; using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; @@ -10,6 +12,33 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { public partial class LyricLanguageChangeHandler : LyricPropertyChangeHandler, ILyricLanguageChangeHandler { + #region Auto-Generate + + public bool CanGenerate() + { + var detector = GetDetector(); + return CanDetect(detector); + } + + public IDictionary GetGeneratorNotSupportedLyrics() + { + var detector = GetDetector(); + return GetInvalidMessageFromDetector(detector); + } + + public void AutoGenerate() + { + var detector = GetDetector(); + + PerformOnSelection(lyric => + { + var detectedLanguage = detector.Detect(lyric); + lyric.Language = detectedLanguage; + }); + } + + #endregion + public void SetLanguage(CultureInfo? language) { PerformOnSelection(lyric => diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs index b1fa8d7bf..149ca28de 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs @@ -2,7 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric; using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; @@ -11,6 +14,39 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { public partial class LyricReferenceChangeHandler : LyricPropertyChangeHandler, ILyricReferenceChangeHandler { + #region Auto-Generate + + public bool CanGenerate() + { + var detector = GetDetector(HitObjects); + return CanDetect(detector); + } + + public IDictionary GetGeneratorNotSupportedLyrics() + { + var detector = GetDetector(HitObjects); + return GetInvalidMessageFromDetector(detector); + } + + public void AutoGenerate() + { + var detector = GetDetector(HitObjects); + + PerformOnSelection(lyric => + { + var referencedLyric = detector.Detect(lyric); + lyric.ReferenceLyricId = referencedLyric?.ID; + + // technically this property should be assigned by beatmap processor, but should be OK to assign here for testing purpose. + lyric.ReferenceLyric = referencedLyric; + + if (lyric.ReferenceLyricId != null && lyric.ReferenceLyricConfig is not SyncLyricConfig) + lyric.ReferenceLyricConfig = new SyncLyricConfig(); + }); + } + + #endregion + public void UpdateReferenceLyric(Lyric? referenceLyric) { if (referenceLyric != null && !HitObjects.Contains(referenceLyric)) diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs index 205d56ef7..900d450ba 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs @@ -1,6 +1,9 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags; using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; @@ -8,6 +11,32 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { public partial class LyricRomajiTagsChangeHandler : LyricTextTagsChangeHandler, ILyricRomajiTagsChangeHandler { + #region Auto-Generate + + public bool CanGenerate() + { + var generator = GetSelector(); + return CanGenerate(generator); + } + + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetSelector(); + return GetInvalidMessageFromGenerator(generator); + } + + public void AutoGenerate() + { + var generator = GetSelector(); + + PerformOnSelection(lyric => + { + lyric.RomajiTags = generator.Generate(lyric); + }); + } + + #endregion + protected override bool ContainsInLyric(Lyric lyric, RomajiTag textTag) => lyric.RomajiTags.Contains(textTag); diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs index 3a727c365..e255d142f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs @@ -1,6 +1,9 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags; using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; @@ -8,6 +11,32 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { public partial class LyricRubyTagsChangeHandler : LyricTextTagsChangeHandler, ILyricRubyTagsChangeHandler { + #region Auto-Generate + + public bool CanGenerate() + { + var generator = GetSelector(); + return CanGenerate(generator); + } + + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetSelector(); + return GetInvalidMessageFromGenerator(generator); + } + + public void AutoGenerate() + { + var generator = GetSelector(); + + PerformOnSelection(lyric => + { + lyric.RubyTags = generator.Generate(lyric); + }); + } + + #endregion + protected override bool ContainsInLyric(Lyric lyric, RubyTag textTag) => lyric.RubyTags.Contains(textTag); diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs index 360c05da4..c8323071f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags; using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; @@ -13,6 +15,32 @@ namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics { public partial class LyricTimeTagsChangeHandler : LyricPropertyChangeHandler, ILyricTimeTagsChangeHandler { + #region Auto-Generate + + public bool CanGenerate() + { + var generator = GetSelector(); + return CanGenerate(generator); + } + + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetSelector(); + return GetInvalidMessageFromGenerator(generator); + } + + public void AutoGenerate() + { + var generator = GetSelector(); + + PerformOnSelection(lyric => + { + lyric.TimeTags = generator.Generate(lyric); + }); + } + + #endregion + public void SetTimeTagTime(TimeTag timeTag, double time) { CheckExactlySelectedOneHitObject(); From e1a16dd7f3eac93fb2a025e2c7b8e8bb0845441e Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 21:29:05 +0800 Subject: [PATCH 06/12] Implement the change the handler for able to generate the notes by the lyric. --- .../Lyrics/LyricNotesChangeHandlerTest.cs | 10 ++++ .../Lyrics/ILyricNotesChangeHandler.cs | 8 +++ .../Lyrics/LyricNotesChangeHandler.cs | 53 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs create mode 100644 osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricNotesChangeHandler.cs create mode 100644 osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricNotesChangeHandler.cs diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs new file mode 100644 index 000000000..d516f2a59 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.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. + +using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; + +public partial class LyricNotesChangeHandlerTest : LyricPropertyChangeHandlerTest +{ +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricNotesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricNotesChangeHandler.cs new file mode 100644 index 000000000..245ad271a --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricNotesChangeHandler.cs @@ -0,0 +1,8 @@ +// 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.Edit.ChangeHandlers.Lyrics; + +public interface ILyricNotesChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler +{ +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricNotesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricNotesChangeHandler.cs new file mode 100644 index 000000000..7707916de --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricNotesChangeHandler.cs @@ -0,0 +1,53 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using osu.Framework.Allocation; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes; +using osu.Game.Rulesets.Karaoke.Edit.Utils; +using osu.Game.Rulesets.Karaoke.Objects; +using osu.Game.Screens.Edit; + +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricNotesChangeHandler : LyricPropertyChangeHandler, ILyricNotesChangeHandler +{ + #region Auto-Generate + + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } + + public bool CanGenerate() + { + var generator = GetGenerator(); + return CanGenerate(generator); + } + + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetGenerator(); + return GetInvalidMessageFromGenerator(generator); + } + + public void AutoGenerate() + { + var generator = GetGenerator(); + + PerformOnSelection(lyric => + { + // clear exist notes if from those + var matchedNotes = EditorBeatmapUtils.GetNotesByLyric(beatmap, lyric); + RemoveRange(matchedNotes); + + var notes = generator.Generate(lyric); + AddRange(notes); + }); + } + + #endregion + + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsCreateOrRemoveNoteLocked(lyric); +} From feb5634a46546322a2d438c7904c166889b8bef3 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 21:38:35 +0800 Subject: [PATCH 07/12] Separate the test cases. --- .../LyricAutoGenerateChangeHandlerTest.cs | 270 ------------------ .../Lyrics/LyricLanguageChangeHandlerTest.cs | 38 +++ .../Lyrics/LyricNotesChangeHandlerTest.cs | 60 ++++ .../Lyrics/LyricReferenceChangeHandlerTest.cs | 45 +++ .../LyricRomajiTagsChangeHandlerTest.cs | 49 ++++ .../Lyrics/LyricRubyTagsChangeHandlerTest.cs | 49 ++++ .../Lyrics/LyricTimeTagsChangeHandlerTest.cs | 48 ++++ 7 files changed, 289 insertions(+), 270 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs index 400e78b65..9dc520c86 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs @@ -4,14 +4,9 @@ using System.Globalization; using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; -using osu.Game.Rulesets.Karaoke.Edit.Generator; -using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; -using osu.Game.Rulesets.Karaoke.Objects.Properties; -using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; @@ -19,271 +14,6 @@ public partial class LyricAutoGenerateChangeHandlerTest : LyricPropertyChangeHan { protected override bool IncludeAutoGenerator => true; - #region Reference lyric - - [Test] - public void TestDetectReferenceLyric() - { - PrepareHitObject(() => new Lyric - { - Text = "カラオケ" - }, false); - - PrepareHitObject(() => new Lyric - { - Text = "カラオケ" - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.DetectReferenceLyric)); - - AssertSelectedHitObject(h => - { - Assert.IsNotNull(h.ReferenceLyric); - Assert.IsTrue(h.ReferenceLyricConfig is SyncLyricConfig); - }); - } - - [Test] - public void TestDetectReferenceLyricWithNonSupportedLyric() - { - PrepareHitObject(() => new Lyric - { - Text = "カラオケ" - }, false); - - PrepareHitObject(() => new Lyric - { - Text = "???" - }); - - TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.DetectReferenceLyric)); - } - - #endregion - - #region Language - - [Test] - public void TestDetectLanguage() - { - PrepareHitObject(() => new Lyric - { - Text = "カラオケ" - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.DetectLanguage)); - - AssertSelectedHitObject(h => - { - Assert.AreEqual(new CultureInfo("ja"), h.Language); - }); - } - - [Test] - public void TestDetectLanguageWithNonSupportedLyric() - { - PrepareHitObject(() => new Lyric - { - Text = "???" - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.DetectLanguage)); - - AssertSelectedHitObject(h => - { - Assert.IsNull(h.Language); - }); - } - - #endregion - - #region Ruby - - [Test] - public void TestAutoGenerateRubyTags() - { - PrepareHitObject(() => new Lyric - { - Text = "風", - Language = new CultureInfo(17) - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRubyTags)); - - AssertSelectedHitObject(h => - { - var rubyTags = h.RubyTags; - Assert.AreEqual(1, rubyTags.Count); - Assert.AreEqual("かぜ", rubyTags[0].Text); - }); - } - - [Test] - public void TestAutoGenerateRubyTagsWithNonSupportedLyric() - { - PrepareHitObjects(() => new[] - { - new Lyric - { - Text = "風", - }, - new Lyric - { - Text = string.Empty, - }, - new Lyric - { - Text = string.Empty, - Language = new CultureInfo(17) - }, - }); - - TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRubyTags)); - } - - #endregion - - #region Romaji - - [Test] - public void TestAutoGenerateRomajiTags() - { - PrepareHitObject(() => new Lyric - { - Text = "風", - Language = new CultureInfo(17) - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRomajiTags)); - - AssertSelectedHitObject(h => - { - var romajiTags = h.RomajiTags; - Assert.AreEqual(1, romajiTags.Count); - Assert.AreEqual("kaze", romajiTags[0].Text); - }); - } - - [Test] - public void TestAutoGenerateRomajiTagsWithNonSupportedLyric() - { - PrepareHitObjects(() => new[] - { - new Lyric - { - Text = "風", - }, - new Lyric - { - Text = string.Empty, - }, - new Lyric - { - Text = string.Empty, - Language = new CultureInfo(17) - }, - }); - - TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRomajiTags)); - } - - #endregion - - #region TimeTag - - [Test] - public void TestAutoGenerateTimeTags() - { - PrepareHitObject(() => new Lyric - { - Text = "カラオケ", - Language = new CultureInfo(17) - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateTimeTags)); - - AssertSelectedHitObject(h => - { - Assert.AreEqual(5, h.TimeTags.Count); - }); - } - - [Test] - public void TestAutoGenerateTimeTagsWithNonSupportedLyric() - { - PrepareHitObjects(() => new[] - { - new Lyric - { - Text = "カラオケ", - }, - new Lyric - { - Text = string.Empty, - }, - new Lyric - { - Text = string.Empty, - Language = new CultureInfo(17) - }, - }); - - TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateTimeTags)); - } - - #endregion - - #region Note - - [Test] - public void TestAutoGenerateNotes() - { - PrepareHitObject(() => new Lyric - { - Text = "カラオケ", - TimeTags = new[] - { - new TimeTag(new TextIndex(0), 0), - new TimeTag(new TextIndex(1), 1000), - new TimeTag(new TextIndex(2), 2000), - new TimeTag(new TextIndex(3), 3000), - new TimeTag(new TextIndex(3, TextIndex.IndexState.End), 4000), - } - }); - - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateNotes)); - - AssertSelectedHitObject(h => - { - var actualNotes = getMatchedNotes(h); - Assert.AreEqual(4, actualNotes.Length); - - Assert.AreEqual("カ", actualNotes[0].Text); - Assert.AreEqual("ラ", actualNotes[1].Text); - Assert.AreEqual("オ", actualNotes[2].Text); - Assert.AreEqual("ケ", actualNotes[3].Text); - }); - } - - [Test] - public void TestAutoGenerateNotesWithNonSupportedLyric() - { - PrepareHitObject(() => new Lyric - { - Text = "カラオケ", - }); - - TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateNotes)); - } - - private Note[] getMatchedNotes(Lyric lyric) - { - var editorBeatmap = Dependencies.Get(); - return EditorBeatmapUtils.GetNotesByLyric(editorBeatmap, lyric).ToArray(); - } - - #endregion - # region With reference lyric [TestCase(LyricAutoGenerateProperty.DetectReferenceLyric, true)] diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricLanguageChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricLanguageChangeHandlerTest.cs index 5ba493d40..d39d95958 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricLanguageChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricLanguageChangeHandlerTest.cs @@ -10,6 +10,44 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; public partial class LyricLanguageChangeHandlerTest : LyricPropertyChangeHandlerTest { + protected override bool IncludeAutoGenerator => true; + + #region Auto-Generate + + [Test] + public void TestDetectLanguage() + { + PrepareHitObject(() => new Lyric + { + Text = "カラオケ" + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + Assert.AreEqual(new CultureInfo("ja"), h.Language); + }); + } + + [Test] + public void TestDetectLanguageWithNonSupportedLyric() + { + PrepareHitObject(() => new Lyric + { + Text = "???" + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + Assert.IsNull(h.Language); + }); + } + + #endregion + [Test] public void TestSetLanguageToJapanese() { diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs index d516f2a59..11fcb41de 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricNotesChangeHandlerTest.cs @@ -1,10 +1,70 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; +using osu.Game.Rulesets.Karaoke.Edit.Utils; +using osu.Game.Rulesets.Karaoke.Objects; +using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; public partial class LyricNotesChangeHandlerTest : LyricPropertyChangeHandlerTest { + protected override bool IncludeAutoGenerator => true; + + #region Note + + [Test] + public void TestAutoGenerateNotes() + { + PrepareHitObject(() => new Lyric + { + Text = "カラオケ", + TimeTags = new[] + { + new TimeTag(new TextIndex(0), 0), + new TimeTag(new TextIndex(1), 1000), + new TimeTag(new TextIndex(2), 2000), + new TimeTag(new TextIndex(3), 3000), + new TimeTag(new TextIndex(3, TextIndex.IndexState.End), 4000), + } + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + var actualNotes = getMatchedNotes(h); + Assert.AreEqual(4, actualNotes.Length); + + Assert.AreEqual("カ", actualNotes[0].Text); + Assert.AreEqual("ラ", actualNotes[1].Text); + Assert.AreEqual("オ", actualNotes[2].Text); + Assert.AreEqual("ケ", actualNotes[3].Text); + }); + } + + [Test] + public void TestAutoGenerateNotesWithNonSupportedLyric() + { + PrepareHitObject(() => new Lyric + { + Text = "カラオケ", + }); + + TriggerHandlerChangedWithException(c => c.AutoGenerate()); + } + + private Note[] getMatchedNotes(Lyric lyric) + { + var editorBeatmap = Dependencies.Get(); + return EditorBeatmapUtils.GetNotesByLyric(editorBeatmap, lyric).ToArray(); + } + + #endregion } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricReferenceChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricReferenceChangeHandlerTest.cs index a6c3ff5f9..41e34237c 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricReferenceChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricReferenceChangeHandlerTest.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; @@ -10,6 +11,50 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; public partial class LyricReferenceChangeHandlerTest : LyricPropertyChangeHandlerTest { + protected override bool IncludeAutoGenerator => true; + + #region Auto-Generate + + [Test] + public void TestDetectReferenceLyric() + { + PrepareHitObject(() => new Lyric + { + Text = "カラオケ" + }, false); + + PrepareHitObject(() => new Lyric + { + Text = "カラオケ" + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + Assert.IsNotNull(h.ReferenceLyric); + Assert.IsTrue(h.ReferenceLyricConfig is SyncLyricConfig); + }); + } + + [Test] + public void TestDetectReferenceLyricWithNonSupportedLyric() + { + PrepareHitObject(() => new Lyric + { + Text = "カラオケ" + }, false); + + PrepareHitObject(() => new Lyric + { + Text = "???" + }); + + TriggerHandlerChangedWithException(c => c.AutoGenerate()); + } + + #endregion + [Test] public void TestUpdateReferenceLyric() { diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandlerTest.cs index 667dc4249..5b7875c7b 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandlerTest.cs @@ -5,12 +5,61 @@ using System.Globalization; using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Objects; namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; public partial class LyricRomajiTagsChangeHandlerTest : LyricPropertyChangeHandlerTest { + protected override bool IncludeAutoGenerator => true; + + #region Auto-Generate + + [Test] + public void TestAutoGenerateRomajiTags() + { + PrepareHitObject(() => new Lyric + { + Text = "風", + Language = new CultureInfo(17) + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + var romajiTags = h.RomajiTags; + Assert.AreEqual(1, romajiTags.Count); + Assert.AreEqual("kaze", romajiTags[0].Text); + }); + } + + [Test] + public void TestAutoGenerateRomajiTagsWithNonSupportedLyric() + { + PrepareHitObjects(() => new[] + { + new Lyric + { + Text = "風", + }, + new Lyric + { + Text = string.Empty, + }, + new Lyric + { + Text = string.Empty, + Language = new CultureInfo(17) + }, + }); + + TriggerHandlerChangedWithException(c => c.AutoGenerate()); + } + + #endregion + [Test] public void TestAdd() { diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandlerTest.cs index 9c48fd685..3802bb3d3 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandlerTest.cs @@ -5,12 +5,61 @@ using System.Globalization; using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Objects; namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; public partial class LyricRubyTagsChangeHandlerTest : LyricPropertyChangeHandlerTest { + protected override bool IncludeAutoGenerator => true; + + #region Auto-Generate + + [Test] + public void TestAutoGenerateRubyTags() + { + PrepareHitObject(() => new Lyric + { + Text = "風", + Language = new CultureInfo(17) + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + var rubyTags = h.RubyTags; + Assert.AreEqual(1, rubyTags.Count); + Assert.AreEqual("かぜ", rubyTags[0].Text); + }); + } + + [Test] + public void TestAutoGenerateRubyTagsWithNonSupportedLyric() + { + PrepareHitObjects(() => new[] + { + new Lyric + { + Text = "風", + }, + new Lyric + { + Text = string.Empty, + }, + new Lyric + { + Text = string.Empty, + Language = new CultureInfo(17) + }, + }); + + TriggerHandlerChangedWithException(c => c.AutoGenerate()); + } + + #endregion + [Test] public void TestAdd() { diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandlerTest.cs index 6f9e20c99..d7578ca47 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandlerTest.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; using osu.Game.Screens.Edit; @@ -15,6 +17,52 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; public partial class LyricTimeTagsChangeHandlerTest : LyricPropertyChangeHandlerTest { + protected override bool IncludeAutoGenerator => true; + + #region TimeTag + + [Test] + public void TestAutoGenerateTimeTags() + { + PrepareHitObject(() => new Lyric + { + Text = "カラオケ", + Language = new CultureInfo(17) + }); + + TriggerHandlerChanged(c => c.AutoGenerate()); + + AssertSelectedHitObject(h => + { + Assert.AreEqual(5, h.TimeTags.Count); + }); + } + + [Test] + public void TestAutoGenerateTimeTagsWithNonSupportedLyric() + { + PrepareHitObjects(() => new[] + { + new Lyric + { + Text = "カラオケ", + }, + new Lyric + { + Text = string.Empty, + }, + new Lyric + { + Text = string.Empty, + Language = new CultureInfo(17) + }, + }); + + TriggerHandlerChangedWithException(c => c.AutoGenerate()); + } + + #endregion + [Test] public void TestSetTimeTagTime() { From c8a539932b0c3c5fd3cbf564dfe24dc39e9f7d28 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 22:08:14 +0800 Subject: [PATCH 08/12] Change the test scope in this test case. Need to test the behavior that inherit the ILyricPropertyAutoGenerateChangeHandler instead. --- ...cPropertyAutoGenerateChangeHandlerTest.cs} | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) rename osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/{LyricAutoGenerateChangeHandlerTest.cs => LyricPropertyAutoGenerateChangeHandlerTest.cs} (57%) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricPropertyAutoGenerateChangeHandlerTest.cs similarity index 57% rename from osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs rename to osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricPropertyAutoGenerateChangeHandlerTest.cs index 9dc520c86..8f0321543 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricPropertyAutoGenerateChangeHandlerTest.cs @@ -10,21 +10,31 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.ChangeHandlers.Lyrics; -public partial class LyricAutoGenerateChangeHandlerTest : LyricPropertyChangeHandlerTest +/// +/// This test is focus on make sure that: +/// If the in the is not empty. +/// should be able to change the property. +/// +/// +[TestFixture(typeof(LyricReferenceChangeHandler))] +[TestFixture(typeof(LyricLanguageChangeHandler))] +[TestFixture(typeof(LyricRubyTagsChangeHandler))] +[TestFixture(typeof(LyricRomajiTagsChangeHandler))] +[TestFixture(typeof(LyricTimeTagsChangeHandler))] +[TestFixture(typeof(LyricNotesChangeHandler))] +public partial class LyricPropertyAutoGenerateChangeHandlerTest : LyricPropertyChangeHandlerTest + where TChangeHandler : LyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler, new() { protected override bool IncludeAutoGenerator => true; # region With reference lyric - [TestCase(LyricAutoGenerateProperty.DetectReferenceLyric, true)] - [TestCase(LyricAutoGenerateProperty.DetectLanguage, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateRubyTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateRomajiTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateTimeTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateNotes, false)] - public void TestCanGenerateWithReferenceLyric(LyricAutoGenerateProperty autoGenerateProperty, bool canGenerate) + [Test] + public void TestCanGenerateWithReferenceLyric() { - if (autoGenerateProperty == LyricAutoGenerateProperty.DetectReferenceLyric) + bool lyricReferenceChangeHandler = isLyricReferenceChangeHandler(); + + if (lyricReferenceChangeHandler) { PrepareHitObject(() => new Lyric { @@ -48,19 +58,16 @@ public void TestCanGenerateWithReferenceLyric(LyricAutoGenerateProperty autoGene TriggerHandlerChanged(c => { - Assert.AreEqual(canGenerate, c.CanGenerate(autoGenerateProperty)); + Assert.AreEqual(lyricReferenceChangeHandler, c.CanGenerate()); }); } - [TestCase(LyricAutoGenerateProperty.DetectReferenceLyric, true)] - [TestCase(LyricAutoGenerateProperty.DetectLanguage, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateRubyTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateRomajiTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateTimeTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateNotes, false)] - public void TestGeneratorNotSupportedLyricsWithReferenceLyric(LyricAutoGenerateProperty autoGenerateProperty, bool canGenerate) + [Test] + public void TestGeneratorNotSupportedLyricsWithReferenceLyric() { - if (autoGenerateProperty == LyricAutoGenerateProperty.DetectReferenceLyric) + bool lyricReferenceChangeHandler = isLyricReferenceChangeHandler(); + + if (lyricReferenceChangeHandler) { PrepareHitObject(() => new Lyric { @@ -84,20 +91,17 @@ public void TestGeneratorNotSupportedLyricsWithReferenceLyric(LyricAutoGenerateP TriggerHandlerChanged(c => { - bool hasNotSupportedLyrics = c.GetGeneratorNotSupportedLyrics(autoGenerateProperty).Any(); - Assert.AreEqual(canGenerate, !hasNotSupportedLyrics); + bool hasNotSupportedLyrics = c.GetGeneratorNotSupportedLyrics().Any(); + Assert.AreEqual(lyricReferenceChangeHandler, !hasNotSupportedLyrics); }); } - [TestCase(LyricAutoGenerateProperty.DetectReferenceLyric, true)] - [TestCase(LyricAutoGenerateProperty.DetectLanguage, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateRubyTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateRomajiTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateTimeTags, false)] - [TestCase(LyricAutoGenerateProperty.AutoGenerateNotes, false)] - public void TestAutoGenerate(LyricAutoGenerateProperty autoGenerateProperty, bool canGenerate) + [Test] + public void TestAutoGenerate() { - if (autoGenerateProperty == LyricAutoGenerateProperty.DetectReferenceLyric) + bool lyricReferenceChangeHandler = isLyricReferenceChangeHandler(); + + if (lyricReferenceChangeHandler) { PrepareHitObject(() => new Lyric { @@ -119,15 +123,18 @@ public void TestAutoGenerate(LyricAutoGenerateProperty autoGenerateProperty, boo } }); - if (canGenerate) + if (lyricReferenceChangeHandler) { - TriggerHandlerChanged(c => c.AutoGenerate(autoGenerateProperty)); + TriggerHandlerChanged(c => c.AutoGenerate()); } else { - TriggerHandlerChangedWithChangeForbiddenException(c => c.AutoGenerate(autoGenerateProperty)); + TriggerHandlerChangedWithChangeForbiddenException(c => c.AutoGenerate()); } } + private bool isLyricReferenceChangeHandler() + => typeof(TChangeHandler) == typeof(LyricReferenceChangeHandler); + #endregion } From 8866f74df91ab308080792350c24e77941b27810 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 22:13:01 +0800 Subject: [PATCH 09/12] Remove the injection for the old change handler. --- .../Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs | 4 ---- .../Lyrics/AssignLanguage/AssignLanguageStepScreen.cs | 8 ++------ .../GenerateRubyRomaji/GenerateRubyRomajiStepScreen.cs | 8 ++------ .../Lyrics/GenerateTimeTag/GenerateTimeTagStepScreen.cs | 4 ---- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs index 155dd24ae..efc1fa6b9 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs @@ -26,9 +26,6 @@ public partial class LyricEditorScreen : BeatmapEditorScreen [Cached(typeof(ILyricsChangeHandler))] private readonly LyricsChangeHandler lyricsChangeHandler; - [Cached(typeof(ILyricAutoGenerateChangeHandler))] - private readonly LyricAutoGenerateChangeHandler lyricAutoGenerateChangeHandler; - [Cached(typeof(ILyricTextChangeHandler))] private readonly LyricTextChangeHandler lyricTextChangeHandler; @@ -71,7 +68,6 @@ public LyricEditorScreen() : base(KaraokeBeatmapEditorScreenMode.Lyric) { AddInternal(lyricsChangeHandler = new LyricsChangeHandler()); - AddInternal(lyricAutoGenerateChangeHandler = new LyricAutoGenerateChangeHandler()); AddInternal(lyricTextChangeHandler = new LyricTextChangeHandler()); AddInternal(lyricReferenceChangeHandler = new LyricReferenceChangeHandler()); AddInternal(lyricLanguageChangeHandler = new LyricLanguageChangeHandler()); diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/AssignLanguage/AssignLanguageStepScreen.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/AssignLanguage/AssignLanguageStepScreen.cs index e9d2ba39f..f8cf5ca72 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/AssignLanguage/AssignLanguageStepScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/AssignLanguage/AssignLanguageStepScreen.cs @@ -21,9 +21,6 @@ public partial class AssignLanguageStepScreen : LyricImporterStepScreenWithLyric public override IconUsage Icon => FontAwesome.Solid.Globe; - [Cached(typeof(ILyricAutoGenerateChangeHandler))] - private readonly LyricAutoGenerateChangeHandler lyricAutoGenerateChangeHandler; - [Cached(typeof(ILyricLanguageChangeHandler))] private readonly LyricLanguageChangeHandler lyricLanguageChangeHandler; @@ -35,7 +32,6 @@ public partial class AssignLanguageStepScreen : LyricImporterStepScreenWithLyric public AssignLanguageStepScreen() { - AddInternal(lyricAutoGenerateChangeHandler = new LyricAutoGenerateChangeHandler()); AddInternal(lyricLanguageChangeHandler = new LyricLanguageChangeHandler()); AddInternal(lyricRubyTagsChangeHandler = new LyricRubyTagsChangeHandler()); AddInternal(lyricRomajiTagsChangeHandler = new LyricRomajiTagsChangeHandler()); @@ -59,8 +55,8 @@ protected override void LoadComplete() public override void Complete() { // Check is need to go to generate ruby/romaji step or just skip. - if (lyricAutoGenerateChangeHandler.CanGenerate(LyricAutoGenerateProperty.AutoGenerateRubyTags) - || lyricAutoGenerateChangeHandler.CanGenerate(LyricAutoGenerateProperty.AutoGenerateRomajiTags)) + if (lyricRubyTagsChangeHandler.CanGenerate() + || lyricRomajiTagsChangeHandler.CanGenerate()) { ScreenStack.Push(LyricImporterStep.GenerateRuby); } diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateRubyRomaji/GenerateRubyRomajiStepScreen.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateRubyRomaji/GenerateRubyRomajiStepScreen.cs index 88b17f697..a1f9e5647 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateRubyRomaji/GenerateRubyRomajiStepScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateRubyRomaji/GenerateRubyRomajiStepScreen.cs @@ -21,9 +21,6 @@ public partial class GenerateRubyRomajiStepScreen : LyricImporterStepScreenWithL public override IconUsage Icon => FontAwesome.Solid.Gem; - [Cached(typeof(ILyricAutoGenerateChangeHandler))] - private readonly LyricAutoGenerateChangeHandler lyricAutoGenerateChangeHandler; - [Cached(typeof(ILyricRubyTagsChangeHandler))] private readonly LyricRubyTagsChangeHandler lyricRubyTagsChangeHandler; @@ -32,7 +29,6 @@ public partial class GenerateRubyRomajiStepScreen : LyricImporterStepScreenWithL public GenerateRubyRomajiStepScreen() { - AddInternal(lyricAutoGenerateChangeHandler = new LyricAutoGenerateChangeHandler()); AddInternal(lyricRubyTagsChangeHandler = new LyricRubyTagsChangeHandler()); AddInternal(lyricRomajiTagsChangeHandler = new LyricRomajiTagsChangeHandler()); } @@ -51,9 +47,9 @@ protected override void LoadComplete() base.LoadComplete(); // Asking auto-generate ruby or romaji. - if (lyricAutoGenerateChangeHandler.CanGenerate(LyricAutoGenerateProperty.AutoGenerateRubyTags)) + if (lyricRubyTagsChangeHandler.CanGenerate()) AskForAutoGenerateRuby(); - else if (lyricAutoGenerateChangeHandler.CanGenerate(LyricAutoGenerateProperty.AutoGenerateRomajiTags)) + else if (lyricRomajiTagsChangeHandler.CanGenerate()) AskForAutoGenerateRomaji(); } diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateTimeTag/GenerateTimeTagStepScreen.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateTimeTag/GenerateTimeTagStepScreen.cs index acd3a7d96..39e81e48b 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateTimeTag/GenerateTimeTagStepScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Import/Lyrics/GenerateTimeTag/GenerateTimeTagStepScreen.cs @@ -24,15 +24,11 @@ public partial class GenerateTimeTagStepScreen : LyricImporterStepScreenWithLyri public override IconUsage Icon => FontAwesome.Solid.Tag; - [Cached(typeof(ILyricAutoGenerateChangeHandler))] - private readonly LyricAutoGenerateChangeHandler lyricAutoGenerateChangeHandler; - [Cached(typeof(ILyricTimeTagsChangeHandler))] private readonly LyricTimeTagsChangeHandler lyricTimeTagsChangeHandler; public GenerateTimeTagStepScreen() { - AddInternal(lyricAutoGenerateChangeHandler = new LyricAutoGenerateChangeHandler()); AddInternal(lyricTimeTagsChangeHandler = new LyricTimeTagsChangeHandler()); } From 2f771234d9f87a4db3c1cee97c4be28fc6633321 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 22:13:18 +0800 Subject: [PATCH 10/12] Add the new change handler. --- .../Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs index efc1fa6b9..f5b5399f4 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/LyricEditorScreen.cs @@ -26,6 +26,9 @@ public partial class LyricEditorScreen : BeatmapEditorScreen [Cached(typeof(ILyricsChangeHandler))] private readonly LyricsChangeHandler lyricsChangeHandler; + [Cached(typeof(ILyricNotesChangeHandler))] + private readonly LyricNotesChangeHandler lyricNotesChangeHandler; + [Cached(typeof(ILyricTextChangeHandler))] private readonly LyricTextChangeHandler lyricTextChangeHandler; @@ -68,6 +71,7 @@ public LyricEditorScreen() : base(KaraokeBeatmapEditorScreenMode.Lyric) { AddInternal(lyricsChangeHandler = new LyricsChangeHandler()); + AddInternal(lyricNotesChangeHandler = new LyricNotesChangeHandler()); AddInternal(lyricTextChangeHandler = new LyricTextChangeHandler()); AddInternal(lyricReferenceChangeHandler = new LyricReferenceChangeHandler()); AddInternal(lyricLanguageChangeHandler = new LyricLanguageChangeHandler()); From 81e20c078ddefc613a97d9469e973717465a9fc6 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 22:20:36 +0800 Subject: [PATCH 11/12] Throw the interface in the auto-generate button. --- .../LanguageAutoGenerateSubsection.cs | 7 +----- .../LyricEditorAutoGenerateSubsection.cs | 25 +++++-------------- .../Notes/NoteAutoGenerateSubsection.cs | 7 +----- .../ReferenceLyricAutoGenerateSection.cs | 7 +----- .../RomajiTagAutoGenerateSection.cs | 7 +----- .../RubyRomaji/RubyTagAutoGenerateSection.cs | 7 +----- .../RubyRomaji/TextTagAutoGenerateSection.cs | 8 ++---- .../TimeTags/TimeTagAutoGenerateSection.cs | 7 +----- 8 files changed, 14 insertions(+), 61 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/LanguageAutoGenerateSubsection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/LanguageAutoGenerateSubsection.cs index d1b8d2176..287a18e29 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/LanguageAutoGenerateSubsection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/LanguageAutoGenerateSubsection.cs @@ -12,15 +12,10 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings.Language { - public partial class LanguageAutoGenerateSubsection : LyricEditorAutoGenerateSubsection + public partial class LanguageAutoGenerateSubsection : LyricEditorAutoGenerateSubsection { private const string typing_mode = "TYPING_MODE"; - public LanguageAutoGenerateSubsection() - : base(LyricAutoGenerateProperty.DetectLanguage) - { - } - protected override DescriptionFormat CreateInvalidDescriptionFormat() => new() { diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricEditorAutoGenerateSubsection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricEditorAutoGenerateSubsection.cs index 679dde15a..5adc67118 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricEditorAutoGenerateSubsection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricEditorAutoGenerateSubsection.cs @@ -12,17 +12,11 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings { - public abstract partial class LyricEditorAutoGenerateSubsection : AutoGenerateSubsection + public abstract partial class LyricEditorAutoGenerateSubsection : AutoGenerateSubsection + where TChangeHandler : ILyricPropertyAutoGenerateChangeHandler { - private readonly LyricAutoGenerateProperty autoGenerateProperty; - - protected LyricEditorAutoGenerateSubsection(LyricAutoGenerateProperty autoGenerateProperty) - { - this.autoGenerateProperty = autoGenerateProperty; - } - protected override EditorSectionButton CreateGenerateButton() - => new AutoGenerateButton(autoGenerateProperty); + => new AutoGenerateButton(); protected sealed override DescriptionTextFlowContainer CreateDescriptionTextFlowContainer() => new LyricEditorDescriptionTextFlowContainer(); @@ -30,14 +24,7 @@ protected sealed override DescriptionTextFlowContainer CreateDescriptionTextFlow private partial class AutoGenerateButton : SelectLyricButton { [Resolved, AllowNull] - private ILyricAutoGenerateChangeHandler lyricAutoGenerateChangeHandler { get; set; } - - private readonly LyricAutoGenerateProperty autoGenerateProperty; - - public AutoGenerateButton(LyricAutoGenerateProperty autoGenerateProperty) - { - this.autoGenerateProperty = autoGenerateProperty; - } + private TChangeHandler changeHandler { get; set; } protected override LocalisableString StandardText => "Generate"; @@ -45,12 +32,12 @@ public AutoGenerateButton(LyricAutoGenerateProperty autoGenerateProperty) protected override IDictionary GetDisableSelectingLyrics() { - return lyricAutoGenerateChangeHandler.GetGeneratorNotSupportedLyrics(autoGenerateProperty); + return changeHandler.GetGeneratorNotSupportedLyrics(); } protected override void Apply() { - lyricAutoGenerateChangeHandler.AutoGenerate(autoGenerateProperty); + changeHandler.AutoGenerate(); } } } diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteAutoGenerateSubsection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteAutoGenerateSubsection.cs index a4b3a06ca..e821b5ac0 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteAutoGenerateSubsection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteAutoGenerateSubsection.cs @@ -20,15 +20,10 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings.Notes /// But need to make sure that lyric should not have any /// If found any issue, will navigate to target lyric. /// - public partial class NoteAutoGenerateSubsection : LyricEditorAutoGenerateSubsection + public partial class NoteAutoGenerateSubsection : LyricEditorAutoGenerateSubsection { private const string create_time_tag_mode = "CREATE_TIME_TAG_MODE"; - public NoteAutoGenerateSubsection() - : base(LyricAutoGenerateProperty.AutoGenerateNotes) - { - } - protected override DescriptionFormat CreateInvalidDescriptionFormat() => new() { diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Reference/ReferenceLyricAutoGenerateSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Reference/ReferenceLyricAutoGenerateSection.cs index 1d5ee2cec..925a6f7bc 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Reference/ReferenceLyricAutoGenerateSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Reference/ReferenceLyricAutoGenerateSection.cs @@ -13,13 +13,8 @@ public partial class ReferenceLyricAutoGenerateSection : AutoGenerateSection protected override AutoGenerateSubsection CreateAutoGenerateSubsection() => new ReferenceLyricAutoGenerateSubsection(); - private partial class ReferenceLyricAutoGenerateSubsection : LyricEditorAutoGenerateSubsection + private partial class ReferenceLyricAutoGenerateSubsection : LyricEditorAutoGenerateSubsection { - public ReferenceLyricAutoGenerateSubsection() - : base(LyricAutoGenerateProperty.DetectReferenceLyric) - { - } - protected override DescriptionFormat CreateInvalidDescriptionFormat() => new() { diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagAutoGenerateSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagAutoGenerateSection.cs index e2b2a78fb..03983e607 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagAutoGenerateSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagAutoGenerateSection.cs @@ -13,13 +13,8 @@ public partial class RomajiTagAutoGenerateSection : TextTagAutoGenerateSection protected override AutoGenerateSubsection CreateAutoGenerateSubsection() => new RomajiTagAutoGenerateSubsection(); - private partial class RomajiTagAutoGenerateSubsection : TextTagAutoGenerateSubsection + private partial class RomajiTagAutoGenerateSubsection : TextTagAutoGenerateSubsection { - public RomajiTagAutoGenerateSubsection() - : base(LyricAutoGenerateProperty.AutoGenerateRomajiTags) - { - } - protected override ConfigButton CreateConfigButton() => new RomajiTagAutoGenerateConfigButton(); diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagAutoGenerateSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagAutoGenerateSection.cs index a6d086991..726a059d3 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagAutoGenerateSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagAutoGenerateSection.cs @@ -13,13 +13,8 @@ public partial class RubyTagAutoGenerateSection : TextTagAutoGenerateSection protected override AutoGenerateSubsection CreateAutoGenerateSubsection() => new RubyTagAutoGenerateSubsection(); - private partial class RubyTagAutoGenerateSubsection : TextTagAutoGenerateSubsection + private partial class RubyTagAutoGenerateSubsection : TextTagAutoGenerateSubsection { - public RubyTagAutoGenerateSubsection() - : base(LyricAutoGenerateProperty.AutoGenerateRubyTags) - { - } - protected override ConfigButton CreateConfigButton() => new RubyTagAutoGenerateConfigButton(); diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagAutoGenerateSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagAutoGenerateSection.cs index c5c0c704d..0e16053c1 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagAutoGenerateSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagAutoGenerateSection.cs @@ -10,15 +10,11 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings.RubyRo { public abstract partial class TextTagAutoGenerateSection : AutoGenerateSection { - protected abstract partial class TextTagAutoGenerateSubsection : LyricEditorAutoGenerateSubsection + protected abstract partial class TextTagAutoGenerateSubsection : LyricEditorAutoGenerateSubsection + where TChangeHandler : ILyricPropertyAutoGenerateChangeHandler { private const string language_mode = "LANGUAGE_MODE"; - protected TextTagAutoGenerateSubsection(LyricAutoGenerateProperty autoGenerateProperty) - : base(autoGenerateProperty) - { - } - protected override DescriptionFormat CreateInvalidDescriptionFormat() => new() { diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/TimeTags/TimeTagAutoGenerateSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/TimeTags/TimeTagAutoGenerateSection.cs index f891672d0..4f175fd06 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/TimeTags/TimeTagAutoGenerateSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/TimeTags/TimeTagAutoGenerateSection.cs @@ -15,15 +15,10 @@ public partial class TimeTagAutoGenerateSection : AutoGenerateSection protected override AutoGenerateSubsection CreateAutoGenerateSubsection() => new TimeTageAutoGenerateSubsection(); - private partial class TimeTageAutoGenerateSubsection : LyricEditorAutoGenerateSubsection + private partial class TimeTageAutoGenerateSubsection : LyricEditorAutoGenerateSubsection { private const string language_mode = "LANGUAGE_MODE"; - public TimeTageAutoGenerateSubsection() - : base(LyricAutoGenerateProperty.AutoGenerateTimeTags) - { - } - protected override DescriptionFormat CreateInvalidDescriptionFormat() => new() { From d11bae223fd239ed78020782ef1f88d35c9077ff Mon Sep 17 00:00:00 2001 From: andy840119 Date: Mon, 24 Apr 2023 22:14:12 +0800 Subject: [PATCH 12/12] It's time to remove the old change handler for auto-generate things. --- .../Lyrics/ILyricAutoGenerateChangeHandler.cs | 29 -- .../Lyrics/LyricAutoGenerateChangeHandler.cs | 257 ------------------ 2 files changed, 286 deletions(-) delete mode 100644 osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricAutoGenerateChangeHandler.cs delete mode 100644 osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricAutoGenerateChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricAutoGenerateChangeHandler.cs deleted file mode 100644 index 0f2c813bc..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricAutoGenerateChangeHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Localisation; -using osu.Game.Rulesets.Karaoke.Objects; - -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics -{ - public interface ILyricAutoGenerateChangeHandler : IAutoGenerateChangeHandler, ILyricPropertyChangeHandler - { - IDictionary GetGeneratorNotSupportedLyrics(LyricAutoGenerateProperty autoGenerateProperty); - } - - public enum LyricAutoGenerateProperty - { - DetectReferenceLyric, - - DetectLanguage, - - AutoGenerateRubyTags, - - AutoGenerateRomajiTags, - - AutoGenerateTimeTags, - - AutoGenerateNotes, - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs deleted file mode 100644 index f1a549081..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Localisation; -using osu.Game.Rulesets.Karaoke.Configuration; -using osu.Game.Rulesets.Karaoke.Edit.Generator; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags; -using osu.Game.Rulesets.Karaoke.Edit.Utils; -using osu.Game.Rulesets.Karaoke.Objects; -using osu.Game.Rulesets.Karaoke.Objects.Properties; -using osu.Game.Screens.Edit; - -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics -{ - public partial class LyricAutoGenerateChangeHandler : LyricPropertyChangeHandler, ILyricAutoGenerateChangeHandler - { - [Resolved, AllowNull] - private KaraokeRulesetEditGeneratorConfigManager generatorConfigManager { get; set; } - - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } - - // should change this flag if wants to change property in the lyrics. - // Not a good to waite a global property for that but there's no better choice. - private LyricAutoGenerateProperty? currentAutoGenerateProperty; - - public bool CanGenerate(LyricAutoGenerateProperty autoGenerateProperty) - { - currentAutoGenerateProperty = autoGenerateProperty; - - switch (autoGenerateProperty) - { - case LyricAutoGenerateProperty.DetectReferenceLyric: - var referenceLyricDetector = createLyricDetector(); - return canDetect(referenceLyricDetector); - - case LyricAutoGenerateProperty.DetectLanguage: - var languageDetector = createLyricDetector(); - return canDetect(languageDetector); - - case LyricAutoGenerateProperty.AutoGenerateRubyTags: - var rubyGenerator = createLyricGenerator(); - return canGenerate(rubyGenerator); - - case LyricAutoGenerateProperty.AutoGenerateRomajiTags: - var romajiGenerator = createLyricGenerator(); - return canGenerate(romajiGenerator); - - case LyricAutoGenerateProperty.AutoGenerateTimeTags: - var timeTagGenerator = createLyricGenerator(); - return canGenerate(timeTagGenerator); - - case LyricAutoGenerateProperty.AutoGenerateNotes: - var noteGenerator = createLyricGenerator(); - return canGenerate(noteGenerator); - - default: - throw new ArgumentOutOfRangeException(nameof(autoGenerateProperty)); - } - - bool canDetect(PropertyDetector detector) - => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(detector.CanDetect); - - bool canGenerate(PropertyGenerator generator) - => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(generator.CanGenerate); - } - - public IDictionary GetGeneratorNotSupportedLyrics(LyricAutoGenerateProperty autoGenerateProperty) - { - currentAutoGenerateProperty = autoGenerateProperty; - - switch (autoGenerateProperty) - { - case LyricAutoGenerateProperty.DetectReferenceLyric: - var referenceLyricDetector = createLyricDetector(); - return getInvalidMessageFromDetector(referenceLyricDetector); - - case LyricAutoGenerateProperty.DetectLanguage: - var languageDetector = createLyricDetector(); - return getInvalidMessageFromDetector(languageDetector); - - case LyricAutoGenerateProperty.AutoGenerateRubyTags: - var rubyGenerator = createLyricGenerator(); - return getInvalidMessageFromGenerator(rubyGenerator); - - case LyricAutoGenerateProperty.AutoGenerateRomajiTags: - var romajiGenerator = createLyricGenerator(); - return getInvalidMessageFromGenerator(romajiGenerator); - - case LyricAutoGenerateProperty.AutoGenerateTimeTags: - var timeTagGenerator = createLyricGenerator(); - return getInvalidMessageFromGenerator(timeTagGenerator); - - case LyricAutoGenerateProperty.AutoGenerateNotes: - var noteGenerator = createLyricGenerator(); - return getInvalidMessageFromGenerator(noteGenerator); - - default: - throw new ArgumentOutOfRangeException(nameof(autoGenerateProperty)); - } - - IDictionary getInvalidMessageFromDetector(PropertyDetector detector) - => HitObjects.Select(x => new KeyValuePair(x, detector.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) - .Where(x => x.Value != null) - .ToDictionary(k => k.Key, v => v.Value!.Value); - - IDictionary getInvalidMessageFromGenerator(PropertyGenerator generator) - => HitObjects.Select(x => new KeyValuePair(x, generator.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) - .Where(x => x.Value != null) - .ToDictionary(k => k.Key, v => v.Value!.Value); - - LocalisableString? getReferenceLyricInvalidMessage(Lyric lyric) - { - bool locked = IsWritePropertyLocked(lyric); - return locked ? "Cannot modify property because has reference lyric." : default(LocalisableString?); - } - } - - public void AutoGenerate(LyricAutoGenerateProperty autoGenerateProperty) - { - currentAutoGenerateProperty = autoGenerateProperty; - - switch (autoGenerateProperty) - { - case LyricAutoGenerateProperty.DetectReferenceLyric: - var referenceLyricDetector = createLyricDetector(); - PerformOnSelection(lyric => - { - var referencedLyric = referenceLyricDetector.Detect(lyric); - lyric.ReferenceLyricId = referencedLyric.ID; - - // technically this property should be assigned by beatmap processor, but should be OK to assign here for testing purpose. - lyric.ReferenceLyric = referencedLyric; - - if (lyric.ReferenceLyricId != null && lyric.ReferenceLyricConfig is not SyncLyricConfig) - lyric.ReferenceLyricConfig = new SyncLyricConfig(); - }); - break; - - case LyricAutoGenerateProperty.DetectLanguage: - var languageDetector = createLyricDetector(); - PerformOnSelection(lyric => - { - var detectedLanguage = languageDetector.Detect(lyric); - lyric.Language = detectedLanguage; - }); - break; - - case LyricAutoGenerateProperty.AutoGenerateRubyTags: - var rubyGenerator = createLyricGenerator(); - PerformOnSelection(lyric => - { - lyric.RubyTags = rubyGenerator.Generate(lyric); - }); - break; - - case LyricAutoGenerateProperty.AutoGenerateRomajiTags: - var romajiGenerator = createLyricGenerator(); - PerformOnSelection(lyric => - { - lyric.RomajiTags = romajiGenerator.Generate(lyric); - }); - break; - - case LyricAutoGenerateProperty.AutoGenerateTimeTags: - var timeTagGenerator = createLyricGenerator(); - PerformOnSelection(lyric => - { - lyric.TimeTags = timeTagGenerator.Generate(lyric); - }); - break; - - case LyricAutoGenerateProperty.AutoGenerateNotes: - var noteGenerator = createLyricGenerator(); - PerformOnSelection(lyric => - { - // clear exist notes if from those - var matchedNotes = EditorBeatmapUtils.GetNotesByLyric(beatmap, lyric); - RemoveRange(matchedNotes); - - var notes = noteGenerator.Generate(lyric); - AddRange(notes); - }); - break; - - default: - throw new ArgumentOutOfRangeException(nameof(autoGenerateProperty)); - } - } - - private PropertyDetector createLyricDetector() - { - switch (typeof(T)) - { - case Type t when t == typeof(Lyric): - var lyrics = beatmap.HitObjects.OfType().ToArray(); - var referenceLyricDetectorConfig = generatorConfigManager.Get(); - return (PropertyDetector)(object)new ReferenceLyricDetector(lyrics, referenceLyricDetectorConfig); - - case Type t when t == typeof(CultureInfo): - var languageDetectorConfig = generatorConfigManager.Get(); - return (PropertyDetector)(object)new LanguageDetector(languageDetectorConfig); - - default: - throw new NotSupportedException(); - } - } - - private PropertyGenerator createLyricGenerator() - { - switch (typeof(TProperty)) - { - case Type t when t == typeof(RubyTag[]): - return (PropertyGenerator)(object)new RubyTagGeneratorSelector(generatorConfigManager); - - case Type t when t == typeof(RomajiTag[]): - return (PropertyGenerator)(object)new RomajiTagGeneratorSelector(generatorConfigManager); - - case Type t when t == typeof(TimeTag[]): - return (PropertyGenerator)(object)new TimeTagGeneratorSelector(generatorConfigManager); - - case Type t when t == typeof(Note[]): - var config = generatorConfigManager.Get(); - return (PropertyGenerator)(object)new NoteGenerator(config); - - default: - throw new NotSupportedException(); - } - } - - public override bool IsSelectionsLocked() - => throw new InvalidOperationException("Auto-generator does not support this check method."); - - protected override bool IsWritePropertyLocked(Lyric lyric) => - currentAutoGenerateProperty switch - { - LyricAutoGenerateProperty.DetectReferenceLyric => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.ReferenceLyric), nameof(Lyric.ReferenceLyricConfig)), - LyricAutoGenerateProperty.DetectLanguage => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Language)), - LyricAutoGenerateProperty.AutoGenerateRubyTags => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.RubyTags)), - LyricAutoGenerateProperty.AutoGenerateRomajiTags => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.RomajiTags)), - LyricAutoGenerateProperty.AutoGenerateTimeTags => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.TimeTags)), - LyricAutoGenerateProperty.AutoGenerateNotes => HitObjectWritableUtils.IsCreateOrRemoveNoteLocked(lyric), - _ => throw new ArgumentOutOfRangeException() - }; - } -}