mirror of
https://github.com/ppy/osu.git
synced 2026-05-18 16:10:48 +08:00
Merge pull request #35542 from smoogipoo/mp-vote-to-skip
Implement vote-to-skip in multiplayer
This commit is contained in:
@@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
public Drawable OverlayContent => InternalChild;
|
||||
|
||||
public Drawable FadingContent => (OverlayContent as Container)?.Child;
|
||||
public new Drawable FadingContent => (OverlayContent as Container)?.Child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public partial class TestSceneMultiplayerSkipOverlay : MultiplayerTestScene
|
||||
{
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom()));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("add skip overlay", () =>
|
||||
{
|
||||
GameplayClockContainer gameplayClockContainer;
|
||||
|
||||
var working = CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo));
|
||||
|
||||
Child = gameplayClockContainer = new MasterGameplayClockContainer(working, 0)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new MultiplayerSkipOverlay(120000)
|
||||
},
|
||||
};
|
||||
|
||||
gameplayClockContainer.Start();
|
||||
});
|
||||
|
||||
AddStep("set playing state", () => MultiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Playing));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSkip()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int i2 = i;
|
||||
|
||||
AddStep($"join user {i2}", () =>
|
||||
{
|
||||
MultiplayerClient.AddUser(new APIUser
|
||||
{
|
||||
Id = i2,
|
||||
Username = $"User {i2}"
|
||||
});
|
||||
|
||||
MultiplayerClient.ChangeUserState(i2, MultiplayerUserState.Playing);
|
||||
});
|
||||
}
|
||||
|
||||
AddStep("local user votes", () => MultiplayerClient.VoteToSkipIntro().WaitSafely());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int i2 = i;
|
||||
AddStep($"user {i2} votes", () => MultiplayerClient.UserVoteToSkipIntro(i2).WaitSafely());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,5 +149,15 @@ namespace osu.Game.Online.Multiplayer
|
||||
/// </summary>
|
||||
/// <param name="item">The changed item.</param>
|
||||
Task PlaylistItemChanged(MultiplayerPlaylistItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Signals that a user has requested to skip the beatmap intro.
|
||||
/// </summary>
|
||||
Task UserVotedToSkipIntro(int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Signals that the vote to skip the beatmap intro has passed.
|
||||
/// </summary>
|
||||
Task VoteToSkipIntroPassed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,11 @@ namespace osu.Game.Online.Multiplayer
|
||||
/// <param name="playlistItemId">The item to remove.</param>
|
||||
Task RemovePlaylistItem(long playlistItemId);
|
||||
|
||||
/// <summary>
|
||||
/// Votes to skip the beatmap intro.
|
||||
/// </summary>
|
||||
Task VoteToSkipIntro();
|
||||
|
||||
/// <summary>
|
||||
/// Invites a player to the current room.
|
||||
/// </summary>
|
||||
|
||||
@@ -131,6 +131,9 @@ namespace osu.Game.Online.Multiplayer
|
||||
public event Action<int, long>? MatchmakingItemDeselected;
|
||||
public event Action<MatchRoomState>? MatchRoomStateChanged;
|
||||
|
||||
public event Action<int>? UserVotedToSkipIntro;
|
||||
public event Action? VoteToSkipIntroPassed;
|
||||
|
||||
public event Action<MultiplayerRoomUser, BeatmapAvailability>? BeatmapAvailabilityChanged;
|
||||
|
||||
/// <summary>
|
||||
@@ -495,6 +498,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
|
||||
public abstract Task RemovePlaylistItem(long playlistItemId);
|
||||
|
||||
public abstract Task VoteToSkipIntro();
|
||||
|
||||
Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state)
|
||||
{
|
||||
handleRoomRequest(() =>
|
||||
@@ -849,6 +854,10 @@ namespace osu.Game.Online.Multiplayer
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
foreach (var user in Room.Users)
|
||||
user.VotedToSkipIntro = false;
|
||||
|
||||
GameplayStarted?.Invoke();
|
||||
});
|
||||
|
||||
@@ -919,6 +928,37 @@ namespace osu.Game.Online.Multiplayer
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
Task IMultiplayerClient.UserVotedToSkipIntro(int userId)
|
||||
{
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
var user = Room.Users.SingleOrDefault(u => u.UserID == userId);
|
||||
|
||||
// TODO: user should NEVER be null here, see https://github.com/ppy/osu/issues/17713.
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
user.VotedToSkipIntro = true;
|
||||
|
||||
UserVotedToSkipIntro?.Invoke(userId);
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
Task IMultiplayerClient.VoteToSkipIntroPassed()
|
||||
{
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
VoteToSkipIntroPassed?.Invoke();
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the <see cref="APIUser"/> for a given collection of <see cref="MultiplayerRoomUser"/>s.
|
||||
/// </summary>
|
||||
|
||||
@@ -49,6 +49,12 @@ namespace osu.Game.Online.Multiplayer
|
||||
[Key(6)]
|
||||
public int? BeatmapId;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this user voted to skip the beatmap intro.
|
||||
/// </summary>
|
||||
[Key(7)]
|
||||
public bool VotedToSkipIntro;
|
||||
|
||||
[IgnoreMember]
|
||||
public APIUser? User { get; set; }
|
||||
|
||||
|
||||
@@ -70,7 +70,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
connection.On<MultiplayerPlaylistItem>(nameof(IMultiplayerClient.PlaylistItemAdded), ((IMultiplayerClient)this).PlaylistItemAdded);
|
||||
connection.On<long>(nameof(IMultiplayerClient.PlaylistItemRemoved), ((IMultiplayerClient)this).PlaylistItemRemoved);
|
||||
connection.On<MultiplayerPlaylistItem>(nameof(IMultiplayerClient.PlaylistItemChanged), ((IMultiplayerClient)this).PlaylistItemChanged);
|
||||
connection.On(nameof(IStatefulUserHubClient.DisconnectRequested), ((IMultiplayerClient)this).DisconnectRequested);
|
||||
connection.On<int>(nameof(IMultiplayerClient.UserVotedToSkipIntro), ((IMultiplayerClient)this).UserVotedToSkipIntro);
|
||||
connection.On(nameof(IMultiplayerClient.VoteToSkipIntroPassed), ((IMultiplayerClient)this).VoteToSkipIntroPassed);
|
||||
|
||||
connection.On(nameof(IMatchmakingClient.MatchmakingQueueJoined), ((IMatchmakingClient)this).MatchmakingQueueJoined);
|
||||
connection.On(nameof(IMatchmakingClient.MatchmakingQueueLeft), ((IMatchmakingClient)this).MatchmakingQueueLeft);
|
||||
@@ -80,6 +81,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
connection.On<MatchmakingQueueStatus>(nameof(IMatchmakingClient.MatchmakingQueueStatusChanged), ((IMatchmakingClient)this).MatchmakingQueueStatusChanged);
|
||||
connection.On<int, long>(nameof(IMatchmakingClient.MatchmakingItemSelected), ((IMatchmakingClient)this).MatchmakingItemSelected);
|
||||
connection.On<int, long>(nameof(IMatchmakingClient.MatchmakingItemDeselected), ((IMatchmakingClient)this).MatchmakingItemDeselected);
|
||||
|
||||
connection.On(nameof(IStatefulUserHubClient.DisconnectRequested), ((IMultiplayerClient)this).DisconnectRequested);
|
||||
};
|
||||
|
||||
IsConnected.BindTo(connector.IsConnected);
|
||||
@@ -312,6 +315,16 @@ namespace osu.Game.Online.Multiplayer
|
||||
return connection.InvokeAsync(nameof(IMultiplayerServer.RemovePlaylistItem), playlistItemId);
|
||||
}
|
||||
|
||||
public override Task VoteToSkipIntro()
|
||||
{
|
||||
if (!IsConnected.Value)
|
||||
return Task.CompletedTask;
|
||||
|
||||
Debug.Assert(connection != null);
|
||||
|
||||
return connection.InvokeAsync(nameof(IMultiplayerServer.VoteToSkipIntro));
|
||||
}
|
||||
|
||||
public override Task DisconnectInternal()
|
||||
{
|
||||
if (connector == null)
|
||||
|
||||
@@ -56,7 +56,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
AllowPause = false,
|
||||
AllowRestart = false,
|
||||
AllowSkipping = room.AutoSkip,
|
||||
AutomaticallySkipIntro = room.AutoSkip,
|
||||
ShowLeaderboard = true,
|
||||
})
|
||||
@@ -121,6 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
client.GameplayStarted += onGameplayStarted;
|
||||
client.ResultsReady += onResultsReady;
|
||||
client.VoteToSkipIntroPassed += onVoteToSkipIntroPassed;
|
||||
|
||||
ScoreProcessor.HasCompleted.BindValueChanged(_ =>
|
||||
{
|
||||
@@ -148,6 +148,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
Debug.Assert(client.Room != null);
|
||||
}
|
||||
|
||||
protected override SkipOverlay CreateSkipOverlay(double startTime) => new MultiplayerSkipOverlay(startTime);
|
||||
|
||||
protected override void StartGameplay()
|
||||
{
|
||||
// We can enter this screen one of two ways:
|
||||
@@ -219,6 +221,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
await Task.WhenAny(resultsReady.Task, Task.Delay(TimeSpan.FromSeconds(60))).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override void RequestIntroSkip()
|
||||
{
|
||||
// If the room is set up such that the intro is automatically skipped, there's no need to vote on it.
|
||||
if (Configuration.AutomaticallySkipIntro)
|
||||
{
|
||||
base.RequestIntroSkip();
|
||||
return;
|
||||
}
|
||||
|
||||
// No base call because we aren't skipping yet.
|
||||
client.VoteToSkipIntro().FireAndForget();
|
||||
}
|
||||
|
||||
private void onVoteToSkipIntroPassed()
|
||||
{
|
||||
Schedule(() => PerformIntroSkip(true));
|
||||
}
|
||||
|
||||
protected override ResultsScreen CreateResults(ScoreInfo score)
|
||||
{
|
||||
Debug.Assert(Room.RoomID != null);
|
||||
@@ -242,6 +262,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
client.GameplayStarted -= onGameplayStarted;
|
||||
client.ResultsReady -= onResultsReady;
|
||||
client.VoteToSkipIntroPassed -= onVoteToSkipIntroPassed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
public partial class MultiplayerSkipOverlay : SkipOverlay
|
||||
{
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; } = null!;
|
||||
|
||||
private Drawable votedIcon = null!;
|
||||
private OsuSpriteText countText = null!;
|
||||
|
||||
public MultiplayerSkipOverlay(double startTime)
|
||||
: base(startTime)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
FadingContent.AddRange(
|
||||
[
|
||||
votedIcon = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Position = new Vector2(50, 0),
|
||||
Size = new Vector2(20),
|
||||
Alpha = 0,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Green
|
||||
},
|
||||
new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.5f),
|
||||
Icon = FontAwesome.Solid.Check
|
||||
}
|
||||
}
|
||||
},
|
||||
countText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.X,
|
||||
Position = new Vector2(0.75f, 0),
|
||||
Font = OsuFont.Default.With(size: 36, weight: FontWeight.Bold)
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
client.UserLeft += onUserLeft;
|
||||
client.UserStateChanged += onUserStateChanged;
|
||||
client.UserVotedToSkipIntro += onUserVotedToSkipIntro;
|
||||
|
||||
updateText();
|
||||
}
|
||||
|
||||
private void onUserLeft(MultiplayerRoomUser user)
|
||||
{
|
||||
Schedule(updateText);
|
||||
}
|
||||
|
||||
private void onUserStateChanged(MultiplayerRoomUser user, MultiplayerUserState state)
|
||||
{
|
||||
Schedule(updateText);
|
||||
}
|
||||
|
||||
private void onUserVotedToSkipIntro(int userId) => Schedule(() =>
|
||||
{
|
||||
updateText();
|
||||
|
||||
countText.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine);
|
||||
|
||||
if (userId == client.LocalUser?.UserID)
|
||||
{
|
||||
votedIcon.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine);
|
||||
votedIcon.FadeInFromZero(100);
|
||||
}
|
||||
});
|
||||
|
||||
private void updateText()
|
||||
{
|
||||
if (client.Room == null || client.Room.Settings.AutoSkip)
|
||||
return;
|
||||
|
||||
int countTotal = client.Room.Users.Count(u => u.State == MultiplayerUserState.Playing);
|
||||
int countSkipped = client.Room.Users.Count(u => u.State == MultiplayerUserState.Playing && u.VotedToSkipIntro);
|
||||
int countRequired = countTotal / 2 + 1;
|
||||
|
||||
countText.Text = $"{Math.Min(countRequired, countSkipped)} / {countRequired}";
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (client.IsNotNull())
|
||||
{
|
||||
client.UserLeft -= onUserLeft;
|
||||
client.UserStateChanged -= onUserStateChanged;
|
||||
client.UserVotedToSkipIntro -= onUserVotedToSkipIntro;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,14 +115,15 @@ namespace osu.Game.Screens.Play
|
||||
/// <summary>
|
||||
/// Skip forward to the next valid skip point.
|
||||
/// </summary>
|
||||
public void Skip()
|
||||
/// <param name="fullLength"><c>true</c> to skip as close to gameplay as possible, or <c>false</c> to skip only to the next valid skip point.</param>
|
||||
public void Skip(bool fullLength = false)
|
||||
{
|
||||
if (GameplayClock.CurrentTime > GameplayStartTime - MINIMUM_SKIP_TIME)
|
||||
return;
|
||||
|
||||
double skipTarget = GameplayStartTime - MINIMUM_SKIP_TIME;
|
||||
|
||||
if (StartTime < -10000 && GameplayClock.CurrentTime < 0 && skipTarget > 6000)
|
||||
if (!fullLength && StartTime < -10000 && GameplayClock.CurrentTime < 0 && skipTarget > 6000)
|
||||
// double skip exception for storyboards with very long intros
|
||||
skipTarget = 0;
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
private BreakTracker breakTracker;
|
||||
|
||||
private SkipOverlay skipIntroOverlay;
|
||||
protected SkipOverlay SkipIntroOverlay { get; private set; }
|
||||
private SkipOverlay skipOutroOverlay;
|
||||
|
||||
protected ScoreProcessor ScoreProcessor { get; private set; }
|
||||
@@ -500,10 +500,10 @@ namespace osu.Game.Screens.Play
|
||||
},
|
||||
// display the cursor above some HUD elements.
|
||||
DrawableRuleset.Cursor?.CreateProxy() ?? new Container(),
|
||||
skipIntroOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime)
|
||||
SkipIntroOverlay = CreateSkipOverlay(DrawableRuleset.GameplayStartTime).With(o =>
|
||||
{
|
||||
RequestSkip = performUserRequestedSkip
|
||||
},
|
||||
o.RequestSkip = RequestIntroSkip;
|
||||
}),
|
||||
skipOutroOverlay = new SkipOverlay(GameplayState.Storyboard.LatestEventTime ?? 0)
|
||||
{
|
||||
RequestSkip = () => progressToResults(false),
|
||||
@@ -522,13 +522,15 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
if (!Configuration.AllowSkipping || !DrawableRuleset.AllowGameplayOverlays)
|
||||
{
|
||||
skipIntroOverlay.Expire();
|
||||
SkipIntroOverlay.Expire();
|
||||
skipOutroOverlay.Expire();
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
protected virtual SkipOverlay CreateSkipOverlay(double startTime) => new SkipOverlay(startTime);
|
||||
|
||||
private void onBreakTimeChanged(ValueChangedEvent<bool> isBreakTime)
|
||||
{
|
||||
updateGameplayState();
|
||||
@@ -701,13 +703,22 @@ namespace osu.Game.Screens.Play
|
||||
return true;
|
||||
}
|
||||
|
||||
private void performUserRequestedSkip()
|
||||
protected virtual void RequestIntroSkip()
|
||||
{
|
||||
PerformIntroSkip();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skip forward to the next valid skip point.
|
||||
/// </summary>
|
||||
/// <param name="fullLength"><c>true</c> to skip as close to gameplay as possible, or <c>false</c> to skip only to the next valid skip point.</param>
|
||||
protected void PerformIntroSkip(bool fullLength = false)
|
||||
{
|
||||
// user requested skip
|
||||
// disable sample playback to stop currently playing samples and perform skip
|
||||
samplePlaybackDisabled.Value = true;
|
||||
|
||||
(GameplayClockContainer as MasterGameplayClockContainer)?.Skip();
|
||||
(GameplayClockContainer as MasterGameplayClockContainer)?.Skip(fullLength);
|
||||
|
||||
// return samplePlaybackDisabled.Value to what is defined by the beatmap's current state
|
||||
updateSampleDisabledState();
|
||||
@@ -1153,7 +1164,7 @@ namespace osu.Game.Screens.Play
|
||||
GameplayClockContainer.Reset(startClock: true);
|
||||
|
||||
if (Configuration.AutomaticallySkipIntro)
|
||||
skipIntroOverlay.SkipWhenReady();
|
||||
SkipIntroOverlay.SkipWhenReady();
|
||||
}
|
||||
|
||||
public override void OnSuspending(ScreenTransitionEvent e)
|
||||
|
||||
@@ -38,20 +38,21 @@ namespace osu.Game.Screens.Play
|
||||
private readonly double startTime;
|
||||
|
||||
public Action RequestSkip;
|
||||
|
||||
protected FadeContainer FadingContent { get; private set; }
|
||||
|
||||
private Button button;
|
||||
private ButtonContainer buttonContainer;
|
||||
private Circle remainingTimeBox;
|
||||
|
||||
private FadeContainer fadeContainer;
|
||||
private double displayTime;
|
||||
|
||||
private bool isClickable;
|
||||
private bool skipQueued;
|
||||
|
||||
[Resolved]
|
||||
private IGameplayClock gameplayClock { get; set; }
|
||||
|
||||
internal bool IsButtonVisible => fadeContainer.State == Visibility.Visible && buttonContainer.State.Value == Visibility.Visible;
|
||||
internal bool IsButtonVisible => FadingContent.State == Visibility.Visible && buttonContainer.State.Value == Visibility.Visible;
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
||||
|
||||
/// <summary>
|
||||
@@ -77,7 +78,7 @@ namespace osu.Game.Screens.Play
|
||||
InternalChild = buttonContainer = new ButtonContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = fadeContainer = new FadeContainer
|
||||
Child = FadingContent = new FadeContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
@@ -107,13 +108,13 @@ namespace osu.Game.Screens.Play
|
||||
public override void Hide()
|
||||
{
|
||||
base.Hide();
|
||||
fadeContainer.Hide();
|
||||
FadingContent.Hide();
|
||||
}
|
||||
|
||||
public override void Show()
|
||||
{
|
||||
base.Show();
|
||||
fadeContainer.TriggerShow();
|
||||
FadingContent.TriggerShow();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -136,7 +137,7 @@ namespace osu.Game.Screens.Play
|
||||
RequestSkip?.Invoke();
|
||||
};
|
||||
|
||||
fadeContainer.TriggerShow();
|
||||
FadingContent.TriggerShow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -183,7 +184,7 @@ namespace osu.Game.Screens.Play
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
if (isClickable && !e.HasAnyButtonPressed)
|
||||
fadeContainer.TriggerShow();
|
||||
FadingContent.TriggerShow();
|
||||
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
@@ -561,6 +561,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
public override Task RemovePlaylistItem(long playlistItemId) => RemoveUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(playlistItemId));
|
||||
|
||||
public override Task VoteToSkipIntro()
|
||||
{
|
||||
return UserVoteToSkipIntro(api.LocalUser.Value.OnlineID);
|
||||
}
|
||||
|
||||
public async Task UserVoteToSkipIntro(int userId)
|
||||
{
|
||||
await ((IMultiplayerClient)this).UserVotedToSkipIntro(userId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override Task<MultiplayerRoom> CreateRoomInternal(MultiplayerRoom room)
|
||||
{
|
||||
Room apiRoom = new Room(room)
|
||||
|
||||
Reference in New Issue
Block a user