1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 07:22:55 +08:00

Add countdown button + popover

This commit is contained in:
Dan Balasescu 2022-03-17 19:05:28 +09:00
parent b76a87e6f8
commit efce471f0b
4 changed files with 246 additions and 118 deletions

View File

@ -8,6 +8,7 @@ using osu.Framework.Audio;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Framework.Utils; using osu.Framework.Utils;
@ -55,15 +56,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID
}; };
if (button != null) Child = new PopoverContainer
Remove(button); {
RelativeSizeAxes = Axes.Both,
Add(button = new MultiplayerReadyButton Child = button = new MultiplayerReadyButton
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(200, 50), Size = new Vector2(200, 50),
}); }
};
}); });
[Test] [Test]

View File

@ -9,6 +9,7 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -56,6 +57,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID, RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID,
}; };
Child = new PopoverContainer
{
RelativeSizeAxes = Axes.Both,
Child = new FillFlowContainer Child = new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
@ -75,6 +79,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
Size = new Vector2(200, 50), Size = new Vector2(200, 50),
} }
} }
}
}; };
}); });

View File

@ -12,6 +12,7 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Audio; using osu.Game.Audio;
@ -100,7 +101,10 @@ namespace osu.Game.Screens.OnlinePlay.Match
{ {
sampleStart = audio.Samples.Get(@"SongSelect/confirm-selection"); sampleStart = audio.Samples.Get(@"SongSelect/confirm-selection");
InternalChildren = new Drawable[] InternalChild = new PopoverContainer
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{ {
beatmapAvailabilityTracker, beatmapAvailabilityTracker,
new MultiplayerRoomSounds(), new MultiplayerRoomSounds(),
@ -221,6 +225,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
} }
} }
} }
}
}; };
} }

View File

@ -4,15 +4,24 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using Humanizer;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osuTK; using osuTK;
@ -30,19 +39,43 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private Sample sampleReadyAll; private Sample sampleReadyAll;
private Sample sampleUnready; private Sample sampleUnready;
private readonly ReadyButton readyButton; private readonly BindableBool enabled = new BindableBool();
private readonly CountdownButton countdownButton;
private int countReady; private int countReady;
private ScheduledDelegate readySampleDelegate; private ScheduledDelegate readySampleDelegate;
private IBindable<bool> operationInProgress; private IBindable<bool> operationInProgress;
public MultiplayerReadyButton() public MultiplayerReadyButton()
{ {
InternalChild = readyButton = new ReadyButton InternalChild = new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.AutoSize)
},
Content = new[]
{
new Drawable[]
{
new ReadyButton
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Size = Vector2.One, Size = Vector2.One,
Action = onReadyClick, Action = onReadyClick,
Enabled = { Value = true }, Enabled = { BindTarget = enabled },
},
countdownButton = new CountdownButton
{
RelativeSizeAxes = Axes.Y,
Size = new Vector2(40, 1),
Alpha = 0,
Action = startCountdown,
Enabled = { BindTarget = enabled }
}
}
}
}; };
} }
@ -111,6 +144,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
}); });
} }
private void startCountdown(TimeSpan duration)
{
}
private void endOperation() private void endOperation()
{ {
clickOperation?.Dispose(); clickOperation?.Dispose();
@ -121,7 +158,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{ {
if (Room == null) if (Room == null)
{ {
readyButton.Enabled.Value = false; enabled.Value = false;
return; return;
} }
@ -130,7 +167,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
int newCountReady = Room.Users.Count(u => u.State == MultiplayerUserState.Ready); int newCountReady = Room.Users.Count(u => u.State == MultiplayerUserState.Ready);
int newCountTotal = Room.Users.Count(u => u.State != MultiplayerUserState.Spectating); int newCountTotal = Room.Users.Count(u => u.State != MultiplayerUserState.Spectating);
readyButton.Enabled.Value = switch (localUser?.State)
{
default:
countdownButton.Alpha = 0;
break;
case MultiplayerUserState.Spectating:
case MultiplayerUserState.Ready:
countdownButton.Alpha = Room.Host?.Equals(localUser) == true ? 1 : 0;
break;
}
enabled.Value =
Room.State == MultiplayerRoomState.Open Room.State == MultiplayerRoomState.Open
&& CurrentPlaylistItem.Value?.ID == Room.Settings.PlaylistItemId && CurrentPlaylistItem.Value?.ID == Room.Settings.PlaylistItemId
&& !Room.Playlist.Single(i => i.ID == Room.Settings.PlaylistItemId).Expired && !Room.Playlist.Single(i => i.ID == Room.Settings.PlaylistItemId).Expired
@ -138,7 +187,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
// When the local user is the host and spectating the match, the "start match" state should be enabled if any users are ready. // When the local user is the host and spectating the match, the "start match" state should be enabled if any users are ready.
if (localUser?.State == MultiplayerUserState.Spectating) if (localUser?.State == MultiplayerUserState.Spectating)
readyButton.Enabled.Value &= Room.Host?.Equals(localUser) == true && newCountReady > 0; enabled.Value &= Room.Host?.Equals(localUser) == true && newCountReady > 0;
if (newCountReady == countReady) if (newCountReady == countReady)
return; return;
@ -269,5 +318,72 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
multiplayerClient.RoomUpdated -= onRoomUpdated; multiplayerClient.RoomUpdated -= onRoomUpdated;
} }
} }
public class CountdownButton : IconButton, IHasPopover
{
private static readonly TimeSpan[] available_delays =
{
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(30),
TimeSpan.FromMinutes(1),
TimeSpan.FromMinutes(2)
};
public new Action<TimeSpan> Action;
private readonly Drawable background;
public CountdownButton()
{
Icon = FontAwesome.Solid.CaretDown;
IconScale = new Vector2(0.6f);
Add(background = new Box
{
RelativeSizeAxes = Axes.Both,
Depth = float.MaxValue
});
base.Action = this.ShowPopover;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
background.Colour = colours.Green;
}
public Popover GetPopover()
{
var flow = new FillFlowContainer
{
Width = 200,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(2),
};
foreach (var duration in available_delays)
{
flow.Add(new PopoverButton
{
RelativeSizeAxes = Axes.X,
Text = $"Start match in {duration.Humanize()}",
BackgroundColour = background.Colour,
Action = () =>
{
Action(duration);
this.HidePopover();
}
});
}
return new OsuPopover { Child = flow };
}
public class PopoverButton : OsuButton
{
}
}
} }
} }