mirror of
https://github.com/ppy/osu.git
synced 2025-02-16 05:52:55 +08:00
Merge pull request #11793 from peppy/playlists-freemod-support
Add "free mod" user mod selection support to the playlists system
This commit is contained in:
commit
781379826b
@ -8,11 +8,14 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
@ -26,6 +29,14 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
||||
|
||||
private readonly ModSelectOverlay userModsSelectOverlay;
|
||||
|
||||
/// <summary>
|
||||
/// A container that provides controls for selection of user mods.
|
||||
/// This will be shown/hidden automatically when applicable.
|
||||
/// </summary>
|
||||
protected Drawable UserModsSection;
|
||||
|
||||
private Sample sampleStart;
|
||||
|
||||
/// <summary>
|
||||
@ -51,9 +62,26 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
protected RoomSubScreen()
|
||||
{
|
||||
AddInternal(BeatmapAvailablilityTracker = new OnlinePlayBeatmapAvailablilityTracker
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
SelectedItem = { BindTarget = SelectedItem }
|
||||
BeatmapAvailablilityTracker = new OnlinePlayBeatmapAvailablilityTracker
|
||||
{
|
||||
SelectedItem = { BindTarget = SelectedItem }
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Depth = float.MinValue,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING },
|
||||
Child = userModsSelectOverlay = new UserModSelectOverlay
|
||||
{
|
||||
SelectedMods = { BindTarget = UserMods },
|
||||
IsValidMod = _ => false
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -78,6 +106,19 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods));
|
||||
}
|
||||
|
||||
public override bool OnBackButton()
|
||||
{
|
||||
if (userModsSelectOverlay.State.Value == Visibility.Visible)
|
||||
{
|
||||
userModsSelectOverlay.Hide();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnBackButton();
|
||||
}
|
||||
|
||||
protected void ShowUserModSelect() => userModsSelectOverlay.Show();
|
||||
|
||||
public override void OnEntering(IScreen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
@ -117,17 +158,31 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
{
|
||||
updateWorkingBeatmap();
|
||||
|
||||
if (SelectedItem.Value == null)
|
||||
var selected = SelectedItem.Value;
|
||||
|
||||
if (selected == null)
|
||||
return;
|
||||
|
||||
// Remove any user mods that are no longer allowed.
|
||||
UserMods.Value = UserMods.Value
|
||||
.Where(m => SelectedItem.Value.AllowedMods.Any(a => m.GetType() == a.GetType()))
|
||||
.Where(m => selected.AllowedMods.Any(a => m.GetType() == a.GetType()))
|
||||
.ToList();
|
||||
|
||||
UpdateMods();
|
||||
|
||||
Ruleset.Value = SelectedItem.Value.Ruleset.Value;
|
||||
Ruleset.Value = selected.Ruleset.Value;
|
||||
|
||||
if (!selected.AllowedMods.Any())
|
||||
{
|
||||
UserModsSection?.Hide();
|
||||
userModsSelectOverlay.Hide();
|
||||
userModsSelectOverlay.IsValidMod = _ => false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UserModsSection?.Show();
|
||||
userModsSelectOverlay.IsValidMod = m => selected.AllowedMods.Any(a => a.GetType() == m.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
private void beatmapUpdated(ValueChangedEvent<WeakReference<BeatmapSetInfo>> weakSet) => Schedule(updateWorkingBeatmap);
|
||||
@ -182,5 +237,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
if (track != null)
|
||||
track.Looping = false;
|
||||
}
|
||||
|
||||
private class UserModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ using osu.Framework.Threading;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
@ -42,9 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
[Resolved]
|
||||
private OngoingOperationTracker ongoingOperationTracker { get; set; }
|
||||
|
||||
private ModSelectOverlay userModsSelectOverlay;
|
||||
private MultiplayerMatchSettingsOverlay settingsOverlay;
|
||||
private Drawable userModsSection;
|
||||
|
||||
private readonly IBindable<bool> isConnected = new Bindable<bool>();
|
||||
|
||||
@ -154,7 +151,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
new BeatmapSelectionControl { RelativeSizeAxes = Axes.X }
|
||||
}
|
||||
},
|
||||
userModsSection = new FillFlowContainer
|
||||
UserModsSection = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
@ -175,7 +172,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
Origin = Anchor.CentreLeft,
|
||||
Width = 90,
|
||||
Text = "Select",
|
||||
Action = () => userModsSelectOverlay.Show()
|
||||
Action = ShowUserModSelect,
|
||||
},
|
||||
new ModDisplay
|
||||
{
|
||||
@ -230,19 +227,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING },
|
||||
Child = userModsSelectOverlay = new UserModSelectOverlay
|
||||
{
|
||||
SelectedMods = { BindTarget = UserMods },
|
||||
IsValidMod = _ => false
|
||||
}
|
||||
},
|
||||
settingsOverlay = new MultiplayerMatchSettingsOverlay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -269,7 +253,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
base.LoadComplete();
|
||||
|
||||
SelectedItem.BindTo(client.CurrentMatchPlayingItem);
|
||||
SelectedItem.BindValueChanged(onSelectedItemChanged, true);
|
||||
|
||||
BeatmapAvailability.BindValueChanged(updateBeatmapAvailability, true);
|
||||
UserMods.BindValueChanged(onUserModsChanged);
|
||||
@ -285,24 +268,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void onSelectedItemChanged(ValueChangedEvent<PlaylistItem> item)
|
||||
{
|
||||
if (client?.LocalUser == null)
|
||||
return;
|
||||
|
||||
if (item.NewValue?.AllowedMods.Any() != true)
|
||||
{
|
||||
userModsSection.Hide();
|
||||
userModsSelectOverlay.Hide();
|
||||
userModsSelectOverlay.IsValidMod = _ => false;
|
||||
}
|
||||
else
|
||||
{
|
||||
userModsSection.Show();
|
||||
userModsSelectOverlay.IsValidMod = m => item.NewValue.AllowedMods.Any(a => a.GetType() == m.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateMods()
|
||||
{
|
||||
if (SelectedItem.Value == null || client.LocalUser == null)
|
||||
@ -322,12 +287,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
return true;
|
||||
}
|
||||
|
||||
if (userModsSelectOverlay.State.Value == Visibility.Visible)
|
||||
{
|
||||
userModsSelectOverlay.Hide();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnBackButton();
|
||||
}
|
||||
|
||||
@ -435,9 +394,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
}
|
||||
|
||||
private class UserModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,12 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
[Resolved(typeof(Room), nameof(Room.Playlist))]
|
||||
protected BindableList<PlaylistItem> Playlist { get; private set; }
|
||||
|
||||
protected readonly Bindable<IReadOnlyList<Mod>> FreeMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||
|
||||
[CanBeNull]
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IBindable<PlaylistItem> selectedItem { get; set; }
|
||||
|
||||
private readonly Bindable<IReadOnlyList<Mod>> freeMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||
private readonly FreeModSelectOverlay freeModSelectOverlay;
|
||||
|
||||
private WorkingBeatmap initialBeatmap;
|
||||
@ -50,7 +51,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
freeModSelectOverlay = new FreeModSelectOverlay
|
||||
{
|
||||
SelectedMods = { BindTarget = freeMods },
|
||||
SelectedMods = { BindTarget = FreeMods },
|
||||
IsValidMod = IsValidFreeMod,
|
||||
};
|
||||
}
|
||||
@ -72,14 +73,14 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
// At this point, Mods contains both the required and allowed mods. For selection purposes, it should only contain the required mods.
|
||||
// Similarly, freeMods is currently empty but should only contain the allowed mods.
|
||||
Mods.Value = selectedItem?.Value?.RequiredMods.Select(m => m.CreateCopy()).ToArray() ?? Array.Empty<Mod>();
|
||||
freeMods.Value = selectedItem?.Value?.AllowedMods.Select(m => m.CreateCopy()).ToArray() ?? Array.Empty<Mod>();
|
||||
FreeMods.Value = selectedItem?.Value?.AllowedMods.Select(m => m.CreateCopy()).ToArray() ?? Array.Empty<Mod>();
|
||||
|
||||
Ruleset.BindValueChanged(onRulesetChanged);
|
||||
}
|
||||
|
||||
private void onRulesetChanged(ValueChangedEvent<RulesetInfo> ruleset)
|
||||
{
|
||||
freeMods.Value = Array.Empty<Mod>();
|
||||
FreeMods.Value = Array.Empty<Mod>();
|
||||
}
|
||||
|
||||
protected sealed override bool OnStart()
|
||||
@ -95,7 +96,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
item.RequiredMods.AddRange(Mods.Value.Select(m => m.CreateCopy()));
|
||||
|
||||
item.AllowedMods.Clear();
|
||||
item.AllowedMods.AddRange(freeMods.Value.Select(m => m.CreateCopy()));
|
||||
item.AllowedMods.AddRange(FreeMods.Value.Select(m => m.CreateCopy()));
|
||||
|
||||
SelectItem(item);
|
||||
return true;
|
||||
@ -138,7 +139,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
protected override IEnumerable<(FooterButton, OverlayContainer)> CreateFooterButtons()
|
||||
{
|
||||
var buttons = base.CreateFooterButtons().ToList();
|
||||
buttons.Insert(buttons.FindIndex(b => b.Item1 is FooterButtonMods) + 1, (new FooterButtonFreeMods { Current = freeMods }, freeModSelectOverlay));
|
||||
buttons.Insert(buttons.FindIndex(b => b.Item1 is FooterButtonMods) + 1, (new FooterButtonFreeMods { Current = FreeMods }, freeModSelectOverlay));
|
||||
return buttons;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,9 @@ using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using Footer = osu.Game.Screens.OnlinePlay.Match.Components.Footer;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
@ -143,13 +145,55 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[] { new OverlinedHeader("Leaderboard"), },
|
||||
new[]
|
||||
{
|
||||
UserModsSection = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding { Bottom = 10 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OverlinedHeader("Extra mods"),
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new PurpleTriangleButton
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Width = 90,
|
||||
Text = "Select",
|
||||
Action = ShowUserModSelect,
|
||||
},
|
||||
new ModDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
DisplayUnrankedText = false,
|
||||
Current = UserMods,
|
||||
Scale = new Vector2(0.8f),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
new OverlinedHeader("Leaderboard")
|
||||
},
|
||||
new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, },
|
||||
new Drawable[] { new OverlinedHeader("Chat"), },
|
||||
new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } }
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
|
@ -56,6 +56,9 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
|
||||
item.RequiredMods.Clear();
|
||||
item.RequiredMods.AddRange(Mods.Value.Select(m => m.CreateCopy()));
|
||||
|
||||
item.AllowedMods.Clear();
|
||||
item.AllowedMods.AddRange(FreeMods.Value.Select(m => m.CreateCopy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user