Merge branch 'master' into fix-transform-mutation-loading-layer

This commit is contained in:
Bartłomiej Dach
2021-01-05 23:10:51 +01:00
11 changed files with 83 additions and 43 deletions

View File

@ -7,8 +7,10 @@ using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -23,6 +25,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public class TestSceneMultiplayerReadyButton : MultiplayerTestScene public class TestSceneMultiplayerReadyButton : MultiplayerTestScene
{ {
private MultiplayerReadyButton button; private MultiplayerReadyButton button;
private BeatmapSetInfo importedSet;
private BeatmapManager beatmaps; private BeatmapManager beatmaps;
private RulesetStore rulesets; private RulesetStore rulesets;
@ -38,9 +41,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
[SetUp] [SetUp]
public new void Setup() => Schedule(() => public new void Setup() => Schedule(() =>
{ {
var beatmap = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First().Beatmaps.First(); importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap);
Child = button = new MultiplayerReadyButton Child = button = new MultiplayerReadyButton
{ {
@ -51,13 +53,30 @@ namespace osu.Game.Tests.Visual.Multiplayer
{ {
Value = new PlaylistItem Value = new PlaylistItem
{ {
Beatmap = { Value = beatmap }, Beatmap = { Value = Beatmap.Value.BeatmapInfo },
Ruleset = { Value = beatmap.Ruleset } Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset }
} }
} }
}; };
}); });
[Test]
public void TestDeletedBeatmapDisableReady()
{
OsuButton readyButton = null;
AddAssert("ensure ready button enabled", () =>
{
readyButton = button.ChildrenOfType<OsuButton>().Single();
return readyButton.Enabled.Value;
});
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
AddAssert("ready button disabled", () => !readyButton.Enabled.Value);
AddStep("undelete beatmap", () => beatmaps.Undelete(importedSet));
AddAssert("ready button enabled back", () => readyButton.Enabled.Value);
}
[Test] [Test]
public void TestToggleStateWhenNotHost() public void TestToggleStateWhenNotHost()
{ {

View File

@ -151,11 +151,11 @@ namespace osu.Game
updateBlockingOverlayFade(); updateBlockingOverlayFade();
} }
public void RemoveBlockingOverlay(OverlayContainer overlay) public void RemoveBlockingOverlay(OverlayContainer overlay) => Schedule(() =>
{ {
visibleBlockingOverlays.Remove(overlay); visibleBlockingOverlays.Remove(overlay);
updateBlockingOverlayFade(); updateBlockingOverlayFade();
} });
/// <summary> /// <summary>
/// Close all game-wide overlays. /// Close all game-wide overlays.

View File

@ -2,12 +2,15 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarBeatmapListingButton : ToolbarOverlayToggleButton public class ToolbarBeatmapListingButton : ToolbarOverlayToggleButton
{ {
protected override Anchor TooltipAnchor => Anchor.TopRight;
public ToolbarBeatmapListingButton() public ToolbarBeatmapListingButton()
{ {
Hotkey = GlobalAction.ToggleDirect; Hotkey = GlobalAction.ToggleDirect;

View File

@ -2,11 +2,14 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarChangelogButton : ToolbarOverlayToggleButton public class ToolbarChangelogButton : ToolbarOverlayToggleButton
{ {
protected override Anchor TooltipAnchor => Anchor.TopRight;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(ChangelogOverlay changelog) private void load(ChangelogOverlay changelog)
{ {

View File

@ -2,12 +2,15 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarChatButton : ToolbarOverlayToggleButton public class ToolbarChatButton : ToolbarOverlayToggleButton
{ {
protected override Anchor TooltipAnchor => Anchor.TopRight;
public ToolbarChatButton() public ToolbarChatButton()
{ {
Hotkey = GlobalAction.ToggleChat; Hotkey = GlobalAction.ToggleChat;

View File

@ -2,11 +2,14 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarNewsButton : ToolbarOverlayToggleButton public class ToolbarNewsButton : ToolbarOverlayToggleButton
{ {
protected override Anchor TooltipAnchor => Anchor.TopRight;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(NewsOverlay news) private void load(NewsOverlay news)
{ {

View File

@ -2,11 +2,14 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarRankingsButton : ToolbarOverlayToggleButton public class ToolbarRankingsButton : ToolbarOverlayToggleButton
{ {
protected override Anchor TooltipAnchor => Anchor.TopRight;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(RankingsOverlay rankings) private void load(RankingsOverlay rankings)
{ {

View File

@ -2,12 +2,15 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarSocialButton : ToolbarOverlayToggleButton public class ToolbarSocialButton : ToolbarOverlayToggleButton
{ {
protected override Anchor TooltipAnchor => Anchor.TopRight;
public ToolbarSocialButton() public ToolbarSocialButton()
{ {
Hotkey = GlobalAction.ToggleSocial; Hotkey = GlobalAction.ToggleSocial;

View File

@ -2,8 +2,6 @@
// 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;
using System.Linq;
using System.Linq.Expressions;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -41,38 +39,21 @@ namespace osu.Game.Screens.OnlinePlay.Components
SelectedItem.BindValueChanged(item => updateSelectedItem(item.NewValue), true); SelectedItem.BindValueChanged(item => updateSelectedItem(item.NewValue), true);
} }
private void updateSelectedItem(PlaylistItem item) private void updateSelectedItem(PlaylistItem _) => Scheduler.AddOnce(updateBeatmapState);
{ private void beatmapUpdated(ValueChangedEvent<WeakReference<BeatmapSetInfo>> _) => Scheduler.AddOnce(updateBeatmapState);
hasBeatmap = findBeatmap(expr => beatmaps.QueryBeatmap(expr)); private void beatmapRemoved(ValueChangedEvent<WeakReference<BeatmapSetInfo>> _) => Scheduler.AddOnce(updateBeatmapState);
}
private void beatmapUpdated(ValueChangedEvent<WeakReference<BeatmapSetInfo>> weakSet) private void updateBeatmapState()
{
if (weakSet.NewValue.TryGetTarget(out var set))
{
if (findBeatmap(expr => set.Beatmaps.AsQueryable().FirstOrDefault(expr)))
Schedule(() => hasBeatmap = true);
}
}
private void beatmapRemoved(ValueChangedEvent<WeakReference<BeatmapSetInfo>> weakSet)
{
if (weakSet.NewValue.TryGetTarget(out var set))
{
if (findBeatmap(expr => set.Beatmaps.AsQueryable().FirstOrDefault(expr)))
Schedule(() => hasBeatmap = false);
}
}
private bool findBeatmap(Func<Expression<Func<BeatmapInfo, bool>>, BeatmapInfo> expression)
{ {
int? beatmapId = SelectedItem.Value?.Beatmap.Value?.OnlineBeatmapID; int? beatmapId = SelectedItem.Value?.Beatmap.Value?.OnlineBeatmapID;
string checksum = SelectedItem.Value?.Beatmap.Value?.MD5Hash; string checksum = SelectedItem.Value?.Beatmap.Value?.MD5Hash;
if (beatmapId == null || checksum == null) if (beatmapId == null || checksum == null)
return false; return;
return expression(b => b.OnlineBeatmapID == beatmapId && b.MD5Hash == checksum) != null; var databasedBeatmap = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId && b.MD5Hash == checksum);
hasBeatmap = databasedBeatmap?.BeatmapSet?.DeletePending == false;
} }
protected override void Update() protected override void Update()

View File

@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Pooling;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Layout;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -124,6 +125,8 @@ namespace osu.Game.Screens.Select
{ {
BeatmapSetsChanged?.Invoke(); BeatmapSetsChanged?.Invoke();
BeatmapSetsLoaded = true; BeatmapSetsLoaded = true;
itemsCache.Invalidate();
}); });
} }
@ -567,6 +570,15 @@ namespace osu.Game.Screens.Select
#endregion #endregion
protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source)
{
// handles the vertical size of the carousel changing (ie. on window resize when aspect ratio has changed).
if ((invalidation & Invalidation.Layout) > 0)
itemsCache.Invalidate();
return base.OnInvalidate(invalidation, source);
}
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
@ -777,13 +789,19 @@ namespace osu.Game.Screens.Select
Scroll.ScrollContent.Height = currentY; Scroll.ScrollContent.Height = currentY;
if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) itemsCache.Validate();
// update and let external consumers know about selection loss.
if (BeatmapSetsLoaded)
{
bool selectionLost = selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected;
if (selectionLost)
{ {
selectedBeatmapSet = null; selectedBeatmapSet = null;
SelectionChanged?.Invoke(null); SelectionChanged?.Invoke(null);
} }
}
itemsCache.Validate();
} }
private bool firstScroll = true; private bool firstScroll = true;
@ -806,14 +824,13 @@ namespace osu.Game.Screens.Select
break; break;
case PendingScrollOperation.Immediate: case PendingScrollOperation.Immediate:
// in order to simplify animation logic, rather than using the animated version of ScrollTo, // in order to simplify animation logic, rather than using the animated version of ScrollTo,
// we take the difference in scroll height and apply to all visible panels. // we take the difference in scroll height and apply to all visible panels.
// this avoids edge cases like when the visible panels is reduced suddenly, causing ScrollContainer // this avoids edge cases like when the visible panels is reduced suddenly, causing ScrollContainer
// to enter clamp-special-case mode where it animates completely differently to normal. // to enter clamp-special-case mode where it animates completely differently to normal.
float scrollChange = scrollTarget.Value - Scroll.Current; float scrollChange = scrollTarget.Value - Scroll.Current;
Scroll.ScrollTo(scrollTarget.Value, false); Scroll.ScrollTo(scrollTarget.Value, false);
foreach (var i in Scroll.Children) foreach (var i in Scroll.Children)
i.Y += scrollChange; i.Y += scrollChange;
break; break;

View File

@ -428,16 +428,21 @@ namespace osu.Game.Screens.Select
private void updateSelectedBeatmap(BeatmapInfo beatmap) private void updateSelectedBeatmap(BeatmapInfo beatmap)
{ {
if (beatmap == null && beatmapNoDebounce == null)
return;
if (beatmap?.Equals(beatmapNoDebounce) == true) if (beatmap?.Equals(beatmapNoDebounce) == true)
return; return;
beatmapNoDebounce = beatmap; beatmapNoDebounce = beatmap;
performUpdateSelected(); performUpdateSelected();
} }
private void updateSelectedRuleset(RulesetInfo ruleset) private void updateSelectedRuleset(RulesetInfo ruleset)
{ {
if (ruleset == null && rulesetNoDebounce == null)
return;
if (ruleset?.Equals(rulesetNoDebounce) == true) if (ruleset?.Equals(rulesetNoDebounce) == true)
return; return;