Merge branch 'master' into new-difficulty-colours

This commit is contained in:
Dean Herbert
2021-08-06 18:05:53 +09:00
committed by GitHub
23 changed files with 651 additions and 110 deletions

View File

@ -9,7 +9,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
public abstract class DisableableTabControl<T> : TabControl<T>
{
public readonly BindableBool Enabled = new BindableBool();
public readonly BindableBool Enabled = new BindableBool(true);
protected override void AddTabItem(TabItem<T> tab, bool addToDropdown = true)
{

View File

@ -0,0 +1,39 @@
// 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.Input;
using osu.Framework.Input.Bindings;
namespace osu.Game.Screens.OnlinePlay.Match.Components
{
public abstract class CreateRoomButton : PurpleTriangleButton, IKeyBindingHandler<PlatformAction>
{
[BackgroundDependencyLoader]
private void load()
{
Triangles.TriangleScale = 1.5f;
}
public bool OnPressed(PlatformAction action)
{
if (!Enabled.Value)
return false;
switch (action)
{
case PlatformAction.DocumentNew:
// might as well also handle new tab. it's a bit of an undefined flow on this screen.
case PlatformAction.TabNew:
TriggerClick();
return true;
}
return false;
}
public void OnReleased(PlatformAction action)
{
}
}
}

View File

@ -4,15 +4,17 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Match.Components
{
public abstract class MatchSettingsOverlay : FocusedOverlayContainer
public abstract class MatchSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler<GlobalAction>
{
protected const float TRANSITION_DURATION = 350;
protected const float FIELD_PADDING = 45;
@ -21,6 +23,10 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
protected override bool BlockScrollInput => false;
protected abstract OsuButton SubmitButton { get; }
protected abstract bool IsLoading { get; }
[BackgroundDependencyLoader]
private void load()
{
@ -29,6 +35,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
Add(Settings = CreateSettings());
}
protected abstract void SelectBeatmap();
protected abstract OnlinePlayComposite CreateSettings();
protected override void PopIn()
@ -41,6 +49,33 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine);
}
public bool OnPressed(GlobalAction action)
{
switch (action)
{
case GlobalAction.Select:
if (IsLoading)
return true;
if (SubmitButton.Enabled.Value)
{
SubmitButton.TriggerClick();
return true;
}
else
{
SelectBeatmap();
return true;
}
}
return false;
}
public void OnReleased(GlobalAction action)
{
}
protected class SettingsTextBox : OsuTextBox
{
[BackgroundDependencyLoader]

View File

@ -8,7 +8,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
public class CreateMultiplayerMatchButton : PurpleTriangleButton
public class CreateMultiplayerMatchButton : CreateRoomButton
{
private IBindable<bool> isConnected;
private IBindable<bool> operationInProgress;
@ -22,8 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
[BackgroundDependencyLoader]
private void load()
{
Triangles.TriangleScale = 1.5f;
Text = "Create room";
isConnected = multiplayerClient.IsConnected.GetBoundCopy();

View File

@ -47,7 +47,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
RelativeSizeAxes = Axes.X,
Height = 40,
Text = "Select beatmap",
Action = () => matchSubScreen.Push(new MultiplayerMatchSongSelect()),
Action = () =>
{
if (matchSubScreen.IsCurrentScreen())
matchSubScreen.Push(new MultiplayerMatchSongSelect());
},
Alpha = 0
}
}
@ -68,6 +72,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
}, true);
}
public void BeginSelection() => selectButton.TriggerClick();
private void updateBeatmap()
{
if (SelectedItem.Value == null)

View File

@ -28,8 +28,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay
{
private MatchSettings settings;
protected override OsuButton SubmitButton => settings.ApplyButton;
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; }
protected override bool IsLoading => ongoingOperationTracker.InProgress.Value;
protected override void SelectBeatmap() => settings.SelectBeatmap();
protected override OnlinePlayComposite CreateSettings()
=> new MatchSettings
=> settings = new MatchSettings
{
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Y,
@ -54,6 +65,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private LoadingLayer loadingLayer;
private BeatmapSelectionControl initialBeatmapControl;
public void SelectBeatmap() => initialBeatmapControl.BeginSelection();
[Resolved]
private IRoomManager manager { get; set; }
@ -149,7 +162,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
},
new Section("Game type")
{
Alpha = disabled_alpha,
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
@ -161,7 +173,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
TypePicker = new MatchTypePicker
{
RelativeSizeAxes = Axes.X,
Enabled = { Value = false }
},
typeLabel = new OsuSpriteText
{
@ -305,7 +316,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
// Otherwise, update the room directly in preparation for it to be submitted to the API on match creation.
if (client.Room != null)
{
client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text).ContinueWith(t => Schedule(() =>
client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text, matchType: TypePicker.Current.Value).ContinueWith(t => Schedule(() =>
{
if (t.IsCompletedSuccessfully)
onSuccess(currentRoom.Value);

View File

@ -58,7 +58,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
new Room
{
Name = { Value = $"{API.LocalUser}'s awesome room" },
Category = { Value = RoomCategory.Realtime }
Category = { Value = RoomCategory.Realtime },
Type = { Value = MatchType.HeadToHead },
};
protected override string ScreenTitle => "Multiplayer";

View File

@ -37,6 +37,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
private RulesetStore rulesets { get; set; }
private SpriteIcon crown;
private OsuSpriteText userRankText;
private ModDisplay userModsDisplay;
private StateDisplay userStateDisplay;
@ -56,99 +57,108 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
var backgroundColour = Color4Extensions.FromHex("#33413C");
InternalChildren = new Drawable[]
InternalChild = new GridContainer
{
crown = new SpriteIcon
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.Solid.Crown,
Size = new Vector2(14),
Colour = Color4Extensions.FromHex("#F7E65D"),
Alpha = 0
new Dimension(GridSizeMode.Absolute, 18),
new Dimension(GridSizeMode.AutoSize),
new Dimension()
},
new Container
Content = new[]
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = 24 },
Child = new Container
new Drawable[]
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 5,
Children = new Drawable[]
crown = new SpriteIcon
{
new Box
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.Solid.Crown,
Size = new Vector2(14),
Colour = Color4Extensions.FromHex("#F7E65D"),
Alpha = 0
},
new TeamDisplay(user),
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 5,
Children = new Drawable[]
{
RelativeSizeAxes = Axes.Both,
Colour = backgroundColour
},
new UserCoverBackground
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both,
Width = 0.75f,
User = user,
Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f))
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Spacing = new Vector2(10),
Direction = FillDirection.Horizontal,
Children = new Drawable[]
new Box
{
new UpdateableAvatar
RelativeSizeAxes = Axes.Both,
Colour = backgroundColour
},
new UserCoverBackground
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both,
Width = 0.75f,
User = user,
Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f))
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Spacing = new Vector2(10),
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
User = user
},
new UpdateableFlag
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Size = new Vector2(30, 20),
Country = user?.Country
},
new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18),
Text = user?.Username
},
userRankText = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 14),
new UpdateableAvatar
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
User = user
},
new UpdateableFlag
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Size = new Vector2(30, 20),
Country = user?.Country
},
new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18),
Text = user?.Username
},
userRankText = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 14),
}
}
}
},
new Container
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Right = 70 },
Child = userModsDisplay = new ModDisplay
},
new Container
{
Scale = new Vector2(0.5f),
ExpansionMode = ExpansionMode.AlwaysContracted,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Right = 70 },
Child = userModsDisplay = new ModDisplay
{
Scale = new Vector2(0.5f),
ExpansionMode = ExpansionMode.AlwaysContracted,
}
},
userStateDisplay = new StateDisplay
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 10 },
}
},
userStateDisplay = new StateDisplay
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 10 },
}
}
}
},
}
};
}

View File

@ -0,0 +1,134 @@
// 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.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
using osu.Game.Users;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
{
internal class TeamDisplay : MultiplayerRoomComposite
{
private readonly User user;
private Drawable box;
[Resolved]
private OsuColour colours { get; set; }
[Resolved]
private MultiplayerClient client { get; set; }
public TeamDisplay(User user)
{
this.user = user;
RelativeSizeAxes = Axes.Y;
Width = 15;
Margin = new MarginPadding { Horizontal = 3 };
Alpha = 0;
Scale = new Vector2(0, 1);
}
[BackgroundDependencyLoader]
private void load()
{
box = new Container
{
RelativeSizeAxes = Axes.Both,
CornerRadius = 5,
Masking = true,
Scale = new Vector2(0, 1),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Child = new Box
{
Colour = Color4.White,
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
};
if (user.Id == client.LocalUser?.UserID)
{
InternalChild = new OsuClickableContainer
{
RelativeSizeAxes = Axes.Both,
TooltipText = "Change team",
Action = changeTeam,
Child = box
};
}
else
{
InternalChild = box;
}
}
private void changeTeam()
{
client.SendMatchRequest(new ChangeTeamRequest
{
TeamID = ((client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0,
});
}
private int? displayedTeam;
protected override void OnRoomUpdated()
{
base.OnRoomUpdated();
// we don't have a way of knowing when an individual user's state has updated, so just handle on RoomUpdated for now.
var userRoomState = Room?.Users.FirstOrDefault(u => u.UserID == user.Id)?.MatchState;
const double duration = 400;
int? newTeam = (userRoomState as TeamVersusUserState)?.TeamID;
if (newTeam == displayedTeam)
return;
displayedTeam = newTeam;
if (displayedTeam != null)
{
box.FadeColour(getColourForTeam(displayedTeam.Value), duration, Easing.OutQuint);
box.ScaleTo(new Vector2(box.Scale.X < 0 ? 1 : -1, 1), duration, Easing.OutQuint);
this.ScaleTo(Vector2.One, duration, Easing.OutQuint);
this.FadeIn(duration);
}
else
{
this.ScaleTo(new Vector2(0, 1), duration, Easing.OutQuint);
this.FadeOut(duration);
}
}
private ColourInfo getColourForTeam(int id)
{
switch (id)
{
default:
return colours.Red;
case 1:
return colours.Blue;
}
}
}
}

View File

@ -6,13 +6,11 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
namespace osu.Game.Screens.OnlinePlay.Playlists
{
public class CreatePlaylistsRoomButton : PurpleTriangleButton
public class CreatePlaylistsRoomButton : CreateRoomButton
{
[BackgroundDependencyLoader]
private void load()
{
Triangles.TriangleScale = 1.5f;
Text = "Create playlist";
}
}

View File

@ -48,7 +48,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
protected override Room CreateNewRoom()
{
return new Room { Name = { Value = $"{API.LocalUser}'s awesome playlist" } };
return new Room
{
Name = { Value = $"{API.LocalUser}'s awesome playlist" },
Type = { Value = MatchType.Playlists }
};
}
protected override string ScreenTitle => "Playlists";

View File

@ -26,8 +26,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{
public Action EditPlaylist;
private MatchSettings settings;
protected override OsuButton SubmitButton => settings.ApplyButton;
protected override bool IsLoading => settings.IsLoading; // should probably be replaced with an OngoingOperationTracker.
protected override void SelectBeatmap() => settings.SelectBeatmap();
protected override OnlinePlayComposite CreateSettings()
=> new MatchSettings
=> settings = new MatchSettings
{
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Y,
@ -45,12 +53,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
public RoomAvailabilityPicker AvailabilityPicker;
public TriangleButton ApplyButton;
public bool IsLoading => loadingLayer.State.Value == Visibility.Visible;
public OsuSpriteText ErrorText;
private LoadingLayer loadingLayer;
private DrawableRoomPlaylist playlist;
private OsuSpriteText playlistLength;
private PurpleTriangleButton editPlaylistButton;
[Resolved(CanBeNull = true)]
private IRoomManager manager { get; set; }
@ -199,7 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
},
new Drawable[]
{
new PurpleTriangleButton
editPlaylistButton = new PurpleTriangleButton
{
RelativeSizeAxes = Axes.X,
Height = 40,
@ -292,6 +304,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
ApplyButton.Enabled.Value = hasValidSettings;
}
public void SelectBeatmap() => editPlaylistButton.TriggerClick();
private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) =>
playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}";

View File

@ -230,7 +230,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
settingsOverlay = new PlaylistsMatchSettingsOverlay
{
RelativeSizeAxes = Axes.Both,
EditPlaylist = () => this.Push(new PlaylistsSongSelect()),
EditPlaylist = () =>
{
if (this.IsCurrentScreen())
this.Push(new PlaylistsSongSelect());
},
State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden }
}
});