1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-07 23:32:56 +08:00

Merge branch 'master' into hold-off-incompatibility

This commit is contained in:
Salman Ahmed 2024-07-19 14:38:10 +03:00 committed by GitHub
commit ce0397aaef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 209 additions and 120 deletions

View File

@ -67,7 +67,7 @@ jobs:
- { prettyname: macOS, fullname: macos-latest } - { prettyname: macOS, fullname: macos-latest }
- { prettyname: Linux, fullname: ubuntu-latest } - { prettyname: Linux, fullname: ubuntu-latest }
threadingMode: ['SingleThread', 'MultiThreaded'] threadingMode: ['SingleThread', 'MultiThreaded']
timeout-minutes: 60 timeout-minutes: 120
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Gameplay
return true; return true;
}); });
AddAssert("sample playback disabled", () => sampleDisabler.SamplePlaybackDisabled.Value); AddUntilStep("sample playback disabled", () => sampleDisabler.SamplePlaybackDisabled.Value);
// because we are in frame stable context, it's quite likely that not all samples are "played" at this point. // because we are in frame stable context, it's quite likely that not all samples are "played" at this point.
// the important thing is that at least one started, and that sample has since stopped. // the important thing is that at least one started, and that sample has since stopped.

View File

@ -12,6 +12,7 @@ using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -319,16 +320,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
}); });
AddUntilStep("wait for load", () => playlist.ChildrenOfType<DrawableLinkCompiler>().Any() && playlist.ChildrenOfType<BeatmapCardThumbnail>().First().DrawWidth > 0); AddUntilStep("wait for load", () => playlist.ChildrenOfType<DrawableLinkCompiler>().Any() && playlist.ChildrenOfType<BeatmapCardThumbnail>().First().DrawWidth > 0);
AddStep("move mouse to first item title", () =>
{ AddStep("move mouse to first item title", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<LinkFlowContainer>().First().ChildrenOfType<SpriteText>().First()));
var drawQuad = playlist.ChildrenOfType<LinkFlowContainer>().First().ScreenSpaceDrawQuad;
var location = (drawQuad.TopLeft + drawQuad.BottomLeft) / 2 + new Vector2(drawQuad.Width * 0.2f, 0);
InputManager.MoveMouseTo(location);
});
AddAssert("first item title not hovered", () => playlist.ChildrenOfType<DrawableLinkCompiler>().First().IsHovered, () => Is.False); AddAssert("first item title not hovered", () => playlist.ChildrenOfType<DrawableLinkCompiler>().First().IsHovered, () => Is.False);
AddStep("click left mouse", () => InputManager.Click(MouseButton.Left));
AddStep("click title", () =>
{
InputManager.MoveMouseTo(playlist.ChildrenOfType<LinkFlowContainer>().First().ChildrenOfType<SpriteText>().First());
InputManager.Click(MouseButton.Left);
});
AddUntilStep("first item selected", () => playlist.ChildrenOfType<DrawableRoomPlaylistItem>().First().IsSelectedItem, () => Is.True); AddUntilStep("first item selected", () => playlist.ChildrenOfType<DrawableRoomPlaylistItem>().First().IsSelectedItem, () => Is.True);
// implies being clickable.
AddUntilStep("first item title hovered", () => playlist.ChildrenOfType<DrawableLinkCompiler>().First().IsHovered, () => Is.True); AddUntilStep("first item title hovered", () => playlist.ChildrenOfType<DrawableLinkCompiler>().First().IsHovered, () => Is.True);
AddStep("move mouse to second item results button", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<GrayButton>().ElementAt(5))); AddStep("move mouse to second item results button", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<GrayButton>().ElementAt(5)));

View File

@ -1,12 +1,16 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Screens; using osu.Framework.Screens;
@ -204,12 +208,16 @@ namespace osu.Game.Tests.Visual.Navigation
AddStep("Set current beatmap to default", () => Game.Beatmap.SetDefault()); AddStep("Set current beatmap to default", () => Game.Beatmap.SetDefault());
AddStep("Push editor loader", () => Game.ScreenStack.Push(new EditorLoader())); DelayedLoadEditorLoader loader = null!;
AddStep("Push editor loader", () => Game.ScreenStack.Push(loader = new DelayedLoadEditorLoader()));
AddUntilStep("Wait for loader current", () => Game.ScreenStack.CurrentScreen is EditorLoader); AddUntilStep("Wait for loader current", () => Game.ScreenStack.CurrentScreen is EditorLoader);
AddUntilStep("wait for editor load start", () => loader.Editor != null);
AddStep("Close editor while loading", () => Game.ScreenStack.CurrentScreen.Exit()); AddStep("Close editor while loading", () => Game.ScreenStack.CurrentScreen.Exit());
AddStep("allow editor load", () => loader.AllowLoad.Set());
AddUntilStep("wait for editor ready", () => loader.Editor!.LoadState >= LoadState.Ready);
AddUntilStep("Wait for menu", () => Game.ScreenStack.CurrentScreen is MainMenu); AddUntilStep("Wait for menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
AddAssert("Check no new beatmaps were made", () => allBeatmapSets().SequenceEqual(beatmapSets)); AddAssert("Check no new beatmaps were made", allBeatmapSets, () => Is.EquivalentTo(beatmapSets));
BeatmapSetInfo[] allBeatmapSets() => Game.Realm.Run(realm => realm.All<BeatmapSetInfo>().Where(x => !x.DeletePending).ToArray()); BeatmapSetInfo[] allBeatmapSets() => Game.Realm.Run(realm => realm.All<BeatmapSetInfo>().Where(x => !x.DeletePending).ToArray());
} }
@ -356,5 +364,33 @@ namespace osu.Game.Tests.Visual.Navigation
private EditorBeatmap getEditorBeatmap() => getEditor().ChildrenOfType<EditorBeatmap>().Single(); private EditorBeatmap getEditorBeatmap() => getEditor().ChildrenOfType<EditorBeatmap>().Single();
private Editor getEditor() => (Editor)Game.ScreenStack.CurrentScreen; private Editor getEditor() => (Editor)Game.ScreenStack.CurrentScreen;
private partial class DelayedLoadEditorLoader : EditorLoader
{
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim();
public Editor? Editor { get; private set; }
protected override Editor CreateEditor() => Editor = new DelayedLoadEditor(this);
}
private partial class DelayedLoadEditor : Editor
{
private readonly DelayedLoadEditorLoader loader;
public DelayedLoadEditor(DelayedLoadEditorLoader loader)
: base(loader)
{
this.loader = loader;
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
// Importantly, this occurs before base.load().
if (!loader.AllowLoad.Wait(TimeSpan.FromSeconds(10)))
throw new TimeoutException();
return base.CreateChildDependencies(parent);
}
}
} }
} }

View File

@ -952,6 +952,8 @@ namespace osu.Game.Tests.Visual.Navigation
[Test] [Test]
public void TestTouchScreenDetectionAtSongSelect() public void TestTouchScreenDetectionAtSongSelect()
{ {
AddUntilStep("wait for settings", () => Game.Settings.IsLoaded);
AddStep("touch logo", () => AddStep("touch logo", () =>
{ {
var button = Game.ChildrenOfType<OsuLogo>().Single(); var button = Game.ChildrenOfType<OsuLogo>().Single();

View File

@ -157,6 +157,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
setUpCommentsResponse(getExampleComments()); setUpCommentsResponse(getExampleComments());
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123)); AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
AddUntilStep("comments shown", () => commentsContainer.ChildrenOfType<DrawableComment>().Any());
setUpPostResponse(); setUpPostResponse();
AddStep("enter text", () => editorTextBox.Current.Value = "comm"); AddStep("enter text", () => editorTextBox.Current.Value = "comm");
@ -175,6 +176,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
setUpCommentsResponse(getExampleComments()); setUpCommentsResponse(getExampleComments());
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123)); AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
AddUntilStep("comments shown", () => commentsContainer.ChildrenOfType<DrawableComment>().Any());
setUpPostResponse(true); setUpPostResponse(true);
AddStep("enter text", () => editorTextBox.Current.Value = "comm"); AddStep("enter text", () => editorTextBox.Current.Value = "comm");

View File

@ -101,7 +101,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
bool shouldDim = Dimmed.Value || playButton.Playing.Value; bool shouldDim = Dimmed.Value || playButton.Playing.Value;
playButton.FadeTo(shouldDim ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); playButton.FadeTo(shouldDim ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
background.FadeColour(colourProvider.Background6.Opacity(shouldDim ? 0.8f : 0f), BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); background.FadeColour(colourProvider.Background6.Opacity(shouldDim ? 0.6f : 0f), BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
} }
} }
} }

View File

@ -49,6 +49,8 @@ namespace osu.Game.Screens.OnlinePlay
private const float icon_height = 34; private const float icon_height = 34;
private const float border_thickness = 3;
/// <summary> /// <summary>
/// Invoked when this item requests to be deleted. /// Invoked when this item requests to be deleted.
/// </summary> /// </summary>
@ -81,7 +83,7 @@ namespace osu.Game.Screens.OnlinePlay
private IRulesetInfo ruleset; private IRulesetInfo ruleset;
private Mod[] requiredMods = Array.Empty<Mod>(); private Mod[] requiredMods = Array.Empty<Mod>();
private Container maskingContainer; private Container borderContainer;
private FillFlowContainer difficultyIconContainer; private FillFlowContainer difficultyIconContainer;
private LinkFlowContainer beatmapText; private LinkFlowContainer beatmapText;
private LinkFlowContainer authorText; private LinkFlowContainer authorText;
@ -134,7 +136,7 @@ namespace osu.Game.Screens.OnlinePlay
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
maskingContainer.BorderColour = colours.Yellow; borderContainer.BorderColour = colours.Yellow;
ruleset = rulesets.GetRuleset(Item.RulesetID); ruleset = rulesets.GetRuleset(Item.RulesetID);
var rulesetInstance = ruleset?.CreateInstance(); var rulesetInstance = ruleset?.CreateInstance();
@ -161,7 +163,7 @@ namespace osu.Game.Screens.OnlinePlay
return; return;
} }
maskingContainer.BorderThickness = IsSelectedItem ? 5 : 0; borderContainer.BorderThickness = IsSelectedItem ? border_thickness : 0;
}, true); }, true);
valid.BindValueChanged(_ => Scheduler.AddOnce(refresh)); valid.BindValueChanged(_ => Scheduler.AddOnce(refresh));
@ -278,8 +280,8 @@ namespace osu.Game.Screens.OnlinePlay
{ {
if (!valid.Value) if (!valid.Value)
{ {
maskingContainer.BorderThickness = 5; borderContainer.BorderThickness = border_thickness;
maskingContainer.BorderColour = colours.Red; borderContainer.BorderColour = colours.Red;
} }
if (beatmap != null) if (beatmap != null)
@ -291,12 +293,14 @@ namespace osu.Game.Screens.OnlinePlay
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Width = 60, Width = 60,
Masking = true,
CornerRadius = 10,
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Dimmed = { Value = IsHovered } Dimmed = { Value = IsHovered }
}, },
new DifficultyIcon(beatmap, ruleset, requiredMods) new DifficultyIcon(beatmap, ruleset, requiredMods)
{ {
Size = new Vector2(icon_height), Size = new Vector2(24),
TooltipType = DifficultyIconTooltipType.Extended, TooltipType = DifficultyIconTooltipType.Extended,
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
@ -346,136 +350,153 @@ namespace osu.Game.Screens.OnlinePlay
{ {
Action<SpriteText> fontParameters = s => s.Font = OsuFont.Default.With(size: 14, weight: FontWeight.SemiBold); Action<SpriteText> fontParameters = s => s.Font = OsuFont.Default.With(size: 14, weight: FontWeight.SemiBold);
return maskingContainer = new Container return new Container
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = HEIGHT, Height = HEIGHT,
Masking = true,
CornerRadius = 10,
Children = new Drawable[] Children = new Drawable[]
{ {
new Box // A transparent box that forces the border to be drawn if the panel background is opaque new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Alpha = 0, Masking = true,
AlwaysPresent = true CornerRadius = 10,
}, Children = new Drawable[]
onScreenLoader,
panelBackground = new PanelBackground
{
RelativeSizeAxes = Axes.Both,
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{ {
new Dimension(GridSizeMode.AutoSize), onScreenLoader,
new Dimension(), panelBackground = new PanelBackground
new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize)
},
Content = new[]
{
new Drawable[]
{ {
difficultyIconContainer = new FillFlowContainer RelativeSizeAxes = Axes.Both,
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{ {
Anchor = Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize),
Origin = Anchor.CentreLeft, new Dimension(),
AutoSizeAxes = Axes.X, new Dimension(GridSizeMode.AutoSize),
RelativeSizeAxes = Axes.Y, new Dimension(GridSizeMode.AutoSize)
Direction = FillDirection.Horizontal,
Spacing = new Vector2(4),
Margin = new MarginPadding { Right = 4 },
}, },
mainFillFlow = new MainFlow(() => SelectedItem.Value == Model || !AllowSelection) Content = new[]
{ {
Anchor = Anchor.CentreLeft, new Drawable[]
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{ {
beatmapText = new LinkFlowContainer(fontParameters) difficultyIconContainer = new FillFlowContainer
{ {
RelativeSizeAxes = Axes.X, Anchor = Anchor.CentreLeft,
// workaround to ensure only the first line of text shows, emulating truncation (but without ellipsis at the end). Origin = Anchor.CentreLeft,
// TODO: remove when text/link flow can support truncation with ellipsis natively. AutoSizeAxes = Axes.X,
Height = OsuFont.DEFAULT_FONT_SIZE, RelativeSizeAxes = Axes.Y,
Masking = true
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
Spacing = new Vector2(10f, 0), Spacing = new Vector2(4),
Margin = new MarginPadding { Right = 4 },
},
mainFillFlow = new MainFlow(() => SelectedItem.Value == Model || !AllowSelection)
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, -2),
Children = new Drawable[] Children = new Drawable[]
{ {
beatmapText = new LinkFlowContainer(fontParameters)
{
RelativeSizeAxes = Axes.X,
// workaround to ensure only the first line of text shows, emulating truncation (but without ellipsis at the end).
// TODO: remove when text/link flow can support truncation with ellipsis natively.
Height = OsuFont.DEFAULT_FONT_SIZE,
Masking = true
},
new FillFlowContainer new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
Spacing = new Vector2(10f, 0), Spacing = new Vector2(10f, 0),
Children = new Drawable[] Children = new Drawable[]
{ {
authorText = new LinkFlowContainer(fontParameters) { AutoSizeAxes = Axes.Both }, new FillFlowContainer
explicitContent = new ExplicitContentBeatmapBadge
{ {
Alpha = 0f, AutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Top = 3f }, Direction = FillDirection.Horizontal,
Spacing = new Vector2(10f, 0),
Children = new Drawable[]
{
authorText = new LinkFlowContainer(fontParameters) { AutoSizeAxes = Axes.Both },
explicitContent = new ExplicitContentBeatmapBadge
{
Alpha = 0f,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Top = 3f },
}
},
},
new Container
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Both,
Child = modDisplay = new ModDisplay
{
Scale = new Vector2(0.4f),
ExpansionMode = ExpansionMode.AlwaysExpanded,
Margin = new MarginPadding { Vertical = -6 },
}
} }
},
},
new Container
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Both,
Child = modDisplay = new ModDisplay
{
Scale = new Vector2(0.4f),
ExpansionMode = ExpansionMode.AlwaysExpanded,
Margin = new MarginPadding { Vertical = -6 },
} }
} }
} }
} },
buttonsFlow = new FillFlowContainer
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Direction = FillDirection.Horizontal,
Margin = new MarginPadding { Horizontal = 8 },
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(5),
ChildrenEnumerable = createButtons().Select(button => button.With(b =>
{
b.Anchor = Anchor.Centre;
b.Origin = Anchor.Centre;
}))
},
ownerAvatar = new OwnerAvatar
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(icon_height),
Margin = new MarginPadding { Right = 8 },
Masking = true,
CornerRadius = 4,
Alpha = ShowItemOwner ? 1 : 0
},
} }
}, }
buttonsFlow = new FillFlowContainer },
{ },
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Direction = FillDirection.Horizontal,
Margin = new MarginPadding { Horizontal = 8 },
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(5),
ChildrenEnumerable = createButtons().Select(button => button.With(b =>
{
b.Anchor = Anchor.Centre;
b.Origin = Anchor.Centre;
}))
},
ownerAvatar = new OwnerAvatar
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(icon_height),
Margin = new MarginPadding { Right = 8 },
Masking = true,
CornerRadius = 4,
Alpha = ShowItemOwner ? 1 : 0
},
}
}
}, },
}, borderContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 10,
Children = new Drawable[]
{
new Box // A transparent box that forces the border to be drawn if the panel background is opaque
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
},
}
}
}
}; };
} }
@ -509,6 +530,8 @@ namespace osu.Game.Screens.OnlinePlay
{ {
if (thumbnail != null) if (thumbnail != null)
thumbnail.Dimmed.Value = true; thumbnail.Dimmed.Value = true;
panelBackground.FadeColour(OsuColour.Gray(0.7f), BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
return base.OnHover(e); return base.OnHover(e);
} }
@ -516,6 +539,8 @@ namespace osu.Game.Screens.OnlinePlay
{ {
if (thumbnail != null) if (thumbnail != null)
thumbnail.Dimmed.Value = false; thumbnail.Dimmed.Value = false;
panelBackground.FadeColour(OsuColour.Gray(1f), BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
base.OnHoverLost(e); base.OnHoverLost(e);
} }
@ -642,7 +667,6 @@ namespace osu.Game.Screens.OnlinePlay
backgroundSprite = new UpdateableBeatmapBackgroundSprite backgroundSprite = new UpdateableBeatmapBackgroundSprite
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fill,
}, },
new FillFlowContainer new FillFlowContainer
{ {
@ -651,7 +675,7 @@ namespace osu.Game.Screens.OnlinePlay
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
// This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle
Shear = new Vector2(0.8f, 0), Shear = new Vector2(0.8f, 0),
Alpha = 0.5f, Alpha = 0.6f,
Children = new[] Children = new[]
{ {
// The left half with no gradient applied // The left half with no gradient applied

View File

@ -281,10 +281,33 @@ namespace osu.Game.Screens.Select
realmBeatmapSets.Clear(); realmBeatmapSets.Clear();
realmBeatmapSets.AddRange(sender.Select(r => r.ID)); realmBeatmapSets.AddRange(sender.Select(r => r.ID));
if (originalBeatmapSetsDetached.Count > 0 && sender.Count == 0)
{
// Usually we'd reset stuff here, but doing so triggers a silly flow which ends up deadlocking realm.
// Additionally, user should not be at song select when realm is blocking all operations in the first place.
//
// Note that due to the catch-up logic below, once operations are restored we will still be in a roughly
// correct state. The only things that this return will change is the carousel will not empty *during* the blocking
// operation.
return;
}
// Do a full two-way check for missing (or incorrectly present) beatmaps.
// Let's assume that the worst that can happen is deletions or additions.
setsRequiringRemoval.Clear(); setsRequiringRemoval.Clear();
setsRequiringUpdate.Clear(); setsRequiringUpdate.Clear();
loadBeatmapSets(sender); foreach (Guid id in realmBeatmapSets)
{
if (!root.BeatmapSetsByID.ContainsKey(id))
setsRequiringUpdate.Add(id);
}
foreach (Guid id in root.BeatmapSetsByID.Keys)
{
if (!realmBeatmapSets.Contains(id))
setsRequiringRemoval.Add(id);
}
} }
else else
{ {

View File

@ -609,7 +609,7 @@ namespace osu.Game.Screens.Select
// clear pending task immediately to track any potential nested debounce operation. // clear pending task immediately to track any potential nested debounce operation.
selectionChangedDebounce = null; selectionChangedDebounce = null;
Logger.Log($"Song select updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ShortName ?? "null"}"); Logger.Log($"Song select updating selection with beatmap: {beatmap} {beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ShortName ?? "null"}");
if (transferRulesetValue()) if (transferRulesetValue())
{ {