From 66af56b839f1adfc0515ca3ec02cb401b0831b0c Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sat, 14 Sep 2024 12:44:03 +0800 Subject: [PATCH 1/4] Move the language selector popover into more generic location. --- .../UserInterfaceV2/LanguageSelectorPopover.cs | 3 +-- .../Beatmaps/Lyrics/Content/Components/Badges/LanguageBadge.cs | 2 +- .../Lyrics/Settings/Language/AssignLanguageSubsection.cs | 2 +- .../Translations/Components/CreateNewTranslationButton.cs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) rename osu.Game.Rulesets.Karaoke/{Screens/Edit/Beatmaps/Components => Graphics}/UserInterfaceV2/LanguageSelectorPopover.cs (86%) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Components/UserInterfaceV2/LanguageSelectorPopover.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelectorPopover.cs similarity index 86% rename from osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Components/UserInterfaceV2/LanguageSelectorPopover.cs rename to osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelectorPopover.cs index 11b414988..d2b315762 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Components/UserInterfaceV2/LanguageSelectorPopover.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelectorPopover.cs @@ -4,9 +4,8 @@ using System.Globalization; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; -namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Components.UserInterfaceV2; +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; public partial class LanguageSelectorPopover : OsuPopover { diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Badges/LanguageBadge.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Badges/LanguageBadge.cs index 71bc7c5d4..6ba269e1b 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Badges/LanguageBadge.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Badges/LanguageBadge.cs @@ -10,8 +10,8 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Objects; -using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Components.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States; using osu.Game.Rulesets.Karaoke.Utils; diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/AssignLanguageSubsection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/AssignLanguageSubsection.cs index acb06255a..95514ed0d 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/AssignLanguageSubsection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Language/AssignLanguageSubsection.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; -using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Components.UserInterfaceV2; +using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Utils; namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings.Language; diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Translations/Components/CreateNewTranslationButton.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Translations/Components/CreateNewTranslationButton.cs index fa66e57c9..2e3d39f43 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Translations/Components/CreateNewTranslationButton.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Translations/Components/CreateNewTranslationButton.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; -using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Components.UserInterfaceV2; +using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Translations.Components; From e23b7bdb3cfcd9539a3c08052b4fea4fa6a2c979 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sat, 14 Sep 2024 12:47:13 +0800 Subject: [PATCH 2/4] Remove duplicated popover. --- .../Screens/Settings/SettingsLanguage.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Settings/SettingsLanguage.cs b/osu.Game.Rulesets.Karaoke/Screens/Settings/SettingsLanguage.cs index 20cd80701..f56e196b1 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Settings/SettingsLanguage.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Settings/SettingsLanguage.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Utils; @@ -42,17 +41,4 @@ public LanguageSelectionButton() public Popover GetPopover() => new LanguageSelectorPopover(Current); } - - private partial class LanguageSelectorPopover : OsuPopover - { - public LanguageSelectorPopover(Bindable bindableCultureInfo) - { - Child = new LanguageSelector - { - Width = 260, - Height = 400, - Current = bindableCultureInfo, - }; - } - } } From 432e132abbce8b830f5773bb6e0eddd8ade406e9 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sat, 14 Sep 2024 11:48:13 +0800 Subject: [PATCH 3/4] Implement the component for the language list. --- .../Setup/Components/LabelledLanguageList.cs | 20 ++ .../Edit/Setup/Components/LanguageList.cs | 190 ++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledLanguageList.cs create mode 100644 osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LanguageList.cs diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledLanguageList.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledLanguageList.cs new file mode 100644 index 000000000..db99efe22 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledLanguageList.cs @@ -0,0 +1,20 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Globalization; +using osu.Framework.Bindables; +using osu.Game.Graphics.UserInterfaceV2; + +namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components; + +public partial class LabelledLanguageList : LabelledDrawable +{ + public LabelledLanguageList() + : base(true) + { + } + + public BindableList Languages => Component.Languages; + + protected override LanguageList CreateComponent() => new(); +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LanguageList.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LanguageList.cs new file mode 100644 index 000000000..606565f16 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LanguageList.cs @@ -0,0 +1,190 @@ +// 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.Specialized; +using System.Globalization; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; +using osu.Game.Rulesets.Karaoke.Utils; +using osuTK; + +namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components; + +/// +/// A component which displays a collection of +/// +public partial class LanguageList : CompositeDrawable +{ + public BindableList Languages { get; } = new(); + + private FillFlowContainer languages = null!; + + private const int fade_duration = 200; + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + AutoSizeDuration = fade_duration; + AutoSizeEasing = Easing.OutQuint; + + InternalChild = languages = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(8), + Direction = FillDirection.Full, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Languages.BindCollectionChanged((_, args) => + { + if (args.Action != NotifyCollectionChangedAction.Replace) + updateSingers(); + }, true); + FinishTransforms(true); + } + + private void updateSingers() + { + languages.Clear(); + + foreach (CultureInfo language in Languages) + { + languages.Add(new LanguageDisplay + { + Current = { Value = language }, + DeleteRequested = languageDeletionRequested, + }); + } + + languages.Add(new AddLanguageButton + { + Action = languageInsertionRequested, + }); + } + + private void languageInsertionRequested(CultureInfo language) + { + if (!Languages.Contains(language)) + Languages.Add(language); + } + + private void languageDeletionRequested(CultureInfo language) => Languages.Remove(language); + + private partial class LanguageDisplay : CompositeDrawable, IHasCurrentValue + { + /// + /// Invoked when the user has requested the corresponding to this + /// + public Action? DeleteRequested; + + private readonly BindableWithCurrent current = new(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + + private readonly Box background; + private readonly OsuSpriteText languageName; + + public LanguageDisplay() + { + AutoSizeAxes = Axes.X; + Height = 30; + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + languageName = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Padding = new MarginPadding { Left = 10, Right = 32 }, + }, + new IconButton + { + Icon = FontAwesome.Solid.Times, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(16), + Margin = new MarginPadding { Right = 10 }, + Action = () => + { + DeleteRequested?.Invoke(Current.Value); + }, + }, + }; + + current.BindValueChanged(x => + { + languageName.Text = CultureInfoUtils.GetLanguageDisplayText(x.NewValue); + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.BlueDarker; + languageName.Colour = colours.BlueLighter; + } + } + + internal partial class AddLanguageButton : CompositeDrawable, IHasPopover + { + public Action? Action; + + private readonly Bindable currentLanguage = new(); + + public AddLanguageButton() + { + InternalChild = new IconButton + { + Action = this.ShowPopover, + Icon = FontAwesome.Solid.Plus, + }; + + currentLanguage.BindValueChanged(e => + { + this.HidePopover(); + + var language = e.NewValue; + if (language == null) + return; + + Action?.Invoke(language); + + currentLanguage.Value = null; + }); + } + + public Popover GetPopover() => new LanguageSelectorPopover(currentLanguage) + { + EnableEmptyOption = false, + }; + } +} From ea468b24996944469d013f62767a9474f2e9d2c0 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Fri, 13 Sep 2024 22:54:45 +0800 Subject: [PATCH 4/4] Implement the translation section. --- .../Edit/Setup/KaraokeTranslationSection.cs | 64 +++++++++++++++++++ osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs | 1 + 2 files changed, 65 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeTranslationSection.cs diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeTranslationSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeTranslationSection.cs new file mode 100644 index 000000000..e43518f46 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeTranslationSection.cs @@ -0,0 +1,64 @@ +// 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.Specialized; +using System.Globalization; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; +using osu.Game.Rulesets.Karaoke.Edit.Setup.Components; +using osu.Game.Screens.Edit.Setup; + +namespace osu.Game.Rulesets.Karaoke.Edit.Setup; + +public partial class KaraokeTranslationSection : SetupSection +{ + public override LocalisableString Title => "Translation"; + + [Cached(typeof(IBeatmapTranslationsChangeHandler))] + private readonly BeatmapTranslationsChangeHandler changeHandler = new(); + + private LabelledLanguageList singerList = null!; + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(changeHandler); + + Children = new Drawable[] + { + singerList = new LabelledLanguageList + { + Label = "Translation list", + Description = "All the lyric translation in beatmap.", + FixedLabelWidth = LABEL_WIDTH, + }, + }; + + singerList.Languages.AddRange(changeHandler.Languages); + singerList.Languages.BindCollectionChanged((_, args) => + { + switch (args.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (var language in args.NewItems?.Cast() ?? Array.Empty()) + { + changeHandler.Add(language); + } + + break; + + case NotifyCollectionChangedAction.Remove: + foreach (var language in args.OldItems?.Cast() ?? Array.Empty()) + { + changeHandler.Remove(language); + } + + break; + } + }); + } +} diff --git a/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs b/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs index e2805d34c..d0c431517 100644 --- a/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs +++ b/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs @@ -287,6 +287,7 @@ public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatm public override IEnumerable CreateEditorSetupSections() => new SetupSection[] { new KaraokeSingerSection(), + new KaraokeTranslationSection(), new KaraokeNoteSection(), };