mirror of
https://github.com/ppy/osu.git
synced 2025-01-08 06:52:59 +08:00
Merge pull request #28440 from bdach/daily-challenge/new-screen
Add minimal viable new screen for daily challenge feature
This commit is contained in:
commit
94b7148a9e
@ -0,0 +1,40 @@
|
|||||||
|
// 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 System;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
using osu.Game.Tests.Visual.OnlinePlay;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.DailyChallenge
|
||||||
|
{
|
||||||
|
public partial class TestSceneDailyChallenge : OnlinePlayTestScene
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestDailyChallenge()
|
||||||
|
{
|
||||||
|
var room = new Room
|
||||||
|
{
|
||||||
|
RoomID = { Value = 1234 },
|
||||||
|
Name = { Value = "Daily Challenge: June 4, 2024" },
|
||||||
|
Playlist =
|
||||||
|
{
|
||||||
|
new PlaylistItem(TestResources.CreateTestBeatmapSetInfo().Beatmaps.First())
|
||||||
|
{
|
||||||
|
RequiredMods = [new APIMod(new OsuModTraceable())],
|
||||||
|
AllowedMods = [new APIMod(new OsuModDoubleTime())]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
EndDate = { Value = DateTimeOffset.Now.AddHours(12) },
|
||||||
|
Category = { Value = RoomCategory.DailyChallenge }
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add room", () => API.Perform(new CreateRoomRequest(room)));
|
||||||
|
AddStep("push screen", () => LoadScreen(new Screens.OnlinePlay.DailyChallenge.DailyChallenge(room)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -644,7 +644,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("open mod overlay", () => this.ChildrenOfType<RoomSubScreen.UserModSelectButton>().Single().TriggerClick());
|
AddStep("open mod overlay", () => this.ChildrenOfType<UserModSelectButton>().Single().TriggerClick());
|
||||||
|
|
||||||
AddStep("invoke on back button", () => multiplayerComponents.OnBackButton());
|
AddStep("invoke on back button", () => multiplayerComponents.OnBackButton());
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddUntilStep("wait for join", () => RoomJoined);
|
AddUntilStep("wait for join", () => RoomJoined);
|
||||||
|
|
||||||
ClickButtonWhenEnabled<RoomSubScreen.UserModSelectButton>();
|
ClickButtonWhenEnabled<UserModSelectButton>();
|
||||||
|
|
||||||
AddUntilStep("mod select contents loaded",
|
AddUntilStep("mod select contents loaded",
|
||||||
() => this.ChildrenOfType<ModColumn>().Any() && this.ChildrenOfType<ModColumn>().All(col => col.IsLoaded && col.ItemsLoaded));
|
() => this.ChildrenOfType<ModColumn>().Any() && this.ChildrenOfType<ModColumn>().All(col => col.IsLoaded && col.ItemsLoaded));
|
||||||
@ -311,7 +311,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddUntilStep("wait for join", () => RoomJoined);
|
AddUntilStep("wait for join", () => RoomJoined);
|
||||||
|
|
||||||
ClickButtonWhenEnabled<RoomSubScreen.UserModSelectButton>();
|
ClickButtonWhenEnabled<UserModSelectButton>();
|
||||||
AddAssert("mod select shows unranked", () => screen.UserModsSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().Ranked.Value == false);
|
AddAssert("mod select shows unranked", () => screen.UserModsSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().Ranked.Value == false);
|
||||||
AddAssert("score multiplier = 1.20", () => screen.UserModsSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(1.2).Within(0.01));
|
AddAssert("score multiplier = 1.20", () => screen.UserModsSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(1.2).Within(0.01));
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Online.Rooms
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class OnlinePlayBeatmapAvailabilityTracker : CompositeComponent
|
public partial class OnlinePlayBeatmapAvailabilityTracker : CompositeComponent
|
||||||
{
|
{
|
||||||
public readonly IBindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
|
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private RealmAccess realm { get; set; } = null!;
|
private RealmAccess realm { get; set; } = null!;
|
||||||
|
@ -31,6 +31,7 @@ using osu.Game.Overlays.SkinEditor;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Backgrounds;
|
using osu.Game.Screens.Backgrounds;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
|
using osu.Game.Screens.OnlinePlay.DailyChallenge;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
@ -149,9 +150,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
OnPlaylists = () => this.Push(new Playlists()),
|
OnPlaylists = () => this.Push(new Playlists()),
|
||||||
OnDailyChallenge = room =>
|
OnDailyChallenge = room =>
|
||||||
{
|
{
|
||||||
Playlists playlistsScreen;
|
this.Push(new DailyChallenge(room));
|
||||||
this.Push(playlistsScreen = new Playlists());
|
|
||||||
playlistsScreen.Join(room);
|
|
||||||
},
|
},
|
||||||
OnExit = () =>
|
OnExit = () =>
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,8 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
|||||||
|
|
||||||
req.Success += result =>
|
req.Success += result =>
|
||||||
{
|
{
|
||||||
|
result = result.Where(r => r.Category.Value != RoomCategory.DailyChallenge).ToList();
|
||||||
|
|
||||||
foreach (var existing in RoomManager.Rooms.ToArray())
|
foreach (var existing in RoomManager.Rooms.ToArray())
|
||||||
{
|
{
|
||||||
if (result.All(r => r.RoomID.Value != existing.RoomID.Value))
|
if (result.All(r => r.RoomID.Value != existing.RoomID.Value))
|
||||||
|
376
osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs
Normal file
376
osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
// 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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Extensions.LocalisationExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Match;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||||
|
{
|
||||||
|
public partial class DailyChallenge : OsuScreen
|
||||||
|
{
|
||||||
|
private readonly Room room;
|
||||||
|
private readonly PlaylistItem playlistItem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Any mods applied by/to the local user.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Bindable<IReadOnlyList<Mod>> userMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||||
|
|
||||||
|
private OnlinePlayScreenWaveContainer waves = null!;
|
||||||
|
private MatchLeaderboard leaderboard = null!;
|
||||||
|
private RoomModSelectOverlay userModsSelectOverlay = null!;
|
||||||
|
private Sample? sampleStart;
|
||||||
|
private IDisposable? userModsSelectOverlayRegistration;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
|
||||||
|
|
||||||
|
[Cached(Type = typeof(IRoomManager))]
|
||||||
|
private RoomManager roomManager { get; set; }
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapManager beatmapManager { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private MusicController musicController { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IOverlayManager? overlayManager { get; set; }
|
||||||
|
|
||||||
|
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
||||||
|
|
||||||
|
public DailyChallenge(Room room)
|
||||||
|
{
|
||||||
|
this.room = room;
|
||||||
|
playlistItem = room.Playlist.Single();
|
||||||
|
roomManager = new RoomManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
|
{
|
||||||
|
return new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent))
|
||||||
|
{
|
||||||
|
Model = { Value = room }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(AudioManager audio)
|
||||||
|
{
|
||||||
|
sampleStart = audio.Samples.Get(@"SongSelect/confirm-selection");
|
||||||
|
|
||||||
|
FillFlowContainer footerButtons;
|
||||||
|
|
||||||
|
InternalChild = waves = new OnlinePlayScreenWaveContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
roomManager,
|
||||||
|
beatmapAvailabilityTracker,
|
||||||
|
new ScreenStack(new RoomBackgroundScreen(playlistItem))
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new Header(ButtonSystemStrings.DailyChallenge.ToSentence(), null),
|
||||||
|
new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Horizontal = WaveOverlayContainer.WIDTH_PADDING,
|
||||||
|
Top = Header.HEIGHT,
|
||||||
|
},
|
||||||
|
RowDimensions =
|
||||||
|
[
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 10),
|
||||||
|
new Dimension(),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 30),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 50)
|
||||||
|
],
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
new DrawableRoomPlaylistItem(playlistItem)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AllowReordering = false,
|
||||||
|
Scale = new Vector2(1.4f),
|
||||||
|
Width = 1 / 1.4f,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 10,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex(@"3e3a44") // Temporary.
|
||||||
|
},
|
||||||
|
new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding(10),
|
||||||
|
ColumnDimensions =
|
||||||
|
[
|
||||||
|
new Dimension(),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 10),
|
||||||
|
new Dimension(),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 10),
|
||||||
|
new Dimension()
|
||||||
|
],
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable?[]
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
// Middle column (leaderboard)
|
||||||
|
new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
new OverlinedHeader("Leaderboard")
|
||||||
|
},
|
||||||
|
[leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }],
|
||||||
|
},
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
new Dimension(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Spacer
|
||||||
|
null,
|
||||||
|
// Main right column
|
||||||
|
new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
new OverlinedHeader("Chat")
|
||||||
|
},
|
||||||
|
[new MatchChatDisplay(room) { RelativeSizeAxes = Axes.Both }]
|
||||||
|
},
|
||||||
|
RowDimensions =
|
||||||
|
[
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
new Dimension()
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Horizontal = -WaveOverlayContainer.WIDTH_PADDING,
|
||||||
|
},
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex(@"28242d") // Temporary.
|
||||||
|
},
|
||||||
|
footerButtons = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Padding = new MarginPadding(5),
|
||||||
|
Spacing = new Vector2(10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new PlaylistsReadyButton
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Size = new Vector2(250, 1),
|
||||||
|
Action = startPlay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LoadComponent(userModsSelectOverlay = new RoomModSelectOverlay
|
||||||
|
{
|
||||||
|
SelectedMods = { BindTarget = userMods },
|
||||||
|
IsValidMod = _ => false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (playlistItem.AllowedMods.Any())
|
||||||
|
{
|
||||||
|
footerButtons.Insert(-1, new UserModSelectButton
|
||||||
|
{
|
||||||
|
Text = "Free mods",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Size = new Vector2(250, 1),
|
||||||
|
Action = () => userModsSelectOverlay.Show(),
|
||||||
|
});
|
||||||
|
|
||||||
|
var rulesetInstance = rulesets.GetRuleset(playlistItem.RulesetID)!.CreateInstance();
|
||||||
|
var allowedMods = playlistItem.AllowedMods.Select(m => m.ToMod(rulesetInstance));
|
||||||
|
userModsSelectOverlay.IsValidMod = m => allowedMods.Any(a => a.GetType() == m.GetType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
beatmapAvailabilityTracker.SelectedItem.Value = playlistItem;
|
||||||
|
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => trySetDailyChallengeBeatmap(), true);
|
||||||
|
|
||||||
|
userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(userModsSelectOverlay);
|
||||||
|
userModsSelectOverlay.SelectedItem.Value = playlistItem;
|
||||||
|
userMods.BindValueChanged(_ => Scheduler.AddOnce(updateMods), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trySetDailyChallengeBeatmap()
|
||||||
|
{
|
||||||
|
var beatmap = beatmapManager.QueryBeatmap(b => b.OnlineID == playlistItem.Beatmap.OnlineID);
|
||||||
|
Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmap); // this will gracefully fall back to dummy beatmap if missing locally.
|
||||||
|
Ruleset.Value = rulesets.GetRuleset(playlistItem.RulesetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnEntering(ScreenTransitionEvent e)
|
||||||
|
{
|
||||||
|
base.OnEntering(e);
|
||||||
|
|
||||||
|
waves.Show();
|
||||||
|
roomManager.JoinRoom(room);
|
||||||
|
applyLoopingToTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnResuming(ScreenTransitionEvent e)
|
||||||
|
{
|
||||||
|
base.OnResuming(e);
|
||||||
|
applyLoopingToTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnSuspending(ScreenTransitionEvent e)
|
||||||
|
{
|
||||||
|
base.OnSuspending(e);
|
||||||
|
|
||||||
|
userModsSelectOverlay.Hide();
|
||||||
|
cancelTrackLooping();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnExiting(ScreenExitEvent e)
|
||||||
|
{
|
||||||
|
waves.Hide();
|
||||||
|
userModsSelectOverlay.Hide();
|
||||||
|
cancelTrackLooping();
|
||||||
|
this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
|
||||||
|
|
||||||
|
roomManager.PartRoom();
|
||||||
|
|
||||||
|
return base.OnExiting(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyLoopingToTrack()
|
||||||
|
{
|
||||||
|
if (!this.IsCurrentScreen())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var track = Beatmap.Value?.Track;
|
||||||
|
|
||||||
|
if (track != null)
|
||||||
|
{
|
||||||
|
Beatmap.Value?.PrepareTrackForPreview(true);
|
||||||
|
musicController.EnsurePlayingSomething();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelTrackLooping()
|
||||||
|
{
|
||||||
|
var track = Beatmap.Value?.Track;
|
||||||
|
|
||||||
|
if (track != null)
|
||||||
|
track.Looping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMods()
|
||||||
|
{
|
||||||
|
if (!this.IsCurrentScreen())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Mods.Value = userMods.Value.Concat(playlistItem.RequiredMods.Select(m => m.ToMod(Ruleset.Value.CreateInstance()))).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startPlay()
|
||||||
|
{
|
||||||
|
sampleStart?.Play();
|
||||||
|
this.Push(new PlayerLoader(() => new PlaylistsPlayer(room, playlistItem)
|
||||||
|
{
|
||||||
|
Exited = () => leaderboard.RefetchScores()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
userModsSelectOverlayRegistration?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,11 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
@ -20,10 +18,10 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
{
|
{
|
||||||
public const float HEIGHT = 80;
|
public const float HEIGHT = 80;
|
||||||
|
|
||||||
private readonly ScreenStack stack;
|
private readonly ScreenStack? stack;
|
||||||
private readonly MultiHeaderTitle title;
|
private readonly MultiHeaderTitle title;
|
||||||
|
|
||||||
public Header(string mainTitle, ScreenStack stack)
|
public Header(LocalisableString mainTitle, ScreenStack? stack)
|
||||||
{
|
{
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
|
|
||||||
@ -37,12 +35,15 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
};
|
};
|
||||||
|
|
||||||
// unnecessary to unbind these as this header has the same lifetime as the screen stack we are attaching to.
|
if (stack != null)
|
||||||
stack.ScreenPushed += (_, _) => updateSubScreenTitle();
|
{
|
||||||
stack.ScreenExited += (_, _) => updateSubScreenTitle();
|
// unnecessary to unbind these as this header has the same lifetime as the screen stack we are attaching to.
|
||||||
|
stack.ScreenPushed += (_, _) => updateSubScreenTitle();
|
||||||
|
stack.ScreenExited += (_, _) => updateSubScreenTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSubScreenTitle() => title.Screen = stack.CurrentScreen as IOnlinePlaySubScreen;
|
private void updateSubScreenTitle() => title.Screen = stack?.CurrentScreen as IOnlinePlaySubScreen;
|
||||||
|
|
||||||
private partial class MultiHeaderTitle : CompositeDrawable
|
private partial class MultiHeaderTitle : CompositeDrawable
|
||||||
{
|
{
|
||||||
@ -51,13 +52,16 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
private readonly OsuSpriteText dot;
|
private readonly OsuSpriteText dot;
|
||||||
private readonly OsuSpriteText pageTitle;
|
private readonly OsuSpriteText pageTitle;
|
||||||
|
|
||||||
[CanBeNull]
|
public IOnlinePlaySubScreen? Screen
|
||||||
public IOnlinePlaySubScreen Screen
|
|
||||||
{
|
{
|
||||||
set => pageTitle.Text = value?.ShortTitle.Titleize() ?? string.Empty;
|
set
|
||||||
|
{
|
||||||
|
pageTitle.Text = value?.ShortTitle.Titleize() ?? default(LocalisableString);
|
||||||
|
dot.Alpha = pageTitle.Text == default ? 0 : 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiHeaderTitle(string mainTitle)
|
public MultiHeaderTitle(LocalisableString mainTitle)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
@ -82,14 +86,14 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Font = OsuFont.TorusAlternate.With(size: 24),
|
Font = OsuFont.TorusAlternate.With(size: 24),
|
||||||
Text = "·"
|
Text = "·",
|
||||||
|
Alpha = 0,
|
||||||
},
|
},
|
||||||
pageTitle = new OsuSpriteText
|
pageTitle = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Font = OsuFont.TorusAlternate.With(size: 24),
|
Font = OsuFont.TorusAlternate.With(size: 24),
|
||||||
Text = "Lounge"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -16,8 +16,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
|||||||
{
|
{
|
||||||
public partial class RoomModSelectOverlay : UserModSelectOverlay
|
public partial class RoomModSelectOverlay : UserModSelectOverlay
|
||||||
{
|
{
|
||||||
[Resolved]
|
public Bindable<PlaylistItem> SelectedItem { get; } = new Bindable<PlaylistItem>();
|
||||||
private IBindable<PlaylistItem> selectedItem { get; set; } = null!;
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private RulesetStore rulesets { get; set; } = null!;
|
private RulesetStore rulesets { get; set; } = null!;
|
||||||
@ -33,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
selectedItem.BindValueChanged(v =>
|
SelectedItem.BindValueChanged(v =>
|
||||||
{
|
{
|
||||||
roomRequiredMods.Clear();
|
roomRequiredMods.Clear();
|
||||||
|
|
||||||
|
@ -17,12 +17,9 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Input.Bindings;
|
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Input.Bindings;
|
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
@ -243,6 +240,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
|||||||
|
|
||||||
LoadComponent(UserModsSelectOverlay = new RoomModSelectOverlay
|
LoadComponent(UserModsSelectOverlay = new RoomModSelectOverlay
|
||||||
{
|
{
|
||||||
|
SelectedItem = { BindTarget = SelectedItem },
|
||||||
SelectedMods = { BindTarget = UserMods },
|
SelectedMods = { BindTarget = UserMods },
|
||||||
IsValidMod = _ => false
|
IsValidMod = _ => false
|
||||||
});
|
});
|
||||||
@ -531,22 +529,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
|||||||
/// <param name="room">The room to change the settings of.</param>
|
/// <param name="room">The room to change the settings of.</param>
|
||||||
protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room);
|
protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room);
|
||||||
|
|
||||||
public partial class UserModSelectButton : PurpleRoundedButton, IKeyBindingHandler<GlobalAction>
|
|
||||||
{
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
|
||||||
{
|
|
||||||
if (e.Action == GlobalAction.ToggleModSelection && !e.Repeat)
|
|
||||||
{
|
|
||||||
TriggerClick();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
|
27
osu.Game/Screens/OnlinePlay/Match/UserModSelectButton.cs
Normal file
27
osu.Game/Screens/OnlinePlay/Match/UserModSelectButton.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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.Input.Bindings;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Input.Bindings;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.OnlinePlay.Match
|
||||||
|
{
|
||||||
|
public partial class UserModSelectButton : PurpleRoundedButton, IKeyBindingHandler<GlobalAction>
|
||||||
|
{
|
||||||
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
|
{
|
||||||
|
if (e.Action == GlobalAction.ToggleModSelection && !e.Repeat)
|
||||||
|
{
|
||||||
|
TriggerClick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) { }
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
@ -36,7 +35,7 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
|
|
||||||
protected LoungeSubScreen Lounge { get; private set; }
|
protected LoungeSubScreen Lounge { get; private set; }
|
||||||
|
|
||||||
private MultiplayerWaveContainer waves;
|
private OnlinePlayScreenWaveContainer waves;
|
||||||
private ScreenStack screenStack;
|
private ScreenStack screenStack;
|
||||||
|
|
||||||
[Cached(Type = typeof(IRoomManager))]
|
[Cached(Type = typeof(IRoomManager))]
|
||||||
@ -63,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
InternalChild = waves = new MultiplayerWaveContainer
|
InternalChild = waves = new OnlinePlayScreenWaveContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -230,19 +229,6 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
|
|
||||||
protected abstract LoungeSubScreen CreateLounge();
|
protected abstract LoungeSubScreen CreateLounge();
|
||||||
|
|
||||||
private partial class MultiplayerWaveContainer : WaveContainer
|
|
||||||
{
|
|
||||||
protected override bool StartHidden => true;
|
|
||||||
|
|
||||||
public MultiplayerWaveContainer()
|
|
||||||
{
|
|
||||||
FirstWaveColour = Color4Extensions.FromHex(@"654d8c");
|
|
||||||
SecondWaveColour = Color4Extensions.FromHex(@"554075");
|
|
||||||
ThirdWaveColour = Color4Extensions.FromHex(@"44325e");
|
|
||||||
FourthWaveColour = Color4Extensions.FromHex(@"392850");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScreenStack IHasSubScreenStack.SubScreenStack => screenStack;
|
ScreenStack IHasSubScreenStack.SubScreenStack => screenStack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
osu.Game/Screens/OnlinePlay/OnlinePlayScreenWaveContainer.cs
Normal file
22
osu.Game/Screens/OnlinePlay/OnlinePlayScreenWaveContainer.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.OnlinePlay
|
||||||
|
{
|
||||||
|
public partial class OnlinePlayScreenWaveContainer : WaveContainer
|
||||||
|
{
|
||||||
|
protected override bool StartHidden => true;
|
||||||
|
|
||||||
|
public OnlinePlayScreenWaveContainer()
|
||||||
|
{
|
||||||
|
FirstWaveColour = Color4Extensions.FromHex(@"654d8c");
|
||||||
|
SecondWaveColour = Color4Extensions.FromHex(@"554075");
|
||||||
|
ThirdWaveColour = Color4Extensions.FromHex(@"44325e");
|
||||||
|
FourthWaveColour = Color4Extensions.FromHex(@"392850");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user