diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index b72df0a30..760c41f14 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -9,7 +9,6 @@ M:osu.Framework.Bindables.IBindableList`1.GetBoundCopy();Fails on iOS. Use manua T:Microsoft.EntityFrameworkCore.Internal.EnumerableExtensions;Don't use internal extension methods. T:Microsoft.EntityFrameworkCore.Internal.TypeExtensions;Don't use internal extension methods. T:NuGet.Packaging.CollectionExtensions;Don't use internal extension methods. -M:System.Enum.HasFlag(System.Enum);Use osu.Framework.Extensions.EnumExtensions.HasFlagFast() instead. M:Realms.IRealmCollection`1.SubscribeForNotifications`1(Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IRealmCollection,NotificationCallbackDelegate) instead. M:System.Guid.#ctor;Probably meaning to use Guid.NewGuid() instead. If actually wanting empty, use Guid.Empty. M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Linq.IQueryable{``0},Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IQueryable,NotificationCallbackDelegate) instead. diff --git a/osu.Game.Rulesets.Karaoke.Tests/Graphics/Sprites/Processor/DisplayProcessorTestScene.cs b/osu.Game.Rulesets.Karaoke.Tests/Graphics/Sprites/Processor/DisplayProcessorTestScene.cs index 0e9c32558..22e9ea9d4 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Graphics/Sprites/Processor/DisplayProcessorTestScene.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Graphics/Sprites/Processor/DisplayProcessorTestScene.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -92,7 +91,7 @@ public void TestDisplayProperty([Values] LyricDisplayProperty property) } }); - if (property.HasFlagFast(LyricDisplayProperty.TopText)) + if (property.HasFlag(LyricDisplayProperty.TopText)) { AssertTopTextChanged(); } @@ -103,7 +102,7 @@ public void TestDisplayProperty([Values] LyricDisplayProperty property) AssertCenterTextChanged(); - if (property.HasFlagFast(LyricDisplayProperty.BottomText)) + if (property.HasFlag(LyricDisplayProperty.BottomText)) { AssertBottomTextChanged(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs index 96e7d661a..74662970c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -111,10 +110,10 @@ private void updateLayout() float verticalMargin = Layout.VerticalMargin * scale + padding; previewLyric.Margin = new MarginPadding { - Left = Layout.Alignment.HasFlagFast(Anchor.x0) ? horizontalMargin : 0, - Right = Layout.Alignment.HasFlagFast(Anchor.x2) ? horizontalMargin : 0, - Top = Layout.Alignment.HasFlagFast(Anchor.y0) ? verticalMargin : 0, - Bottom = Layout.Alignment.HasFlagFast(Anchor.y2) ? verticalMargin : 0, + Left = Layout.Alignment.HasFlag(Anchor.x0) ? horizontalMargin : 0, + Right = Layout.Alignment.HasFlag(Anchor.x2) ? horizontalMargin : 0, + Top = Layout.Alignment.HasFlag(Anchor.y0) ? verticalMargin : 0, + Bottom = Layout.Alignment.HasFlag(Anchor.y2) ? verticalMargin : 0, }; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeNoteSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeNoteSection.cs new file mode 100644 index 000000000..d3e65f593 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeNoteSection.cs @@ -0,0 +1,43 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Rulesets.Karaoke.Beatmaps; +using osu.Game.Screens.Edit.Setup; + +namespace osu.Game.Rulesets.Karaoke.Edit.Setup; + +public partial class KaraokeNoteSection : SetupSection +{ + public override LocalisableString Title => "Note"; + + private LabelledSwitchButton scorable = null!; + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + scorable = new LabelledSwitchButton + { + Label = "Scorable", + Description = "Will not show score playfield if the option is unchecked.", + Current = { Value = true }, + }, + }; + + scorable.Current.BindValueChanged(_ => updateValues()); + } + + private void updateValues() + { + if (Beatmap.PlayableBeatmap is not KaraokeBeatmap karaokeBeatmap) + throw new InvalidOperationException(); + + karaokeBeatmap.Scorable = scorable.Current.Value; + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs deleted file mode 100644 index 8a210e066..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Rulesets.Karaoke.Beatmaps; -using osu.Game.Rulesets.Karaoke.Edit.Setup.Components; -using osu.Game.Rulesets.Karaoke.Edit.Utils; -using osu.Game.Screens.Edit.Setup; - -namespace osu.Game.Rulesets.Karaoke.Edit.Setup; - -public partial class KaraokeSetupSection : RulesetSetupSection -{ - private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(Beatmap); - - private LabelledSwitchButton scorable = null!; - private LabelledSingerList singerList = null!; - - public KaraokeSetupSection() - : base(new KaraokeRuleset().RulesetInfo) - { - } - - [BackgroundDependencyLoader] - private void load() - { - Children = new Drawable[] - { - scorable = new LabelledSwitchButton - { - Label = "Scorable", - Description = "Will not show score playfield if the option is unchecked.", - Current = { Value = true }, - }, - singerList = new LabelledSingerList - { - Label = "Singer list", - Description = "All the singers in beatmap.", - FixedLabelWidth = LABEL_WIDTH, - SingerNamePrefix = "#", - }, - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - scorable.Current.BindValueChanged(_ => updateBeatmap()); - } - - private void updateBeatmap() - { - // todo: update the value. - // karaokeBeatmap.Scorable = scorable.Current.Value; - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSingerSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSingerSection.cs new file mode 100644 index 000000000..1d8008940 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSingerSection.cs @@ -0,0 +1,32 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Karaoke.Edit.Setup.Components; +using osu.Game.Screens.Edit.Setup; + +namespace osu.Game.Rulesets.Karaoke.Edit.Setup; + +public partial class KaraokeSingerSection : SetupSection +{ + public override LocalisableString Title => "Singers"; + + private LabelledSingerList singerList = null!; + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + singerList = new LabelledSingerList + { + Label = "Singer list", + Description = "All the singers in beatmap.", + FixedLabelWidth = LABEL_WIDTH, + SingerNamePrefix = "#", + }, + }; + } +} diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DisplayLyricProcessor.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DisplayLyricProcessor.cs index c779f0433..a4402b9aa 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DisplayLyricProcessor.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DisplayLyricProcessor.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Graphics.Sprites.Processor; using osu.Game.Rulesets.Karaoke.Objects; @@ -90,13 +89,13 @@ public void UpdateAll() processor.UpdateAll(); // should trigger top text update even not display. - if (!displayProperty.HasFlagFast(LyricDisplayProperty.TopText)) + if (!displayProperty.HasFlag(LyricDisplayProperty.TopText)) { TopTextChanged?.Invoke(Array.Empty()); } // should trigger bottom text update even not display. - if (!displayProperty.HasFlagFast(LyricDisplayProperty.BottomText)) + if (!displayProperty.HasFlag(LyricDisplayProperty.BottomText)) { BottomTextChanged?.Invoke(Array.Empty()); } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/Processor/BaseDisplayProcessor.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/Processor/BaseDisplayProcessor.cs index 264f219db..bf7559d09 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/Processor/BaseDisplayProcessor.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/Processor/BaseDisplayProcessor.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Objects; @@ -44,7 +43,7 @@ public void UpdateAll() protected void UpdateTopText() { - if (!displayProperty.HasFlagFast(LyricDisplayProperty.TopText)) + if (!displayProperty.HasFlag(LyricDisplayProperty.TopText)) return; TopTextChanged?.Invoke(CalculateTopTexts(lyric).ToArray()); @@ -57,7 +56,7 @@ protected void UpdateCenterText() protected void UpdateBottomText() { - if (!displayProperty.HasFlagFast(LyricDisplayProperty.BottomText)) + if (!displayProperty.HasFlag(LyricDisplayProperty.BottomText)) return; BottomTextChanged?.Invoke(CalculateBottomTexts(lyric).ToArray()); diff --git a/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs b/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs index 7c1df53cd..424c6843c 100644 --- a/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs +++ b/osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs @@ -280,7 +280,11 @@ public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatm return statistic.ToArray(); } - public override RulesetSetupSection CreateEditorSetupSection() => new KaraokeSetupSection(); + public override IEnumerable CreateEditorSetupSections() => new SetupSection[] + { + new KaraokeSingerSection(), + new KaraokeNoteSection(), + }; public KaraokeRuleset() { diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Compose/LyricComposer.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Compose/LyricComposer.cs index 3dd94847d..f019ac584 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Compose/LyricComposer.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Compose/LyricComposer.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -163,7 +162,7 @@ private void load(KaraokeRulesetLyricEditorConfigManager lyricEditorConfigManage protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) { - if (invalidation.HasFlagFast(Invalidation.DrawSize) && source == InvalidationSource.Parent) + if (invalidation.HasFlag(Invalidation.DrawSize) && source == InvalidationSource.Parent) calculatePanelPosition(); return base.OnInvalidate(invalidation, source); diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/EditorTable.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/EditorTable.cs new file mode 100644 index 000000000..28643e787 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/EditorTable.cs @@ -0,0 +1,188 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Diagnostics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Karaoke.Screens.Edit; + +public abstract partial class EditorTable : TableContainer +{ + public event Action? OnRowSelected; + + private const float horizontal_inset = 20; + + protected const float ROW_HEIGHT = 25; + + public const int TEXT_SIZE = 14; + + protected readonly FillFlowContainer BackgroundFlow; + + // We can avoid potentially thousands of objects being added to the input sub-tree since item selection is being handled by the BackgroundFlow + // and no items in the underlying table are clickable. + protected override bool ShouldBeConsideredForInput(Drawable child) => child == BackgroundFlow && base.ShouldBeConsideredForInput(child); + + protected EditorTable() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding { Horizontal = horizontal_inset }; + RowSize = new Dimension(GridSizeMode.Absolute, ROW_HEIGHT); + + AddInternal(BackgroundFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Depth = 1f, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = ROW_HEIGHT } + }); + } + + protected int GetIndexForObject(object? item) + { + for (int i = 0; i < BackgroundFlow.Count; i++) + { + if (BackgroundFlow[i].Item == item) + return i; + } + + return -1; + } + + protected virtual bool SetSelectedRow(object? item) + { + bool foundSelection = false; + + foreach (var b in BackgroundFlow) + { + b.Selected = ReferenceEquals(b.Item, item); + + if (b.Selected) + { + Debug.Assert(!foundSelection); + OnRowSelected?.Invoke(b); + foundSelection = true; + } + } + + return foundSelection; + } + + protected object? GetObjectAtIndex(int index) + { + if (index < 0 || index > BackgroundFlow.Count - 1) + return null; + + return BackgroundFlow[index].Item; + } + + protected override Drawable CreateHeader(int index, TableColumn? column) => new HeaderText(column?.Header ?? default); + + private partial class HeaderText : OsuSpriteText + { + public HeaderText(LocalisableString text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold); + } + } + + public partial class RowBackground : OsuClickableContainer + { + public readonly object Item; + + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + + public RowBackground(object item) + { + Item = item; + + RelativeSizeAxes = Axes.X; + Height = 25; + + AlwaysPresent = true; + + CornerRadius = 3; + Masking = true; + + Children = new Drawable[] + { + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + } + + private Color4 colourHover; + private Color4 colourSelected; + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colours) + { + colourHover = colours.Background1; + colourSelected = colours.Colour3; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateState(); + FinishTransforms(true); + } + + private bool selected; + + public bool Selected + { + get => selected; + set + { + if (value == selected) + return; + + selected = value; + updateState(); + } + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + base.OnHoverLost(e); + } + + private void updateState() + { + hoveredBackground.FadeColour(selected ? colourSelected : colourHover, 450, Easing.OutQuint); + + if (selected || IsHovered) + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + else + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs index 5eda81662..4ee4919d4 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Edit.Checks.Components; -using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Karaoke.Screens.Edit; diff --git a/osu.Game.Rulesets.Karaoke/Skinning/Elements/LyricLayout.cs b/osu.Game.Rulesets.Karaoke/Skinning/Elements/LyricLayout.cs index 2061a0d2d..99bdc4b75 100644 --- a/osu.Game.Rulesets.Karaoke/Skinning/Elements/LyricLayout.cs +++ b/osu.Game.Rulesets.Karaoke/Skinning/Elements/LyricLayout.cs @@ -1,7 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Karaoke.Objects.Drawables; @@ -43,10 +42,10 @@ public void ApplyTo(Drawable d) drawableLyric.Origin = Alignment; drawableLyric.Margin = new MarginPadding { - Left = Alignment.HasFlagFast(Anchor.x0) ? HorizontalMargin : 0, - Right = Alignment.HasFlagFast(Anchor.x2) ? HorizontalMargin : 0, - Top = Alignment.HasFlagFast(Anchor.y0) ? VerticalMargin : 0, - Bottom = Alignment.HasFlagFast(Anchor.y2) ? VerticalMargin : 0, + Left = Alignment.HasFlag(Anchor.x0) ? HorizontalMargin : 0, + Right = Alignment.HasFlag(Anchor.x2) ? HorizontalMargin : 0, + Top = Alignment.HasFlag(Anchor.y0) ? VerticalMargin : 0, + Bottom = Alignment.HasFlag(Anchor.y2) ? VerticalMargin : 0, }; } } diff --git a/osu.Game.Rulesets.Karaoke/UI/HUD/SettingButtonsDisplay.cs b/osu.Game.Rulesets.Karaoke/UI/HUD/SettingButtonsDisplay.cs index 6264a85c9..111610dcc 100644 --- a/osu.Game.Rulesets.Karaoke/UI/HUD/SettingButtonsDisplay.cs +++ b/osu.Game.Rulesets.Karaoke/UI/HUD/SettingButtonsDisplay.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Layout; @@ -58,7 +57,7 @@ protected override bool OnInvalidate(Invalidation invalidation, InvalidationSour // trying to change relative position in here. if ((invalidation & Invalidation.MiscGeometry) != 0) { - var overlayDirection = Anchor.HasFlagFast(Anchor.x0) ? OverlayDirection.Left : OverlayDirection.Right; + var overlayDirection = Anchor.HasFlag(Anchor.x0) ? OverlayDirection.Left : OverlayDirection.Right; settingOverlayContainer?.ChangeOverlayDirection(overlayDirection); } diff --git a/osu.Game.Rulesets.Karaoke/osu.Game.Rulesets.Karaoke.csproj b/osu.Game.Rulesets.Karaoke/osu.Game.Rulesets.Karaoke.csproj index 7b401fc9b..db192822a 100644 --- a/osu.Game.Rulesets.Karaoke/osu.Game.Rulesets.Karaoke.csproj +++ b/osu.Game.Rulesets.Karaoke/osu.Game.Rulesets.Karaoke.csproj @@ -11,13 +11,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - +