1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 23:42:55 +08:00

Merge branch 'master' into multiplayer-header-background

This commit is contained in:
Dean Herbert 2020-02-20 18:04:02 +09:00
commit e25e9b6164
41 changed files with 781 additions and 156 deletions

View File

@ -53,7 +53,7 @@
<Reference Include="Java.Interop" /> <Reference Include="Java.Interop" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.219.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.218.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.218.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -34,9 +34,14 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
foreach (var obj in Beatmap.HitObjects.OfType<CatchHitObject>()) foreach (var obj in Beatmap.HitObjects.OfType<CatchHitObject>())
{ {
obj.IndexInBeatmap = index++; obj.IndexInBeatmap = index;
foreach (var nested in obj.NestedHitObjects.OfType<CatchHitObject>())
nested.IndexInBeatmap = index;
if (obj.LastInCombo && obj.NestedHitObjects.LastOrDefault() is IHasComboInformation lastNested) if (obj.LastInCombo && obj.NestedHitObjects.LastOrDefault() is IHasComboInformation lastNested)
lastNested.LastInCombo = true; lastNested.LastInCombo = true;
index++;
} }
} }

View File

@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.Objects
public int IndexInBeatmap { get; set; } public int IndexInBeatmap { get; set; }
public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(ComboIndex % 4); public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(IndexInBeatmap % 4);
public virtual bool NewCombo { get; set; } public virtual bool NewCombo { get; set; }
@ -100,8 +100,8 @@ namespace osu.Game.Rulesets.Catch.Objects
{ {
Pear, Pear,
Grape, Grape,
Raspberry,
Pineapple, Pineapple,
Raspberry,
Banana // banananananannaanana Banana // banananananannaanana
} }
} }

View File

@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
typeof(DrawableRoomPlaylistItem) typeof(DrawableRoomPlaylistItem)
}; };
private DrawableRoomPlaylist playlist; private TestPlaylist playlist;
[Test] [Test]
public void TestNonEditableNonSelectable() public void TestNonEditableNonSelectable()
@ -211,30 +211,45 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void assertDeleteButtonVisibility(int index, bool visible) private void assertDeleteButtonVisibility(int index, bool visible)
=> AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType<IconButton>().ElementAt(2 + index * 2).Alpha > 0) == visible); => AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType<IconButton>().ElementAt(2 + index * 2).Alpha > 0) == visible);
private void createPlaylist(bool allowEdit, bool allowSelection) => AddStep("create playlist", () => private void createPlaylist(bool allowEdit, bool allowSelection)
{ {
Child = playlist = new DrawableRoomPlaylist(allowEdit, allowSelection) AddStep("create playlist", () =>
{ {
Anchor = Anchor.Centre, Child = playlist = new TestPlaylist(allowEdit, allowSelection)
Origin = Anchor.Centre,
Size = new Vector2(500, 300)
};
for (int i = 0; i < 20; i++)
{
playlist.Items.Add(new PlaylistItem
{ {
ID = i, Anchor = Anchor.Centre,
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Origin = Anchor.Centre,
Ruleset = { Value = new OsuRuleset().RulesetInfo }, Size = new Vector2(500, 300)
RequiredMods = };
for (int i = 0; i < 20; i++)
{
playlist.Items.Add(new PlaylistItem
{ {
new OsuModHardRock(), ID = i,
new OsuModDoubleTime(), Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
new OsuModAutoplay() Ruleset = { Value = new OsuRuleset().RulesetInfo },
} RequiredMods =
}); {
new OsuModHardRock(),
new OsuModDoubleTime(),
new OsuModAutoplay()
}
});
}
});
AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded));
}
private class TestPlaylist : DrawableRoomPlaylist
{
public new IReadOnlyDictionary<PlaylistItem, RearrangeableListItem<PlaylistItem>> ItemMap => base.ItemMap;
public TestPlaylist(bool allowEdit, bool allowSelection)
: base(allowEdit, allowSelection)
{
} }
}); }
} }
} }

View File

@ -1,27 +1,57 @@
// 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.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Game.Screens.Multi.Components;
using osu.Game.Screens.Multi.Match.Components;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual.Multiplayer namespace osu.Game.Tests.Visual.Multiplayer
{ {
public class TestSceneOverlinedParticipants : MultiplayerTestScene public class TestSceneOverlinedParticipants : MultiplayerTestScene
{ {
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(OverlinedParticipants),
typeof(OverlinedDisplay),
typeof(ParticipantsList)
};
protected override bool UseOnlineAPI => true; protected override bool UseOnlineAPI => true;
public TestSceneOverlinedParticipants() public TestSceneOverlinedParticipants()
{ {
Room.RoomID.Value = 7; Room.RoomID.Value = 7;
}
Add(new Container [Test]
public void TestHorizontalLayout()
{
AddStep("create component", () =>
{ {
Anchor = Anchor.Centre, Child = new OverlinedParticipants(Direction.Horizontal)
Origin = Anchor.Centre, {
Size = new Vector2(500), Anchor = Anchor.Centre,
Child = new OverlinedParticipants() Origin = Anchor.Centre,
Width = 500,
AutoSizeAxes = Axes.Y,
};
});
}
[Test]
public void TestVerticalLayout()
{
AddStep("create component", () =>
{
Child = new OverlinedParticipants(Direction.Vertical)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(500)
};
}); });
} }
} }

View File

@ -2,10 +2,9 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Components;
using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Beatmaps;
using osuTK; using osuTK;
@ -27,12 +26,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
}); });
} }
Add(new Container Add(new OverlinedPlaylist(false)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(500), Size = new Vector2(500),
Child = new OverlinedPlaylist(false)
}); });
} }
} }

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 System;
using System.Collections.Generic;
using osu.Game.Overlays;
using NUnit.Framework;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneBeatmapListingOverlay : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(BeatmapListingOverlay),
};
protected override bool UseOnlineAPI => true;
private readonly BeatmapListingOverlay overlay;
public TestSceneBeatmapListingOverlay()
{
Add(overlay = new BeatmapListingOverlay());
}
[Test]
public void TestShow()
{
AddStep("Show", overlay.Show);
}
[Test]
public void TestHide()
{
AddStep("Hide", overlay.Hide);
}
}
}

View File

@ -29,8 +29,8 @@ namespace osu.Game.Tests.Visual.Online
typeof(RankingsOverlayHeader) typeof(RankingsOverlayHeader)
}; };
[Cached] [Cached(typeof(RankingsOverlay))]
private RankingsOverlay rankingsOverlay; private readonly RankingsOverlay rankingsOverlay;
private readonly Bindable<Country> countryBindable = new Bindable<Country>(); private readonly Bindable<Country> countryBindable = new Bindable<Country>();
private readonly Bindable<RankingsScope> scope = new Bindable<RankingsScope>(); private readonly Bindable<RankingsScope> scope = new Bindable<RankingsScope>();

View File

@ -195,6 +195,29 @@ namespace osu.Game.Tests.Visual.Online
Position = 1337, Position = 1337,
}; };
var myBestScoreWithNullPosition = new APILegacyUserTopScoreInfo
{
Score = new APILegacyScoreInfo
{
User = new User
{
Id = 7151382,
Username = @"Mayuri Hana",
Country = new Country
{
FullName = @"Thailand",
FlagName = @"TH",
},
},
Rank = ScoreRank.D,
PP = 160,
MaxCombo = 1234,
TotalScore = 123456,
Accuracy = 0.6543,
},
Position = null,
};
var oneScore = new APILegacyScores var oneScore = new APILegacyScores
{ {
Scores = new List<APILegacyScoreInfo> Scores = new List<APILegacyScoreInfo>
@ -250,6 +273,12 @@ namespace osu.Game.Tests.Visual.Online
allScores.UserScore = myBestScore; allScores.UserScore = myBestScore;
scoresContainer.Scores = allScores; scoresContainer.Scores = allScores;
}); });
AddStep("Load scores with null my best position", () =>
{
allScores.UserScore = myBestScoreWithNullPosition;
scoresContainer.Scores = allScores;
});
} }
private class TestScoresContainer : ScoresContainer private class TestScoresContainer : ScoresContainer

View File

@ -59,6 +59,33 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected)); AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected));
foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus)))
AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); AddStep($"{status} beatmap", () => showBeatmapWithStatus(status));
AddStep("null personal best position", showPersonalBestWithNullPosition);
}
private void showPersonalBestWithNullPosition()
{
leaderboard.TopScore = new APILegacyUserTopScoreInfo
{
Position = null,
Score = new APILegacyScoreInfo
{
Rank = ScoreRank.XH,
Accuracy = 1,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new[] { new OsuModHidden().Acronym, new OsuModHardRock().Acronym, },
User = new User
{
Id = 6602580,
Username = @"waaiiru",
Country = new Country
{
FullName = @"Spain",
FlagName = @"ES",
},
},
}
};
} }
private void showPersonalBest() private void showPersonalBest()

View File

@ -51,6 +51,9 @@ namespace osu.Game.Beatmaps
[NotMapped] [NotMapped]
public BeatmapOnlineInfo OnlineInfo { get; set; } public BeatmapOnlineInfo OnlineInfo { get; set; }
[NotMapped]
public int? MaxCombo { get; set; }
/// <summary> /// <summary>
/// The playable length in milliseconds of this beatmap. /// The playable length in milliseconds of this beatmap.
/// </summary> /// </summary>

View File

@ -14,6 +14,9 @@ namespace osu.Game.Graphics.Containers
{ {
public class OsuScrollContainer : ScrollContainer<Drawable> public class OsuScrollContainer : ScrollContainer<Drawable>
{ {
public const float SCROLL_BAR_HEIGHT = 10;
public const float SCROLL_BAR_PADDING = 3;
/// <summary> /// <summary>
/// Allows controlling the scroll bar from any position in the container using the right mouse button. /// Allows controlling the scroll bar from any position in the container using the right mouse button.
/// Uses the value of <see cref="DistanceDecayOnRightMouseScrollbar"/> to smoothly scroll to the dragged location. /// Uses the value of <see cref="DistanceDecayOnRightMouseScrollbar"/> to smoothly scroll to the dragged location.
@ -96,8 +99,6 @@ namespace osu.Game.Graphics.Containers
protected class OsuScrollbar : ScrollbarContainer protected class OsuScrollbar : ScrollbarContainer
{ {
private const float dim_size = 10;
private Color4 hoverColour; private Color4 hoverColour;
private Color4 defaultColour; private Color4 defaultColour;
private Color4 highlightColour; private Color4 highlightColour;
@ -135,7 +136,7 @@ namespace osu.Game.Graphics.Containers
public override void ResizeTo(float val, int duration = 0, Easing easing = Easing.None) public override void ResizeTo(float val, int duration = 0, Easing easing = Easing.None)
{ {
Vector2 size = new Vector2(dim_size) Vector2 size = new Vector2(SCROLL_BAR_HEIGHT)
{ {
[(int)ScrollDirection] = val [(int)ScrollDirection] = val
}; };

View File

@ -61,6 +61,9 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"failtimes")] [JsonProperty(@"failtimes")]
private BeatmapMetrics metrics { get; set; } private BeatmapMetrics metrics { get; set; }
[JsonProperty(@"max_combo")]
private int? maxCombo { get; set; }
public BeatmapInfo ToBeatmap(RulesetStore rulesets) public BeatmapInfo ToBeatmap(RulesetStore rulesets)
{ {
var set = BeatmapSet?.ToBeatmapSet(rulesets); var set = BeatmapSet?.ToBeatmapSet(rulesets);
@ -76,6 +79,7 @@ namespace osu.Game.Online.API.Requests.Responses
Status = Status, Status = Status,
BeatmapSet = set, BeatmapSet = set,
Metrics = metrics, Metrics = metrics,
MaxCombo = maxCombo,
BaseDifficulty = new BeatmapDifficulty BaseDifficulty = new BeatmapDifficulty
{ {
DrainRate = drainRate, DrainRate = drainRate,

View File

@ -18,7 +18,7 @@ namespace osu.Game.Online.API.Requests.Responses
public class APILegacyUserTopScoreInfo public class APILegacyUserTopScoreInfo
{ {
[JsonProperty(@"position")] [JsonProperty(@"position")]
public int Position; public int? Position;
[JsonProperty(@"score")] [JsonProperty(@"score")]
public APILegacyScoreInfo Score; public APILegacyScoreInfo Score;

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.IO.Network;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Direct; using osu.Game.Overlays.Direct;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -26,8 +27,21 @@ namespace osu.Game.Online.API.Requests
this.direction = direction; this.direction = direction;
} }
// ReSharper disable once ImpureMethodCallOnReadonlyValueField protected override WebRequest CreateWebRequest()
protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={searchCategory.ToString().ToLowerInvariant()}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}"; {
var req = base.CreateWebRequest();
req.AddParameter("q", query);
if (ruleset.ID.HasValue)
req.AddParameter("m", ruleset.ID.Value.ToString());
req.AddParameter("s", searchCategory.ToString().ToLowerInvariant());
req.AddParameter("sort", $"{sortCriteria.ToString().ToLowerInvariant()}_{directionString}");
return req;
}
protected override string Target => @"beatmapsets/search";
} }
public enum BeatmapSearchCategory public enum BeatmapSearchCategory

View File

@ -2,12 +2,17 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.API.Requests
{ {
public class SearchBeatmapSetsResponse : ResponseWithCursor public class SearchBeatmapSetsResponse : ResponseWithCursor
{ {
[JsonProperty("beatmapsets")]
public IEnumerable<APIBeatmapSet> BeatmapSets; public IEnumerable<APIBeatmapSet> BeatmapSets;
[JsonProperty("total")]
public int Total;
} }
} }

View File

@ -41,7 +41,7 @@ namespace osu.Game.Online.Leaderboards
protected Container RankContainer { get; private set; } protected Container RankContainer { get; private set; }
private readonly ScoreInfo score; private readonly ScoreInfo score;
private readonly int rank; private readonly int? rank;
private readonly bool allowHighlight; private readonly bool allowHighlight;
private Box background; private Box background;
@ -58,7 +58,7 @@ namespace osu.Game.Online.Leaderboards
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
private DialogOverlay dialogOverlay { get; set; } private DialogOverlay dialogOverlay { get; set; }
public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) public LeaderboardScore(ScoreInfo score, int? rank, bool allowHighlight = true)
{ {
this.score = score; this.score = score;
this.rank = rank; this.rank = rank;
@ -90,7 +90,7 @@ namespace osu.Game.Online.Leaderboards
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Font = OsuFont.GetFont(size: 20, italics: true), Font = OsuFont.GetFont(size: 20, italics: true),
Text = rank.ToMetric(decimals: rank < 100000 ? 1 : 0), Text = rank == null ? "-" : rank.Value.ToMetric(decimals: rank < 100000 ? 1 : 0),
}, },
}, },
}, },

View File

@ -0,0 +1,24 @@
// 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.Graphics;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.BeatmapListing
{
public class BeatmapListingHeader : OverlayHeader
{
protected override ScreenTitle CreateTitle() => new BeatmapListingTitle();
private class BeatmapListingTitle : ScreenTitle
{
public BeatmapListingTitle()
{
Title = @"beatmap";
Section = @"listing";
}
protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog");
}
}
}

View File

@ -104,6 +104,8 @@ namespace osu.Game.Overlays.BeatmapListing
} }
} }
}); });
Category.Value = BeatmapSearchCategory.Leaderboard;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -8,16 +8,17 @@ using osu.Framework.Graphics;
using osuTK.Graphics; using osuTK.Graphics;
using osuTK; using osuTK;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Overlays.Direct;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
public class BeatmapListingSortTabControl : OverlaySortTabControl<BeatmapSortCriteria> public class BeatmapListingSortTabControl : OverlaySortTabControl<DirectSortCriteria>
{ {
public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(Overlays.SortDirection.Descending); public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(Overlays.SortDirection.Descending);
public BeatmapListingSortTabControl() public BeatmapListingSortTabControl()
{ {
Current.Value = BeatmapSortCriteria.Ranked; Current.Value = DirectSortCriteria.Ranked;
} }
protected override SortTabControl CreateControl() => new BeatmapSortTabControl protected override SortTabControl CreateControl() => new BeatmapSortTabControl
@ -29,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(); public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>();
protected override TabItem<BeatmapSortCriteria> CreateTabItem(BeatmapSortCriteria value) => new BeatmapSortTabItem(value) protected override TabItem<DirectSortCriteria> CreateTabItem(DirectSortCriteria value) => new BeatmapSortTabItem(value)
{ {
SortDirection = { BindTarget = SortDirection } SortDirection = { BindTarget = SortDirection }
}; };
@ -39,12 +40,12 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(); public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>();
public BeatmapSortTabItem(BeatmapSortCriteria value) public BeatmapSortTabItem(DirectSortCriteria value)
: base(value) : base(value)
{ {
} }
protected override TabButton CreateTabButton(BeatmapSortCriteria value) => new BeatmapTabButton(value) protected override TabButton CreateTabButton(DirectSortCriteria value) => new BeatmapTabButton(value)
{ {
Active = { BindTarget = Active }, Active = { BindTarget = Active },
SortDirection = { BindTarget = SortDirection } SortDirection = { BindTarget = SortDirection }
@ -66,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapListing
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
public BeatmapTabButton(BeatmapSortCriteria value) public BeatmapTabButton(DirectSortCriteria value)
: base(value) : base(value)
{ {
Add(icon = new SpriteIcon Add(icon = new SpriteIcon
@ -104,15 +105,4 @@ namespace osu.Game.Overlays.BeatmapListing
} }
} }
} }
public enum BeatmapSortCriteria
{
Title,
Artist,
Difficulty,
Ranked,
Rating,
Plays,
Favourites,
}
} }

View File

@ -0,0 +1,299 @@
// 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.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Threading;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests;
using osu.Game.Overlays.BeatmapListing;
using osu.Game.Overlays.Direct;
using osu.Game.Rulesets;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Overlays
{
public class BeatmapListingOverlay : FullscreenOverlay
{
[Resolved]
private PreviewTrackManager previewTrackManager { get; set; }
[Resolved]
private RulesetStore rulesets { get; set; }
private SearchBeatmapSetsRequest getSetsRequest;
private Container panelsPlaceholder;
private Drawable currentContent;
private BeatmapListingSearchSection searchSection;
private BeatmapListingSortTabControl sortControl;
public BeatmapListingOverlay()
: base(OverlayColourScheme.Blue)
{
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background6
},
new BasicScrollContainer
{
RelativeSizeAxes = Axes.Both,
ScrollbarVisible = false,
Child = new ReverseChildIDFillFlowContainer<Drawable>
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Masking = true,
EdgeEffect = new EdgeEffectParameters
{
Colour = Color4.Black.Opacity(0.25f),
Type = EdgeEffectType.Shadow,
Radius = 3,
Offset = new Vector2(0f, 1f),
},
Children = new Drawable[]
{
new BeatmapListingHeader(),
searchSection = new BeatmapListingSearchSection(),
}
},
new Container
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background4,
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.X,
Height = 40,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background5
},
sortControl = new BeatmapListingSortTabControl
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Left = 20 }
}
}
},
panelsPlaceholder = new Container
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Padding = new MarginPadding { Horizontal = 20 },
}
}
}
}
}
}
}
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
var sortCriteria = sortControl.Current;
var sortDirection = sortControl.SortDirection;
searchSection.Query.BindValueChanged(query =>
{
sortCriteria.Value = string.IsNullOrEmpty(query.NewValue) ? DirectSortCriteria.Ranked : DirectSortCriteria.Relevance;
sortDirection.Value = SortDirection.Descending;
queueUpdateSearch(true);
});
searchSection.Ruleset.BindValueChanged(_ => queueUpdateSearch());
searchSection.Category.BindValueChanged(_ => queueUpdateSearch());
sortCriteria.BindValueChanged(_ => queueUpdateSearch());
sortDirection.BindValueChanged(_ => queueUpdateSearch());
}
private ScheduledDelegate queryChangedDebounce;
private void queueUpdateSearch(bool queryTextChanged = false)
{
getSetsRequest?.Cancel();
queryChangedDebounce?.Cancel();
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100);
}
private void updateSearch()
{
if (!IsLoaded)
return;
if (State.Value == Visibility.Hidden)
return;
if (API == null)
return;
previewTrackManager.StopAnyPlaying(this);
currentContent?.FadeColour(Color4.DimGray, 400, Easing.OutQuint);
getSetsRequest = new SearchBeatmapSetsRequest(
searchSection.Query.Value,
searchSection.Ruleset.Value,
searchSection.Category.Value,
sortControl.Current.Value,
sortControl.SortDirection.Value);
getSetsRequest.Success += response => Schedule(() => recreatePanels(response));
API.Queue(getSetsRequest);
}
private void recreatePanels(SearchBeatmapSetsResponse response)
{
if (response.Total == 0)
{
searchSection.BeatmapSet = null;
LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder);
return;
}
var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList();
var newPanels = new FillFlowContainer<DirectPanel>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(10),
Alpha = 0,
Margin = new MarginPadding { Vertical = 15 },
ChildrenEnumerable = beatmaps.Select<BeatmapSetInfo, DirectPanel>(b => new DirectGridPanel(b)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
})
};
LoadComponentAsync(newPanels, loaded =>
{
addContentToPlaceholder(loaded);
searchSection.BeatmapSet = beatmaps.First();
});
}
private void addContentToPlaceholder(Drawable content)
{
Drawable lastContent = currentContent;
if (lastContent != null)
{
lastContent.FadeOut(100, Easing.OutQuint).Expire();
// Consider the case when the new content is smaller than the last content.
// If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird.
// At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0.
// To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so.
lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y);
}
panelsPlaceholder.Add(currentContent = content);
currentContent.FadeIn(200, Easing.OutQuint);
}
protected override void Dispose(bool isDisposing)
{
getSetsRequest?.Cancel();
queryChangedDebounce?.Cancel();
base.Dispose(isDisposing);
}
private class NotFoundDrawable : CompositeDrawable
{
public NotFoundDrawable()
{
RelativeSizeAxes = Axes.X;
Height = 250;
Alpha = 0;
Margin = new MarginPadding { Top = 15 };
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
AddInternal(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10, 0),
Children = new Drawable[]
{
new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Texture = textures.Get(@"Online/not-found")
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = @"... nope, nothing found.",
}
}
});
}
}
}
}

View File

@ -17,7 +17,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
private readonly Box background; private readonly Box background;
public DrawableTopScore(ScoreInfo score, int position = 1) public DrawableTopScore(ScoreInfo score, int? position = 1)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;

View File

@ -146,7 +146,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
new OsuSpriteText new OsuSpriteText
{ {
Text = $@"{score.MaxCombo:N0}x", Text = $@"{score.MaxCombo:N0}x",
Font = OsuFont.GetFont(size: text_size) Font = OsuFont.GetFont(size: text_size),
Colour = score.MaxCombo == score.Beatmap?.MaxCombo ? highAccuracyColour : Color4.White
} }
}); });

View File

@ -112,9 +112,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
}; };
} }
public int ScorePosition public int? ScorePosition
{ {
set => rankText.Text = $"#{value}"; set => rankText.Text = value == null ? "-" : $"#{value}";
} }
/// <summary> /// <summary>

View File

@ -34,14 +34,13 @@ namespace osu.Game.Overlays.Direct
public enum DirectSortCriteria public enum DirectSortCriteria
{ {
Relevance,
Title, Title,
Artist, Artist,
Creator,
Difficulty, Difficulty,
Ranked, Ranked,
Rating, Rating,
Plays, Plays,
Favourites, Favourites,
Relevance,
} }
} }

View File

@ -75,8 +75,6 @@ namespace osu.Game.Overlays.Music
}, },
}; };
list.Items.BindTo(beatmapSets);
filter.Search.OnCommit = (sender, newText) => filter.Search.OnCommit = (sender, newText) =>
{ {
BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
@ -87,7 +85,13 @@ namespace osu.Game.Overlays.Music
beatmap.Value.Track.Restart(); beatmap.Value.Track.Restart();
} }
}; };
}
protected override void LoadComplete()
{
base.LoadComplete();
list.Items.BindTo(beatmapSets);
beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true); beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true);
} }

View File

@ -25,7 +25,16 @@ namespace osu.Game.Overlays
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; }
public IBindableList<BeatmapSetInfo> BeatmapSets => beatmapSets; public IBindableList<BeatmapSetInfo> BeatmapSets
{
get
{
if (LoadState < LoadState.Ready)
throw new InvalidOperationException($"{nameof(BeatmapSets)} should not be accessed before the music controller is loaded.");
return beatmapSets;
}
}
/// <summary> /// <summary>
/// Point in time after which the current track will be restarted on triggering a "previous track" action. /// Point in time after which the current track will be restarted on triggering a "previous track" action.
@ -54,16 +63,18 @@ namespace osu.Game.Overlays
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next()));
beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemAdded += handleBeatmapAdded;
beatmaps.ItemRemoved += handleBeatmapRemoved; beatmaps.ItemRemoved += handleBeatmapRemoved;
beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next()));
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete();
beatmap.BindValueChanged(beatmapChanged, true); beatmap.BindValueChanged(beatmapChanged, true);
mods.BindValueChanged(_ => ResetTrackAdjustments(), true); mods.BindValueChanged(_ => ResetTrackAdjustments(), true);
base.LoadComplete();
} }
/// <summary> /// <summary>
@ -82,11 +93,16 @@ namespace osu.Game.Overlays
/// </summary> /// </summary>
public bool IsPlaying => current?.Track.IsRunning ?? false; public bool IsPlaying => current?.Track.IsRunning ?? false;
private void handleBeatmapAdded(BeatmapSetInfo set) => private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() =>
Schedule(() => beatmapSets.Add(set)); {
if (!beatmapSets.Contains(set))
beatmapSets.Add(set);
});
private void handleBeatmapRemoved(BeatmapSetInfo set) => private void handleBeatmapRemoved(BeatmapSetInfo set) => Schedule(() =>
Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); {
beatmapSets.RemoveAll(s => s.ID == set.ID);
});
private ScheduledDelegate seekDelegate; private ScheduledDelegate seekDelegate;

View File

@ -58,6 +58,9 @@ namespace osu.Game.Overlays
[Resolved] [Resolved]
private Bindable<WorkingBeatmap> beatmap { get; set; } private Bindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private OsuColour colours { get; set; }
public NowPlayingOverlay() public NowPlayingOverlay()
{ {
Width = 400; Width = 400;
@ -65,7 +68,7 @@ namespace osu.Game.Overlays
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load()
{ {
Children = new Drawable[] Children = new Drawable[]
{ {
@ -182,15 +185,15 @@ namespace osu.Game.Overlays
} }
} }
}; };
playlist.BeatmapSets.BindTo(musicController.BeatmapSets);
playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint);
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
playlist.BeatmapSets.BindTo(musicController.BeatmapSets);
playlist.State.BindValueChanged(s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint), true);
beatmap.BindDisabledChanged(beatmapDisabledChanged, true); beatmap.BindDisabledChanged(beatmapDisabledChanged, true);
musicController.TrackChanged += trackChanged; musicController.TrackChanged += trackChanged;

View File

@ -9,6 +9,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Graphics.Containers;
namespace osu.Game.Overlays.Rankings.Tables namespace osu.Game.Overlays.Rankings.Tables
{ {
@ -61,18 +62,35 @@ namespace osu.Game.Overlays.Rankings.Tables
} }
}; };
private class CountryName : OsuSpriteText private class CountryName : OsuHoverContainer
{ {
protected override IEnumerable<Drawable> EffectTargets => new[] { text };
[Resolved(canBeNull: true)]
private RankingsOverlay rankings { get; set; }
private readonly OsuSpriteText text;
private readonly Country country;
public CountryName(Country country) public CountryName(Country country)
{ {
Font = OsuFont.GetFont(size: 12); this.country = country;
Text = country.FullName ?? string.Empty;
AutoSizeAxes = Axes.Both;
Add(text = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 12),
Text = country.FullName ?? string.Empty,
});
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider) private void load(OverlayColourProvider colourProvider)
{ {
Colour = colourProvider.Light2; IdleColour = colourProvider.Light2;
HoverColour = colourProvider.Content2;
Action = () => rankings?.ShowCountry(country);
} }
} }
} }

View File

@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
if (HitObject is IHasComboInformation combo) if (HitObject is IHasComboInformation combo)
{ {
comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy(); comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy();
comboIndexBindable.BindValueChanged(_ => updateAccentColour(), true); comboIndexBindable.BindValueChanged(_ => updateComboColour(), true);
} }
samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); samplesBindable = HitObject.SamplesBindable.GetBoundCopy();
@ -336,7 +336,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
{ {
base.SkinChanged(skin, allowFallback); base.SkinChanged(skin, allowFallback);
updateAccentColour(); updateComboColour();
ApplySkin(skin, allowFallback); ApplySkin(skin, allowFallback);
@ -344,13 +344,29 @@ namespace osu.Game.Rulesets.Objects.Drawables
updateState(State.Value, true); updateState(State.Value, true);
} }
private void updateAccentColour() private void updateComboColour()
{ {
if (HitObject is IHasComboInformation combo) if (!(HitObject is IHasComboInformation)) return;
{
var comboColours = CurrentSkin.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value; var comboColours = CurrentSkin.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value;
AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White;
} AccentColour.Value = GetComboColour(comboColours);
}
/// <summary>
/// Called to retrieve the combo colour. Automatically assigned to <see cref="AccentColour"/>.
/// Defaults to using <see cref="IHasComboInformation.ComboIndex"/> to decide on a colour.
/// </summary>
/// <remarks>
/// This will only be called if the <see cref="HitObject"/> implements <see cref="IHasComboInformation"/>.
/// </remarks>
/// <param name="comboColours">A list of combo colours provided by the beatmap or skin. Can be null if not available.</param>
protected virtual Color4 GetComboColour(IReadOnlyList<Color4> comboColours)
{
if (!(HitObject is IHasComboInformation combo))
throw new InvalidOperationException($"{nameof(HitObject)} must implement {nameof(IHasComboInformation)}");
return comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White;
} }
/// <summary> /// <summary>

View File

@ -9,12 +9,32 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osuTK; using osuTK;
namespace osu.Game.Screens.Multi.Match.Components namespace osu.Game.Screens.Multi.Components
{ {
public abstract class OverlinedDisplay : MultiplayerComposite public abstract class OverlinedDisplay : MultiplayerComposite
{ {
protected readonly Container Content; protected readonly Container Content;
public override Axes RelativeSizeAxes
{
get => base.RelativeSizeAxes;
set
{
base.RelativeSizeAxes = value;
updateDimensions();
}
}
public override Axes AutoSizeAxes
{
get => base.AutoSizeAxes;
protected set
{
base.AutoSizeAxes = value;
updateDimensions();
}
}
protected string Details protected string Details
{ {
set => details.Text = value; set => details.Text = value;
@ -22,14 +42,12 @@ namespace osu.Game.Screens.Multi.Match.Components
private readonly Circle line; private readonly Circle line;
private readonly OsuSpriteText details; private readonly OsuSpriteText details;
private readonly GridContainer grid;
protected OverlinedDisplay(string title) protected OverlinedDisplay(string title)
{ {
RelativeSizeAxes = Axes.Both; InternalChild = grid = new GridContainer
InternalChild = new GridContainer
{ {
RelativeSizeAxes = Axes.Both,
Content = new[] Content = new[]
{ {
new Drawable[] new Drawable[]
@ -62,19 +80,12 @@ namespace osu.Game.Screens.Multi.Match.Components
}, },
new Drawable[] new Drawable[]
{ {
Content = new Container Content = new Container { Margin = new MarginPadding { Top = 5 } }
{
Margin = new MarginPadding { Top = 5 },
RelativeSizeAxes = Axes.Both
}
} }
},
RowDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize),
} }
}; };
updateDimensions();
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -83,5 +94,23 @@ namespace osu.Game.Screens.Multi.Match.Components
line.Colour = colours.Yellow; line.Colour = colours.Yellow;
details.Colour = colours.Yellow; details.Colour = colours.Yellow;
} }
private void updateDimensions()
{
grid.RowDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize),
new Dimension(AutoSizeAxes.HasFlag(Axes.Y) ? GridSizeMode.AutoSize : GridSizeMode.Distributed),
};
// Assigning to none is done so that setting auto and relative size modes doesn't cause exceptions to be thrown
grid.AutoSizeAxes = Content.AutoSizeAxes = Axes.None;
grid.RelativeSizeAxes = Content.RelativeSizeAxes = Axes.None;
// Auto-size when required, otherwise eagerly relative-size
grid.AutoSizeAxes = Content.AutoSizeAxes = AutoSizeAxes;
grid.RelativeSizeAxes = Content.RelativeSizeAxes = ~AutoSizeAxes;
}
} }
} }

View File

@ -0,0 +1,56 @@
// 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.Graphics;
using osu.Game.Graphics.Containers;
namespace osu.Game.Screens.Multi.Components
{
public class OverlinedParticipants : OverlinedDisplay
{
public new Axes AutoSizeAxes
{
get => base.AutoSizeAxes;
set => base.AutoSizeAxes = value;
}
public OverlinedParticipants(Direction direction)
: base("Participants")
{
OsuScrollContainer scroll;
ParticipantsList list;
Content.Add(scroll = new OsuScrollContainer(direction)
{
Child = list = new ParticipantsList()
});
switch (direction)
{
case Direction.Horizontal:
scroll.RelativeSizeAxes = Axes.X;
scroll.Height = ParticipantsList.TILE_SIZE + OsuScrollContainer.SCROLL_BAR_HEIGHT + OsuScrollContainer.SCROLL_BAR_PADDING * 2;
list.AutoSizeAxes = Axes.Both;
break;
case Direction.Vertical:
scroll.RelativeSizeAxes = Axes.Both;
list.RelativeSizeAxes = Axes.X;
list.AutoSizeAxes = Axes.Y;
break;
}
}
[BackgroundDependencyLoader]
private void load()
{
ParticipantCount.BindValueChanged(_ => setParticipantCount());
MaxParticipants.BindValueChanged(_ => setParticipantCount());
setParticipantCount();
}
private void setParticipantCount() => Details = MaxParticipants.Value != null ? $"{ParticipantCount.Value}/{MaxParticipants.Value}" : ParticipantCount.Value.ToString();
}
}

View File

@ -6,7 +6,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
namespace osu.Game.Screens.Multi.Match.Components namespace osu.Game.Screens.Multi.Components
{ {
public class OverlinedPlaylist : OverlinedDisplay public class OverlinedPlaylist : OverlinedDisplay
{ {

View File

@ -8,7 +8,6 @@ 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.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Users; using osu.Game.Users;
@ -19,21 +18,39 @@ namespace osu.Game.Screens.Multi.Components
{ {
public class ParticipantsList : MultiplayerComposite public class ParticipantsList : MultiplayerComposite
{ {
public const float TILE_SIZE = 70;
public override Axes RelativeSizeAxes
{
get => base.RelativeSizeAxes;
set
{
base.RelativeSizeAxes = value;
fill.RelativeSizeAxes = value;
}
}
public new Axes AutoSizeAxes
{
get => base.AutoSizeAxes;
set
{
base.AutoSizeAxes = value;
fill.AutoSizeAxes = value;
}
}
public FillDirection Direction
{
get => fill.Direction;
set => fill.Direction = value;
}
private readonly FillFlowContainer fill; private readonly FillFlowContainer fill;
public ParticipantsList() public ParticipantsList()
{ {
InternalChild = new OsuScrollContainer InternalChild = fill = new FillFlowContainer { Spacing = new Vector2(10) };
{
RelativeSizeAxes = Axes.Both,
Child = fill = new FillFlowContainer
{
Spacing = new Vector2(10),
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Full,
}
};
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Components;
@ -157,7 +158,15 @@ namespace osu.Game.Screens.Multi.Lounge.Components
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = 10 }, Padding = new MarginPadding { Horizontal = 10 },
Child = new ParticipantsList { RelativeSizeAxes = Axes.Both } Child = new OsuScrollContainer
{
RelativeSizeAxes = Axes.Both,
Child = new ParticipantsList
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}
}
} }
} }
} }

View File

@ -1,29 +0,0 @@
// 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.Graphics;
using osu.Game.Screens.Multi.Components;
namespace osu.Game.Screens.Multi.Match.Components
{
public class OverlinedParticipants : OverlinedDisplay
{
public OverlinedParticipants()
: base("Participants")
{
Content.Add(new ParticipantsList { RelativeSizeAxes = Axes.Both });
}
[BackgroundDependencyLoader]
private void load()
{
ParticipantCount.BindValueChanged(_ => setParticipantCount());
MaxParticipants.BindValueChanged(_ => setParticipantCount());
setParticipantCount();
}
private void setParticipantCount() => Details = MaxParticipants.Value != null ? $"{ParticipantCount.Value}/{MaxParticipants.Value}" : ParticipantCount.Value.ToString();
}
}

View File

@ -103,7 +103,7 @@ namespace osu.Game.Screens.Multi.Match
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Right = 5 }, Padding = new MarginPadding { Right = 5 },
Child = new OverlinedParticipants() Child = new OverlinedParticipants(Direction.Vertical) { RelativeSizeAxes = Axes.Both }
}, },
new Container new Container
{ {
@ -111,6 +111,7 @@ namespace osu.Game.Screens.Multi.Match
Padding = new MarginPadding { Horizontal = 5 }, Padding = new MarginPadding { Horizontal = 5 },
Child = new OverlinedPlaylist(true) // Temporarily always allow selection Child = new OverlinedPlaylist(true) // Temporarily always allow selection
{ {
RelativeSizeAxes = Axes.Both,
SelectedItem = { BindTarget = SelectedItem } SelectedItem = { BindTarget = SelectedItem }
} }
}, },

View File

@ -22,7 +22,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.219.0" />
<PackageReference Include="ppy.osu.Framework" Version="2020.218.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.218.0" />
<PackageReference Include="Sentry" Version="2.0.3" /> <PackageReference Include="Sentry" Version="2.0.3" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />

View File

@ -73,7 +73,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.219.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.218.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.218.0" />
</ItemGroup> </ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. --> <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->