1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-13 08:32:57 +08:00

Make CurrentPlaylistItem not a bindable

This commit is contained in:
Dan Balasescu 2024-11-12 01:38:31 +09:00
parent 9f08b37792
commit 72564b5c98
No known key found for this signature in database
24 changed files with 326 additions and 307 deletions

View File

@ -1,8 +1,6 @@
// 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.
#nullable disable
using System;
using System.Linq;
using System.Threading;
@ -10,6 +8,7 @@ using System.Threading.Tasks;
using Moq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Testing;
@ -31,8 +30,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Cached]
protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
private DrawableLoungeRoom drawableRoom;
private SearchTextBox searchTextBox;
private DrawableLoungeRoom drawableRoom = null!;
private SearchTextBox searchTextBox = null!;
private readonly ManualResetEventSlim allowResponseCallback = new ManualResetEventSlim();
@ -78,6 +77,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
SelectedRoom = new Bindable<Room?>()
}
}
};
@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestFocusViaKeyboardCommit()
{
DrawableLoungeRoom.PasswordEntryPopover popover = null;
DrawableLoungeRoom.PasswordEntryPopover? popover = null;
AddAssert("search textbox has focus", () => checkFocus(searchTextBox));
AddStep("click room twice", () =>
@ -103,11 +103,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("enter password", () => popover.ChildrenOfType<OsuPasswordTextBox>().Single().Text = "password");
AddStep("commit via enter", () => InputManager.Key(Key.Enter));
AddAssert("popover has focus", () => checkFocus(popover));
AddAssert("popover has focus", () => checkFocus(popover!));
AddStep("attempt another enter", () => InputManager.Key(Key.Enter));
AddAssert("popover still has focus", () => checkFocus(popover));
AddAssert("popover still has focus", () => checkFocus(popover!));
AddStep("unblock response", () => allowResponseCallback.Set());
@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestFocusViaMouseCommit()
{
DrawableLoungeRoom.PasswordEntryPopover popover = null;
DrawableLoungeRoom.PasswordEntryPopover? popover = null;
AddAssert("search textbox has focus", () => checkFocus(searchTextBox));
AddStep("click room twice", () =>
@ -144,11 +144,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
AddAssert("popover has focus", () => checkFocus(popover));
AddAssert("popover has focus", () => checkFocus(popover!));
AddStep("attempt another click", () => InputManager.Click(MouseButton.Left));
AddAssert("popover still has focus", () => checkFocus(popover));
AddAssert("popover still has focus", () => checkFocus(popover!));
AddStep("unblock response", () => allowResponseCallback.Set());

View File

@ -41,6 +41,31 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create rooms", () =>
{
PlaylistItem item1 = new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo = { StarRating = 2.5 }
}.BeatmapInfo);
PlaylistItem item2 = new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo = { StarRating = 4.5 }
}.BeatmapInfo);
PlaylistItem item3 = new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo =
{
StarRating = 2.5,
Metadata =
{
Artist = "very very very very very very very very very long artist",
ArtistUnicode = "very very very very very very very very very long artist",
Title = "very very very very very very very very very very very long title",
TitleUnicode = "very very very very very very very very very very very long title",
}
}
}.BeatmapInfo);
Child = rooms = new FillFlowContainer
{
Anchor = Anchor.Centre,
@ -56,16 +81,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Status = { Value = new RoomStatusOpen() },
EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
Type = { Value = MatchType.HeadToHead },
Playlist =
{
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo =
{
StarRating = 2.5
}
}.BeatmapInfo)
}
Playlist = { item1 },
CurrentPlaylistItem = item1
}),
createLoungeRoom(new Room
{
@ -74,46 +91,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
HasPassword = { Value = true },
EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
Type = { Value = MatchType.HeadToHead },
Playlist =
{
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo =
{
StarRating = 2.5,
Metadata =
{
Artist = "very very very very very very very very very long artist",
ArtistUnicode = "very very very very very very very very very long artist",
Title = "very very very very very very very very very very very long title",
TitleUnicode = "very very very very very very very very very very very long title",
}
}
}.BeatmapInfo)
}
Playlist = { item3 },
CurrentPlaylistItem = item3
}),
createLoungeRoom(new Room
{
Name = { Value = "Playlist room with multiple beatmaps" },
Status = { Value = new RoomStatusPlaying() },
EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
Playlist =
{
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo =
{
StarRating = 2.5
}
}.BeatmapInfo),
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo =
{
StarRating = 4.5
}
}.BeatmapInfo)
}
Playlist = { item1, item2 },
CurrentPlaylistItem = item1
}),
createLoungeRoom(new Room
{
@ -181,20 +168,29 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
Name = { Value = "A host-only room" },
QueueMode = { Value = QueueMode.HostOnly },
Type = { Value = MatchType.HeadToHead }
}),
Type = { Value = MatchType.HeadToHead },
})
{
SelectedItem = new Bindable<PlaylistItem>()
},
new DrawableMatchRoom(new Room
{
Name = { Value = "An all-players, team-versus room" },
QueueMode = { Value = QueueMode.AllPlayers },
Type = { Value = MatchType.TeamVersus }
}),
})
{
SelectedItem = new Bindable<PlaylistItem>()
},
new DrawableMatchRoom(new Room
{
Name = { Value = "A round-robin room" },
QueueMode = { Value = QueueMode.AllPlayersRoundRobin },
Type = { Value = MatchType.HeadToHead }
}),
})
{
SelectedItem = new Bindable<PlaylistItem>()
},
}
});
}
@ -215,7 +211,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
return new DrawableLoungeRoom(room)
{
MatchingFilter = true,
SelectedRoom = { BindTarget = selectedRoom }
SelectedRoom = selectedRoom
};
}
}

View File

@ -43,9 +43,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
private OsuButton readyButton => control.ChildrenOfType<OsuButton>().Single();
[Cached(typeof(IBindable<PlaylistItem>))]
private readonly Bindable<PlaylistItem> currentItem = new Bindable<PlaylistItem>();
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) =>
new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent)) { Model = { BindTarget = room } };
@ -107,31 +104,33 @@ namespace osu.Game.Tests.Visual.Multiplayer
[SetUpSteps]
public void SetUpSteps()
{
PlaylistItem item = null!;
AddStep("reset state", () =>
{
multiplayerClient.Invocations.Clear();
beatmapAvailability.Value = BeatmapAvailability.LocallyAvailable();
currentItem.Value = new PlaylistItem(Beatmap.Value.BeatmapInfo)
item = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID
};
room.Value = new Room
{
Playlist = { currentItem.Value },
CurrentPlaylistItem = { BindTarget = currentItem }
Playlist = { item },
CurrentPlaylistItem = item
};
localUser = new MultiplayerRoomUser(API.LocalUser.Value.Id) { User = API.LocalUser.Value };
localUser = new MultiplayerRoomUser(API.LocalUser.Value.Id)
{
User = API.LocalUser.Value
};
multiplayerRoom = new MultiplayerRoom(0)
{
Playlist =
{
TestMultiplayerClient.CreateMultiplayerPlaylistItem(currentItem.Value),
},
Playlist = { TestMultiplayerClient.CreateMultiplayerPlaylistItem(item) },
Users = { localUser },
Host = localUser,
};
@ -144,6 +143,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(250, 50),
SelectedItem = new Bindable<PlaylistItem?>(item)
};
});
}

View File

@ -1,7 +1,6 @@
// 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.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -13,9 +12,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerMatchFooter : MultiplayerTestScene
{
[Cached(typeof(IBindable<PlaylistItem>))]
private readonly Bindable<PlaylistItem> currentItem = new Bindable<PlaylistItem>();
public override void SetUpSteps()
{
base.SetUpSteps();
@ -33,7 +29,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = 50,
Child = new MultiplayerMatchFooter()
Child = new MultiplayerMatchFooter
{
SelectedItem = new Bindable<PlaylistItem?>()
}
}
};
});

View File

@ -28,9 +28,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerPlaylist : MultiplayerTestScene
{
[Cached(typeof(IBindable<PlaylistItem>))]
private readonly Bindable<PlaylistItem> currentItem = new Bindable<PlaylistItem>();
private MultiplayerPlaylist list = null!;
private BeatmapManager beatmaps = null!;
private BeatmapSetInfo importedSet = null!;
@ -56,7 +53,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.4f, 0.8f)
Size = new Vector2(0.4f, 0.8f),
SelectedItem = new Bindable<PlaylistItem?>()
};
});

View File

@ -26,9 +26,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerSpectateButton : MultiplayerTestScene
{
[Cached(typeof(IBindable<PlaylistItem>))]
private readonly Bindable<PlaylistItem> currentItem = new Bindable<PlaylistItem>();
private MultiplayerSpectateButton spectateButton = null!;
private MatchStartControl startControl = null!;
@ -51,13 +48,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create button", () =>
{
AvailabilityTracker.SelectedItem.BindTo(currentItem);
PlaylistItem item = SelectedRoom.Value.Playlist.First();
AvailabilityTracker.SelectedItem.Value = item;
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
currentItem.Value = SelectedRoom.Value.Playlist.First();
Child = new PopoverContainer
{
RelativeSizeAxes = Axes.Both,
@ -72,12 +69,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200, 50),
SelectedItem = new Bindable<PlaylistItem?>(item)
},
startControl = new MatchStartControl
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200, 50),
SelectedItem = new Bindable<PlaylistItem?>(item)
}
}
}

View File

@ -14,9 +14,17 @@ namespace osu.Game.Beatmaps.Drawables
/// </summary>
public partial class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable<IBeatmapInfo>
{
public readonly Bindable<IBeatmapInfo> Beatmap = new Bindable<IBeatmapInfo>();
public readonly Bindable<IBeatmapInfo?> Beatmap = new Bindable<IBeatmapInfo?>();
protected override double LoadDelay => 500;
/// <summary>
/// Delay before the background is loaded while on-screen.
/// </summary>
public double BackgroundLoadDelay = 500;
/// <summary>
/// Delay before the background is unloaded while off-screen.
/// </summary>
public double BackgroundUnloadDelay = 10000;
[Resolved]
private BeatmapManager beatmaps { get; set; } = null!;
@ -29,10 +37,9 @@ namespace osu.Game.Beatmaps.Drawables
this.beatmapSetCoverType = beatmapSetCoverType;
}
/// <summary>
/// Delay before the background is unloaded while off-screen.
/// </summary>
protected virtual double UnloadDelay => 10000;
protected override double LoadDelay => BackgroundLoadDelay;
protected virtual double UnloadDelay => BackgroundUnloadDelay;
protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func<Drawable> createContentFunc, double timeBeforeLoad) =>
new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad, UnloadDelay) { RelativeSizeAxes = Axes.Both };

View File

@ -203,7 +203,7 @@ namespace osu.Game.Online.Multiplayer
APIRoom.Playlist.Clear();
APIRoom.Playlist.AddRange(joinedRoom.Playlist.Select(item => new PlaylistItem(item)));
APIRoom.CurrentPlaylistItem.Value = APIRoom.Playlist.Single(item => item.ID == joinedRoom.Settings.PlaylistItemId);
APIRoom.CurrentPlaylistItem = APIRoom.Playlist.Single(item => item.ID == joinedRoom.Settings.PlaylistItemId);
// The server will null out the end date upon the host joining the room, but the null value is never communicated to the client.
APIRoom.EndDate.Value = null;
@ -847,7 +847,7 @@ namespace osu.Game.Online.Multiplayer
APIRoom.Type.Value = Room.Settings.MatchType;
APIRoom.QueueMode.Value = Room.Settings.QueueMode;
APIRoom.AutoStartDuration.Value = Room.Settings.AutoStartDuration;
APIRoom.CurrentPlaylistItem.Value = APIRoom.Playlist.Single(item => item.ID == settings.PlaylistItemId);
APIRoom.CurrentPlaylistItem = APIRoom.Playlist.Single(item => item.ID == settings.PlaylistItemId);
APIRoom.AutoSkip.Value = Room.Settings.AutoSkip;
RoomUpdated?.Invoke();

View File

@ -1,10 +1,11 @@
// 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.
#nullable disable
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using Newtonsoft.Json;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@ -16,8 +17,25 @@ using osu.Game.Online.Rooms.RoomStatuses;
namespace osu.Game.Online.Rooms
{
[JsonObject(MemberSerialization.OptIn)]
public partial class Room : IDependencyInjectionCandidate
public partial class Room : IDependencyInjectionCandidate, INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
[JsonProperty("current_playlist_item")]
private PlaylistItem? currentPlaylistItem;
/// <summary>
/// Represents the current item selected within the room.
/// </summary>
/// <remarks>
/// Only valid for room listing requests (i.e. in the lounge screen), and may not be valid while inside the room.
/// </remarks>
public PlaylistItem? CurrentPlaylistItem
{
get => currentPlaylistItem;
set => SetField(ref currentPlaylistItem, value);
}
[Cached]
[JsonProperty("id")]
public readonly Bindable<long?> RoomID = new Bindable<long?>();
@ -28,7 +46,7 @@ namespace osu.Game.Online.Rooms
[Cached]
[JsonProperty("host")]
public readonly Bindable<APIUser> Host = new Bindable<APIUser>();
public readonly Bindable<APIUser?> Host = new Bindable<APIUser?>();
[Cached]
[JsonProperty("playlist")]
@ -38,10 +56,6 @@ namespace osu.Game.Online.Rooms
[JsonProperty("channel_id")]
public readonly Bindable<int> ChannelId = new Bindable<int>();
[JsonProperty("current_playlist_item")]
[Cached]
public readonly Bindable<PlaylistItem> CurrentPlaylistItem = new Bindable<PlaylistItem>();
[JsonProperty("playlist_item_stats")]
[Cached]
public readonly Bindable<RoomPlaylistItemStats> PlaylistItemStats = new Bindable<RoomPlaylistItemStats>();
@ -126,7 +140,7 @@ namespace osu.Game.Online.Rooms
[Cached(Name = nameof(Password))]
[JsonProperty("password")]
public readonly Bindable<string> Password = new Bindable<string>();
public readonly Bindable<string?> Password = new Bindable<string?>();
[Cached]
public readonly Bindable<TimeSpan?> Duration = new Bindable<TimeSpan?>();
@ -203,7 +217,7 @@ namespace osu.Game.Online.Rooms
AutoStartDuration.Value = other.AutoStartDuration.Value;
DifficultyRange.Value = other.DifficultyRange.Value;
PlaylistItemStats.Value = other.PlaylistItemStats.Value;
CurrentPlaylistItem.Value = other.CurrentPlaylistItem.Value;
CurrentPlaylistItem = other.CurrentPlaylistItem;
AutoSkip.Value = other.AutoSkip.Value;
other.RemoveExpiredPlaylistItems();
@ -240,7 +254,7 @@ namespace osu.Game.Online.Rooms
public int CountTotal;
[JsonProperty("ruleset_ids")]
public int[] RulesetIDs;
public int[] RulesetIDs = [];
}
[JsonObject(MemberSerialization.OptIn)]
@ -252,5 +266,18 @@ namespace osu.Game.Online.Rooms
[JsonProperty("max")]
public double Max;
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null!)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null!)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
}

View File

@ -1,41 +0,0 @@
// 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.
#nullable disable
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Components
{
public partial class OnlinePlayBackgroundSprite : OnlinePlayComposite
{
protected readonly BeatmapSetCoverType BeatmapSetCoverType;
private UpdateableBeatmapBackgroundSprite sprite;
public OnlinePlayBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover)
{
BeatmapSetCoverType = beatmapSetCoverType;
}
[BackgroundDependencyLoader]
private void load()
{
InternalChild = sprite = CreateBackgroundSprite();
CurrentPlaylistItem.BindValueChanged(_ => updateBeatmap());
Playlist.CollectionChanged += (_, _) => updateBeatmap();
updateBeatmap();
}
private void updateBeatmap()
{
sprite.Beatmap.Value = CurrentPlaylistItem.Value?.Beatmap ?? Playlist.GetCurrentItem()?.Beatmap;
}
protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
}
}

View File

@ -1,9 +1,8 @@
// 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.
#nullable disable
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@ -16,6 +15,7 @@ using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
@ -29,27 +29,28 @@ using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
public partial class DrawableRoom : CompositeDrawable
public abstract partial class DrawableRoom : CompositeDrawable
{
protected const float CORNER_RADIUS = 10;
private const float height = 100;
public readonly Room Room;
protected Container ButtonsContainer { get; private set; }
protected readonly Bindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
protected Container ButtonsContainer { get; private set; } = null!;
private readonly Bindable<MatchType> roomType = new Bindable<MatchType>();
private readonly Bindable<RoomCategory> roomCategory = new Bindable<RoomCategory>();
private readonly Bindable<bool> hasPassword = new Bindable<bool>();
private DrawableRoomParticipantsList drawableRoomParticipantsList;
private RoomSpecialCategoryPill specialCategoryPill;
private PasswordProtectedIcon passwordIcon;
private EndDateInfo endDateInfo;
private DrawableRoomParticipantsList? drawableRoomParticipantsList;
private RoomSpecialCategoryPill? specialCategoryPill;
private PasswordProtectedIcon? passwordIcon;
private EndDateInfo? endDateInfo;
private UpdateableBeatmapBackgroundSprite background = null!;
private DelayedLoadWrapper wrapper = null!;
private DelayedLoadWrapper wrapper;
public DrawableRoom(Room room)
protected DrawableRoom(Room room)
{
Room = room;
@ -77,7 +78,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
AutoSizeAxes = Axes.X
};
InternalChildren = new[]
InternalChildren = new Drawable[]
{
// This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites.
new Box
@ -85,7 +86,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
RelativeSizeAxes = Axes.Both,
Colour = colours.Background5,
},
CreateBackground().With(d =>
background = CreateBackground().With(d =>
{
d.RelativeSizeAxes = Axes.Both;
}),
@ -186,7 +187,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
Font = OsuFont.GetFont(size: 28),
Current = { BindTarget = Room.Name }
},
new RoomStatusText()
new RoomStatusText
{
SelectedItem = { BindTarget = SelectedItem }
}
}
}
},
@ -245,6 +249,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
wrapper.DelayedLoadComplete += _ =>
{
Debug.Assert(specialCategoryPill != null);
Debug.Assert(endDateInfo != null);
Debug.Assert(passwordIcon != null);
wrapper.FadeInFromZero(200);
roomCategory.BindTo(Room.Category);
@ -265,6 +273,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
hasPassword.BindTo(Room.HasPassword);
hasPassword.BindValueChanged(v => passwordIcon.Alpha = v.NewValue ? 1 : 0, true);
};
SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap, true);
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@ -289,7 +299,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
}
}
protected virtual Drawable CreateBackground() => new OnlinePlayBackgroundSprite();
protected virtual UpdateableBeatmapBackgroundSprite CreateBackground() => new UpdateableBeatmapBackgroundSprite();
protected virtual IEnumerable<Drawable> CreateBottomDetails()
{
@ -324,14 +334,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
private partial class RoomStatusText : OnlinePlayComposite
{
[Resolved]
private OsuColour colours { get; set; }
public readonly IBindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
[Resolved]
private BeatmapLookupCache beatmapLookupCache { get; set; }
private OsuColour colours { get; set; } = null!;
private SpriteText statusText;
private LinkFlowContainer beatmapText;
[Resolved]
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
private SpriteText statusText = null!;
private LinkFlowContainer beatmapText = null!;
public RoomStatusText()
{
@ -383,12 +395,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
protected override void LoadComplete()
{
base.LoadComplete();
CurrentPlaylistItem.BindValueChanged(onSelectedItemChanged, true);
SelectedItem.BindValueChanged(onSelectedItemChanged, true);
}
private CancellationTokenSource beatmapLookupCancellation;
private CancellationTokenSource? beatmapLookupCancellation;
private void onSelectedItemChanged(ValueChangedEvent<PlaylistItem> item)
private void onSelectedItemChanged(ValueChangedEvent<PlaylistItem?> item)
{
beatmapLookupCancellation?.Cancel();
beatmapText.Clear();

View File

@ -140,7 +140,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
private void addRooms(IEnumerable<Room> rooms)
{
foreach (var room in rooms)
roomFlow.Add(new DrawableLoungeRoom(room) { SelectedRoom = { BindTarget = SelectedRoom } });
roomFlow.Add(new DrawableLoungeRoom(room) { SelectedRoom = SelectedRoom });
applyFilterCriteria(Filter?.Value);
}

View File

@ -1,9 +1,8 @@
// 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.
#nullable disable
using System.Collections.Generic;
using System.ComponentModel;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
@ -28,6 +27,7 @@ using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osuTK;
using osuTK.Graphics;
using Container = osu.Framework.Graphics.Containers.Container;
namespace osu.Game.Screens.OnlinePlay.Lounge
{
@ -39,14 +39,19 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
private const float transition_duration = 60;
private const float selection_border_width = 4;
public readonly Bindable<Room> SelectedRoom = new Bindable<Room>();
public required Bindable<Room?> SelectedRoom
{
get => selectedRoom;
set => selectedRoom.Current = value;
}
[Resolved(canBeNull: true)]
private LoungeSubScreen lounge { get; set; }
private LoungeSubScreen? lounge { get; set; }
private Sample sampleSelect;
private Sample sampleJoin;
private Drawable selectionBox;
private readonly BindableWithCurrent<Room?> selectedRoom = new BindableWithCurrent<Room?>();
private Sample? sampleSelect;
private Sample? sampleJoin;
private Drawable selectionBox = null!;
public DrawableLoungeRoom(Room room)
: base(room)
@ -89,12 +94,24 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
base.LoadComplete();
Alpha = matchingFilter ? 1 : 0;
selectionBox.Alpha = SelectedRoom.Value == Room ? 1 : 0;
selectionBox.Alpha = selectedRoom.Value == Room ? 1 : 0;
SelectedRoom.BindValueChanged(updateSelectedRoom);
selectedRoom.BindValueChanged(updateSelectedRoom);
Room.PropertyChanged += onRoomPropertyChanged;
updateSelectedItem();
}
private void updateSelectedRoom(ValueChangedEvent<Room> selected)
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Room.CurrentPlaylistItem))
updateSelectedItem();
}
private void updateSelectedItem()
=> SelectedItem.Value = Room.CurrentPlaylistItem;
private void updateSelectedRoom(ValueChangedEvent<Room?> selected)
{
if (selected.NewValue == Room)
selectionBox.FadeIn(transition_duration);
@ -140,7 +157,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
if (e.Repeat)
return false;
if (SelectedRoom.Value != Room)
if (selectedRoom.Value != Room)
return false;
switch (e.Action)
@ -157,14 +174,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
{
}
protected override bool ShouldBeConsideredForInput(Drawable child) => SelectedRoom.Value == Room || child is HoverSounds;
protected override bool ShouldBeConsideredForInput(Drawable child) => selectedRoom.Value == Room || child is HoverSounds;
protected override bool OnClick(ClickEvent e)
{
if (Room != SelectedRoom.Value)
if (Room != selectedRoom.Value)
{
sampleSelect?.Play();
SelectedRoom.Value = Room;
selectedRoom.Value = Room;
return true;
}
@ -179,12 +196,18 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
return true;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
Room.PropertyChanged -= onRoomPropertyChanged;
}
public partial class PasswordEntryPopover : OsuPopover
{
private readonly Room room;
[Resolved(canBeNull: true)]
private LoungeSubScreen lounge { get; set; }
private LoungeSubScreen? lounge { get; set; }
public override bool HandleNonPositionalInput => true;
@ -195,10 +218,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
this.room = room;
}
private OsuPasswordTextBox passwordTextBox;
private RoundedButton joinButton;
private OsuSpriteText errorText;
private Sample sampleJoinFail;
private OsuPasswordTextBox passwordTextBox = null!;
private RoundedButton joinButton = null!;
private OsuSpriteText errorText = null!;
private Sample? sampleJoinFail;
[BackgroundDependencyLoader]
private void load(OsuColour colours, AudioManager audio)

View File

@ -1,10 +1,7 @@
// 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.
#nullable disable
using System;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@ -21,25 +18,22 @@ namespace osu.Game.Screens.OnlinePlay.Match
{
public partial class DrawableMatchRoom : DrawableRoom
{
public readonly IBindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
public Action OnEdit;
public Action? OnEdit;
[Resolved]
private IAPIProvider api { get; set; }
private IAPIProvider api { get; set; } = null!;
private readonly IBindable<APIUser> host = new Bindable<APIUser>();
private readonly BindableWithCurrent<PlaylistItem?> current = new BindableWithCurrent<PlaylistItem?>();
private readonly IBindable<APIUser?> host = new Bindable<APIUser?>();
private readonly bool allowEdit;
[CanBeNull]
private Drawable editButton;
private BackgroundSprite background;
private Drawable? editButton;
public DrawableMatchRoom(Room room, bool allowEdit = true)
: base(room)
{
this.allowEdit = allowEdit;
base.SelectedItem.BindTo(SelectedItem);
host.BindTo(room.Host);
}
@ -58,21 +52,23 @@ namespace osu.Game.Screens.OnlinePlay.Match
}
}
public new required Bindable<PlaylistItem?> SelectedItem
{
get => current;
set => current.Current = value;
}
protected override void LoadComplete()
{
base.LoadComplete();
if (editButton != null)
host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true);
SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap, true);
}
protected override Drawable CreateBackground() => background = new BackgroundSprite();
private partial class BackgroundSprite : UpdateableBeatmapBackgroundSprite
protected override UpdateableBeatmapBackgroundSprite CreateBackground() => base.CreateBackground().With(d =>
{
protected override double LoadDelay => 0;
}
d.BackgroundLoadDelay = 0;
});
}
}

View File

@ -35,7 +35,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
[Cached(typeof(IPreviewTrackOwner))]
public abstract partial class RoomSubScreen : OnlinePlaySubScreen, IPreviewTrackOwner
{
[Cached(typeof(IBindable<PlaylistItem>))]
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
public override bool? ApplyModTrackAdjustments => true;
@ -164,7 +163,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
new DrawableMatchRoom(Room, allowEdit)
{
OnEdit = () => settingsOverlay.Show(),
SelectedItem = { BindTarget = SelectedItem }
SelectedItem = SelectedItem
}
},
null,

View File

@ -23,6 +23,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
public partial class MatchStartControl : CompositeDrawable
{
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!;
@ -32,9 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
[Resolved]
private MultiplayerClient client { get; set; } = null!;
[Resolved]
private IBindable<PlaylistItem?> currentItem { get; set; } = null!;
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
private readonly MultiplayerReadyButton readyButton;
private readonly MultiplayerCountdownButton countdownButton;
@ -94,7 +98,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
base.LoadComplete();
currentItem.BindValueChanged(_ => updateState());
SelectedItem.BindValueChanged(_ => updateState());
client.RoomUpdated += onRoomUpdated;
client.LoadRequested += onLoadRequested;
updateState();
@ -210,7 +214,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
readyButton.Enabled.Value = countdownButton.Enabled.Value =
client.Room.State != MultiplayerRoomState.Closed
&& currentItem.Value?.ID == client.Room.Settings.PlaylistItemId
&& SelectedItem.Value?.ID == client.Room.Settings.PlaylistItemId
&& !client.Room.Playlist.Single(i => i.ID == client.Room.Settings.PlaylistItemId).Expired
&& !operationInProgress.Value;

View File

@ -1,10 +1,10 @@
// 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.
#nullable disable
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
@ -13,6 +13,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private const float ready_button_width = 600;
private const float spectate_button_width = 200;
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
public MultiplayerMatchFooter()
{
RelativeSizeAxes = Axes.Both;
@ -22,17 +30,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
RelativeSizeAxes = Axes.Both,
Content = new[]
{
new Drawable[]
new Drawable?[]
{
null,
new MultiplayerSpectateButton
{
RelativeSizeAxes = Axes.Both,
SelectedItem = selectedItem
},
null,
new MatchStartControl
{
RelativeSizeAxes = Axes.Both,
SelectedItem = selectedItem
},
null
}

View File

@ -28,14 +28,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
public partial class MultiplayerMatchSettingsOverlay : RoomSettingsOverlay
{
private MatchSettings settings = null!;
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
protected override OsuButton SubmitButton => settings.ApplyButton;
protected override bool IsLoading => ongoingOperationTracker.InProgress.Value;
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!;
protected override bool IsLoading => ongoingOperationTracker.InProgress.Value;
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
private MatchSettings settings = null!;
public MultiplayerMatchSettingsOverlay(Room room)
: base(room)
@ -48,7 +54,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Y,
SettingsApplied = Hide
SettingsApplied = Hide,
SelectedItem = { BindTarget = SelectedItem }
};
protected partial class MatchSettings : OnlinePlayComposite
@ -57,6 +64,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
public readonly Bindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
public Action? SettingsApplied;
public OsuTextBox NameField = null!;
@ -66,7 +74,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
public OsuTextBox PasswordTextBox = null!;
public OsuCheckbox AutoSkipCheckbox = null!;
public RoundedButton ApplyButton = null!;
public OsuSpriteText ErrorText = null!;
private OsuEnumDropdown<StartMode> startModeDropdown = null!;
@ -367,7 +374,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
base.LoadComplete();
drawablePlaylist.Items.BindTo(Playlist);
drawablePlaylist.SelectedItem.BindTo(CurrentPlaylistItem);
drawablePlaylist.SelectedItem.BindTo(SelectedItem);
}
protected override void Update()
@ -448,7 +455,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
if (text.StartsWith(not_found_prefix, StringComparison.Ordinal))
{
ErrorText.Text = "The selected beatmap is not available online.";
CurrentPlaylistItem.Value.MarkInvalid();
SelectedItem.Value?.MarkInvalid();
}
else
{

View File

@ -21,6 +21,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
public partial class MultiplayerSpectateButton : CompositeDrawable
{
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!;
@ -30,13 +36,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
[Resolved]
private MultiplayerClient client { get; set; } = null!;
[Resolved]
private IBindable<PlaylistItem?> currentItem { get; set; } = null!;
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
private readonly RoundedButton button;
private IBindable<bool> operationInProgress = null!;
private readonly RoundedButton button;
public MultiplayerSpectateButton()
{
InternalChild = button = new RoundedButton
@ -71,7 +75,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
base.LoadComplete();
currentItem.BindValueChanged(_ => Scheduler.AddOnce(checkForAutomaticDownload), true);
SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(checkForAutomaticDownload), true);
client.RoomUpdated += onRoomUpdated;
updateState();
}
@ -117,7 +121,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private void checkForAutomaticDownload()
{
PlaylistItem? item = currentItem.Value;
PlaylistItem? item = SelectedItem.Value;
downloadCheckCancellation?.Cancel();

View File

@ -19,6 +19,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist
{
public readonly Bindable<MultiplayerPlaylistDisplayMode> DisplayMode = new Bindable<MultiplayerPlaylistDisplayMode>();
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
/// <summary>
/// Invoked when an item requests to be edited.
/// </summary>
@ -27,9 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist
[Resolved]
private MultiplayerClient client { get; set; } = null!;
[Resolved]
private IBindable<PlaylistItem?> currentItem { get; set; } = null!;
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
private MultiplayerPlaylistTabControl playlistTabControl = null!;
private MultiplayerQueueList queueList = null!;
private MultiplayerHistoryList historyList = null!;
@ -58,14 +62,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist
queueList = new MultiplayerQueueList
{
RelativeSizeAxes = Axes.Both,
SelectedItem = { BindTarget = currentItem },
SelectedItem = { BindTarget = selectedItem },
RequestEdit = item => RequestEdit?.Invoke(item)
},
historyList = new MultiplayerHistoryList
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
SelectedItem = { BindTarget = currentItem }
SelectedItem = { BindTarget = selectedItem }
}
}
}

View File

@ -1,13 +1,12 @@
// 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.
#nullable disable
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
@ -45,12 +44,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public override string ShortTitle => "room";
[Resolved]
private MultiplayerClient client { get; set; }
private MultiplayerClient client { get; set; } = null!;
[Resolved(canBeNull: true)]
private OsuGame game { get; set; }
private OsuGame? game { get; set; }
private AddItemButton addItemButton;
private AddItemButton addItemButton = null!;
public MultiplayerMatchSubScreen(Room room)
: base(room)
@ -95,7 +94,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
},
Content = new[]
{
new Drawable[]
new Drawable?[]
{
// Participants column
new GridContainer
@ -142,7 +141,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
new MultiplayerPlaylist
{
RelativeSizeAxes = Axes.Both,
RequestEdit = OpenSongSelection
RequestEdit = OpenSongSelection,
SelectedItem = SelectedItem
}
},
new[]
@ -220,7 +220,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
/// Opens the song selection screen to add or edit an item.
/// </summary>
/// <param name="itemToEdit">An optional playlist item to edit. If null, a new item will be added instead.</param>
internal void OpenSongSelection(PlaylistItem itemToEdit = null)
internal void OpenSongSelection(PlaylistItem? itemToEdit = null)
{
if (!this.IsCurrentScreen())
return;
@ -228,9 +228,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
this.Push(new MultiplayerMatchSongSelect(Room, itemToEdit));
}
protected override Drawable CreateFooter() => new MultiplayerMatchFooter();
protected override Drawable CreateFooter() => new MultiplayerMatchFooter
{
SelectedItem = SelectedItem
};
protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new MultiplayerMatchSettingsOverlay(room);
protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new MultiplayerMatchSettingsOverlay(room)
{
SelectedItem = SelectedItem
};
protected override void UpdateMods()
{
@ -245,7 +251,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
}
[Resolved(canBeNull: true)]
private IDialogOverlay dialogOverlay { get; set; }
private IDialogOverlay? dialogOverlay { get; set; }
private bool exitConfirmed;
@ -275,8 +281,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return base.OnExiting(e);
}
private ModSettingChangeTracker modSettingChangeTracker;
private ScheduledDelegate debouncedModSettingsUpdate;
private ModSettingChangeTracker? modSettingChangeTracker;
private ScheduledDelegate? debouncedModSettingsUpdate;
private void onUserModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
{
@ -422,7 +428,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return;
// If there's only one playlist item and we are the host, assume we want to change it. Else add a new one.
PlaylistItem itemToEdit = client.IsHost && Room.Playlist.Count == 1 ? Room.Playlist.Single() : null;
PlaylistItem? itemToEdit = client.IsHost && Room.Playlist.Count == 1 ? Room.Playlist.Single() : null;
OpenSongSelection(itemToEdit);
@ -434,7 +440,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
base.Dispose(isDisposing);
if (client != null)
if (client.IsNotNull())
{
client.RoomUpdated -= onRoomUpdated;
client.LoadRequested -= onLoadRequested;

View File

@ -1,8 +1,6 @@
// 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.
#nullable disable
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@ -10,7 +8,6 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Match;
namespace osu.Game.Screens.OnlinePlay
{
@ -20,96 +17,69 @@ namespace osu.Game.Screens.OnlinePlay
public partial class OnlinePlayComposite : CompositeDrawable
{
[Resolved(typeof(Room))]
protected Bindable<long?> RoomID { get; private set; }
protected Bindable<long?> RoomID { get; private set; } = null!;
[Resolved(typeof(Room), nameof(Room.Name))]
protected Bindable<string> RoomName { get; private set; }
protected Bindable<string> RoomName { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<APIUser> Host { get; private set; }
protected Bindable<APIUser> Host { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<RoomStatus> Status { get; private set; }
protected Bindable<RoomStatus> Status { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<MatchType> Type { get; private set; }
/// <summary>
/// The currently selected item in the <see cref="RoomSubScreen"/>, or the current item from <see cref="Playlist"/>
/// if this <see cref="OnlinePlayComposite"/> is not within a <see cref="RoomSubScreen"/>.
/// </summary>
[Resolved(typeof(Room))]
protected Bindable<PlaylistItem> CurrentPlaylistItem { get; private set; }
protected Bindable<MatchType> Type { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<Room.RoomPlaylistItemStats> PlaylistItemStats { get; private set; }
protected Bindable<Room.RoomPlaylistItemStats> PlaylistItemStats { get; private set; } = null!;
[Resolved(typeof(Room))]
protected BindableList<PlaylistItem> Playlist { get; private set; }
protected BindableList<PlaylistItem> Playlist { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<Room.RoomDifficultyRange> DifficultyRange { get; private set; }
protected Bindable<Room.RoomDifficultyRange> DifficultyRange { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<RoomCategory> Category { get; private set; }
protected Bindable<RoomCategory> Category { get; private set; } = null!;
[Resolved(typeof(Room))]
protected BindableList<APIUser> RecentParticipants { get; private set; }
protected BindableList<APIUser> RecentParticipants { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<int> ParticipantCount { get; private set; }
protected Bindable<int> ParticipantCount { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<int?> MaxParticipants { get; private set; }
protected Bindable<int?> MaxParticipants { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<int?> MaxAttempts { get; private set; }
protected Bindable<int?> MaxAttempts { get; private set; } = null!;
[Resolved(typeof(Room))]
public Bindable<PlaylistAggregateScore> UserScore { get; private set; }
public Bindable<PlaylistAggregateScore> UserScore { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<DateTimeOffset?> StartDate { get; private set; }
protected Bindable<DateTimeOffset?> StartDate { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<DateTimeOffset?> EndDate { get; private set; }
protected Bindable<DateTimeOffset?> EndDate { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<RoomAvailability> Availability { get; private set; }
protected Bindable<RoomAvailability> Availability { get; private set; } = null!;
[Resolved(typeof(Room))]
public Bindable<string> Password { get; private set; }
public Bindable<string> Password { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<TimeSpan?> Duration { get; private set; }
protected Bindable<TimeSpan?> Duration { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<QueueMode> QueueMode { get; private set; }
protected Bindable<QueueMode> QueueMode { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<TimeSpan> AutoStartDuration { get; private set; }
protected Bindable<TimeSpan> AutoStartDuration { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<bool> AutoSkip { get; private set; }
[Resolved(CanBeNull = true)]
private IBindable<PlaylistItem> subScreenSelectedItem { get; set; }
protected override void LoadComplete()
{
base.LoadComplete();
subScreenSelectedItem?.BindValueChanged(_ => UpdateSelectedItem());
Playlist.BindCollectionChanged((_, _) => UpdateSelectedItem(), true);
}
protected void UpdateSelectedItem()
{
// null room ID means this is a room in the process of being created.
if (RoomID.Value == null)
CurrentPlaylistItem.Value = Playlist.GetCurrentItem();
else if (subScreenSelectedItem != null)
CurrentPlaylistItem.Value = subScreenSelectedItem.Value;
}
protected Bindable<bool> AutoSkip { get; private set; } = null!;
}
}

View File

@ -232,7 +232,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
Name = ServerAPIRoom.Name.Value,
MatchType = ServerAPIRoom.Type.Value,
Password = password,
Password = password ?? string.Empty,
QueueMode = ServerAPIRoom.QueueMode.Value,
AutoStartDuration = ServerAPIRoom.AutoStartDuration.Value
},

View File

@ -1,8 +1,6 @@
// 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.
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics;
@ -296,10 +294,11 @@ namespace osu.Game.Tests.Visual.OnlinePlay
Debug.Assert(result != null);
// Playlist item IDs and beatmaps aren't serialised.
if (source.CurrentPlaylistItem.Value != null)
if (source.CurrentPlaylistItem != null)
{
result.CurrentPlaylistItem.Value = result.CurrentPlaylistItem.Value.With(new Optional<IBeatmapInfo>(source.CurrentPlaylistItem.Value.Beatmap));
result.CurrentPlaylistItem.Value.ID = source.CurrentPlaylistItem.Value.ID;
Debug.Assert(result.CurrentPlaylistItem != null);
result.CurrentPlaylistItem = result.CurrentPlaylistItem.With(new Optional<IBeatmapInfo>(source.CurrentPlaylistItem.Beatmap));
result.CurrentPlaylistItem.ID = source.CurrentPlaylistItem.ID;
}
for (int i = 0; i < source.Playlist.Count; i++)