1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 19:27:31 +08:00

Merge pull request #1 from ppy/master

Merge ppy:master into master
This commit is contained in:
recapitalverb 2020-02-04 19:25:44 +07:00 committed by GitHub
commit 1f2d710ef4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 919 additions and 1005 deletions

View File

@ -277,7 +277,7 @@ namespace osu.Game.Tests.Visual.Background
private void setupUserSettings() private void setupUserSettings()
{ {
AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null); AddUntilStep("Song select has selection", () => songSelect.Carousel?.SelectedBeatmap != null);
AddStep("Set default user settings", () => AddStep("Set default user settings", () =>
{ {
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray(); SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray();

View File

@ -2,12 +2,16 @@
// 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;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
@ -15,7 +19,9 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
private HUDOverlay hudOverlay; private HUDOverlay hudOverlay;
private Drawable hideTarget => hudOverlay.KeyCounter; // best way of checking hideTargets without exposing. // best way to check without exposing.
private Drawable hideTarget => hudOverlay.KeyCounter;
private FillFlowContainer<KeyCounter> keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType<FillFlowContainer<KeyCounter>>().First();
[Resolved] [Resolved]
private OsuConfigManager config { get; set; } private OsuConfigManager config { get; set; }
@ -28,6 +34,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("showhud is set", () => hudOverlay.ShowHud.Value); AddAssert("showhud is set", () => hudOverlay.ShowHud.Value);
AddAssert("hidetarget is visible", () => hideTarget.IsPresent); AddAssert("hidetarget is visible", () => hideTarget.IsPresent);
AddAssert("key counter flow is visible", () => keyCounterFlow.IsPresent);
AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent); AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent);
} }
@ -50,6 +57,9 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent); AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent);
AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent); AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent);
// Key counter flow container should not be affected by this, only the key counter display will be hidden as checked above.
AddAssert("key counter flow not affected", () => keyCounterFlow.IsPresent);
} }
[Test] [Test]
@ -68,12 +78,40 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("config unchanged", () => originalConfigValue == config.Get<bool>(OsuSetting.ShowInterface)); AddAssert("config unchanged", () => originalConfigValue == config.Get<bool>(OsuSetting.ShowInterface));
} }
[Test]
public void TestChangeHUDVisibilityOnHiddenKeyCounter()
{
bool keyCounterVisibleValue = false;
createNew();
AddStep("save keycounter visible value", () => keyCounterVisibleValue = config.Get<bool>(OsuSetting.KeyOverlay));
AddStep("set keycounter visible false", () =>
{
config.Set<bool>(OsuSetting.KeyOverlay, false);
hudOverlay.KeyCounter.AlwaysVisible.Value = false;
});
AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false);
AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent);
AddAssert("key counters hidden", () => !keyCounterFlow.IsPresent);
AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true);
AddUntilStep("hidetarget is visible", () => hideTarget.IsPresent);
AddAssert("key counters still hidden", () => !keyCounterFlow.IsPresent);
AddStep("return value", () => config.Set<bool>(OsuSetting.KeyOverlay, keyCounterVisibleValue));
}
private void createNew(Action<HUDOverlay> action = null) private void createNew(Action<HUDOverlay> action = null)
{ {
AddStep("create overlay", () => AddStep("create overlay", () =>
{ {
Child = hudOverlay = new HUDOverlay(null, null, null, Array.Empty<Mod>()); Child = hudOverlay = new HUDOverlay(null, null, null, Array.Empty<Mod>());
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space));
action?.Invoke(hudOverlay); action?.Invoke(hudOverlay);
}); });
} }

View File

@ -5,6 +5,7 @@ using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using System; using System;
@ -21,6 +22,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(BeatmapRulesetTabItem), typeof(BeatmapRulesetTabItem),
}; };
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
private readonly TestRulesetSelector selector; private readonly TestRulesetSelector selector;
public TestSceneBeatmapRulesetSelector() public TestSceneBeatmapRulesetSelector()

View File

@ -11,6 +11,8 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
using osu.Framework.Allocation;
namespace osu.Game.Tests.Visual.Online namespace osu.Game.Tests.Visual.Online
{ {
@ -22,6 +24,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(CountryPill) typeof(CountryPill)
}; };
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
public TestSceneRankingsCountryFilter() public TestSceneRankingsCountryFilter()
{ {
var countryBindable = new Bindable<Country>(); var countryBindable = new Bindable<Country>();

View File

@ -1,66 +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 System;
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays.Rankings;
using osu.Game.Users;
using osuTK;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneRankingsDismissableFlag : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DismissableFlag),
};
public TestSceneRankingsDismissableFlag()
{
DismissableFlag flag;
SpriteText text;
var countryA = new Country
{
FlagName = "BY",
FullName = "Belarus"
};
var countryB = new Country
{
FlagName = "US",
FullName = "United States"
};
AddRange(new Drawable[]
{
flag = new DismissableFlag
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(30, 20),
Country = countryA,
},
text = new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = "Invoked",
Font = OsuFont.GetFont(size: 30),
Alpha = 0,
}
});
flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint);
AddStep("Trigger click", () => flag.Click());
AddStep("Change to country 2", () => flag.Country = countryB);
AddStep("Change to country 1", () => flag.Country = countryA);
}
}
}

View File

@ -3,8 +3,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Game.Overlays;
using osu.Game.Overlays.Rankings; using osu.Game.Overlays.Rankings;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Users; using osu.Game.Users;
@ -15,24 +16,23 @@ namespace osu.Game.Tests.Visual.Online
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
typeof(DismissableFlag), typeof(RankingsOverlayHeader),
typeof(HeaderTitle), typeof(CountryFilter),
typeof(RankingsRulesetSelector), typeof(CountryPill)
typeof(RankingsScopeSelector),
typeof(RankingsHeader),
}; };
[Cached]
private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Green);
public TestSceneRankingsHeader() public TestSceneRankingsHeader()
{ {
var countryBindable = new Bindable<Country>(); var countryBindable = new Bindable<Country>();
var ruleset = new Bindable<RulesetInfo>(); var ruleset = new Bindable<RulesetInfo>();
var scope = new Bindable<RankingsScope>(); var scope = new Bindable<RankingsScope>();
Add(new RankingsHeader Add(new RankingsOverlayHeader
{ {
Anchor = Anchor.Centre, Current = { BindTarget = scope },
Origin = Anchor.Centre,
Scope = { BindTarget = scope },
Country = { BindTarget = countryBindable }, Country = { BindTarget = countryBindable },
Ruleset = { BindTarget = ruleset }, Ruleset = { BindTarget = ruleset },
Spotlights = new[] Spotlights = new[]

View File

@ -1,55 +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 System;
using System.Collections.Generic;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Overlays.Rankings;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneRankingsHeaderTitle : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DismissableFlag),
typeof(HeaderTitle),
};
public TestSceneRankingsHeaderTitle()
{
var countryBindable = new Bindable<Country>();
var scope = new Bindable<RankingsScope>();
Add(new HeaderTitle
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Country = { BindTarget = countryBindable },
Scope = { BindTarget = scope },
});
var countryA = new Country
{
FlagName = "BY",
FullName = "Belarus"
};
var countryB = new Country
{
FlagName = "US",
FullName = "United States"
};
AddStep("Set country 1", () => countryBindable.Value = countryA);
AddStep("Set country 2", () => countryBindable.Value = countryB);
AddStep("Set null country", () => countryBindable.Value = null);
AddStep("Set scope to Performance", () => scope.Value = RankingsScope.Performance);
AddStep("Set scope to Spotlights", () => scope.Value = RankingsScope.Spotlights);
AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score);
AddStep("Set scope to Country", () => scope.Value = RankingsScope.Country);
}
}
}

View File

@ -25,7 +25,8 @@ namespace osu.Game.Tests.Visual.Online
typeof(TableRowBackground), typeof(TableRowBackground),
typeof(UserBasedTable), typeof(UserBasedTable),
typeof(RankingsTable<>), typeof(RankingsTable<>),
typeof(RankingsOverlay) typeof(RankingsOverlay),
typeof(RankingsOverlayHeader)
}; };
[Cached] [Cached]

View File

@ -1,41 +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 System;
using System.Collections.Generic;
using osu.Game.Overlays.Rankings;
using osu.Framework.Graphics;
using osu.Game.Rulesets;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Taiko;
using osu.Game.Rulesets.Catch;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneRankingsRulesetSelector : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(RankingsRulesetSelector),
};
public TestSceneRankingsRulesetSelector()
{
var current = new Bindable<RulesetInfo>();
Add(new RankingsRulesetSelector
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Current = { BindTarget = current }
});
AddStep("Select osu!", () => current.Value = new OsuRuleset().RulesetInfo);
AddStep("Select mania", () => current.Value = new ManiaRuleset().RulesetInfo);
AddStep("Select taiko", () => current.Value = new TaikoRuleset().RulesetInfo);
AddStep("Select catch", () => current.Value = new CatchRuleset().RulesetInfo);
}
}
}

View File

@ -1,54 +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 System;
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Overlays.Rankings;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneRankingsScopeSelector : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(RankingsScopeSelector),
};
private readonly Box background;
public TestSceneRankingsScopeSelector()
{
var scope = new Bindable<RankingsScope>();
AddRange(new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both
},
new RankingsScopeSelector
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Current = scope,
}
});
AddStep(@"Select country", () => scope.Value = RankingsScope.Country);
AddStep(@"Select performance", () => scope.Value = RankingsScope.Performance);
AddStep(@"Select score", () => scope.Value = RankingsScope.Score);
AddStep(@"Select spotlights", () => scope.Value = RankingsScope.Spotlights);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
background.Colour = colours.GreySeafoam;
}
}
}

View File

@ -0,0 +1,87 @@
// 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 NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Rankings;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneRankingsSpotlightSelector : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(SpotlightSelector),
};
protected override bool UseOnlineAPI => true;
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
[Resolved]
private IAPIProvider api { get; set; }
private readonly SpotlightSelector selector;
public TestSceneRankingsSpotlightSelector()
{
Add(selector = new SpotlightSelector());
}
[Test]
public void TestLocalSpotlights()
{
var spotlights = new[]
{
new APISpotlight
{
Name = "Spotlight 1",
StartDate = DateTimeOffset.Now,
EndDate = DateTimeOffset.Now,
},
new APISpotlight
{
Name = "Spotlight 2",
StartDate = DateTimeOffset.Now,
EndDate = DateTimeOffset.Now,
},
new APISpotlight
{
Name = "Spotlight 3",
StartDate = DateTimeOffset.Now,
EndDate = DateTimeOffset.Now,
},
};
AddStep("load spotlights", () => selector.Spotlights = spotlights);
AddStep("change to spotlight 3", () => selector.Current.Value = spotlights[2]);
}
[Test]
public void TestOnlineSpotlights()
{
List<APISpotlight> spotlights = null;
AddStep("retrieve spotlights", () =>
{
var req = new GetSpotlightsRequest();
req.Success += res => spotlights = res.Spotlights;
api.Perform(req);
});
AddStep("set spotlights", () =>
{
if (spotlights != null)
selector.Spotlights = spotlights;
});
}
}
}

View File

@ -16,6 +16,7 @@ using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Taiko;
using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Overlays;
namespace osu.Game.Tests.Visual.Online namespace osu.Game.Tests.Visual.Online
{ {
@ -36,6 +37,9 @@ namespace osu.Game.Tests.Visual.Online
[Resolved] [Resolved]
private IAPIProvider api { get; set; } private IAPIProvider api { get; set; }
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
private readonly BasicScrollContainer scrollFlow; private readonly BasicScrollContainer scrollFlow;
private readonly DimmedLoadingLayer loading; private readonly DimmedLoadingLayer loading;
private CancellationTokenSource cancellationToken; private CancellationTokenSource cancellationToken;

View File

@ -3,11 +3,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Overlays.BeatmapSet.Scores;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Scoring; using osu.Game.Scoring;
@ -27,6 +29,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(ScoreTableRowBackground), typeof(ScoreTableRowBackground),
}; };
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
public TestSceneScoresContainer() public TestSceneScoresContainer()
{ {
TestScoresContainer scoresContainer; TestScoresContainer scoresContainer;

View File

@ -60,7 +60,6 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
modSelect = new TestModSelectOverlay modSelect = new TestModSelectOverlay
{ {
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
SelectedMods = { BindTarget = SelectedMods } SelectedMods = { BindTarget = SelectedMods }

View File

@ -79,7 +79,6 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
Child = modSelect = new TestModSelectOverlay Child = modSelect = new TestModSelectOverlay
{ {
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
SelectedMods = { BindTarget = SelectedMods } SelectedMods = { BindTarget = SelectedMods }

View File

@ -0,0 +1,20 @@
// 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.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetSpotlightsRequest : APIRequest<SpotlightsCollection>
{
protected override string Target => "spotlights";
}
public class SpotlightsCollection
{
[JsonProperty("spotlights")]
public List<APISpotlight> Spotlights;
}
}

View File

@ -0,0 +1,31 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Online.API.Requests.Responses
{
public class APISpotlight
{
[JsonProperty("id")]
public int Id;
[JsonProperty("name")]
public string Name;
[JsonProperty("type")]
public string Type;
[JsonProperty("mode_specific")]
public bool ModeSpecific;
[JsonProperty(@"start_date")]
public DateTimeOffset StartDate;
[JsonProperty(@"end_date")]
public DateTimeOffset EndDate;
public override string ToString() => Name;
}
}

View File

@ -277,7 +277,7 @@ namespace osu.Game.Online.Leaderboards
protected virtual IEnumerable<LeaderboardScoreStatistic> GetStatistics(ScoreInfo model) => new[] protected virtual IEnumerable<LeaderboardScoreStatistic> GetStatistics(ScoreInfo model) => new[]
{ {
new LeaderboardScoreStatistic(FontAwesome.Solid.Link, "Max Combo", model.MaxCombo.ToString()), new LeaderboardScoreStatistic(FontAwesome.Solid.Link, "Max Combo", model.MaxCombo.ToString()),
new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:0%}" : @"{0:0.00%}", model.Accuracy)) new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", model.DisplayAccuracy)
}; };
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)

View File

@ -2,17 +2,14 @@
// 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.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osuTK;
using System.Linq; using System.Linq;
namespace osu.Game.Overlays.BeatmapSet namespace osu.Game.Overlays.BeatmapSet
{ {
public class BeatmapRulesetSelector : RulesetSelector public class BeatmapRulesetSelector : OverlayRulesetSelector
{ {
private readonly Bindable<BeatmapSetInfo> beatmapSet = new Bindable<BeatmapSetInfo>(); private readonly Bindable<BeatmapSetInfo> beatmapSet = new Bindable<BeatmapSetInfo>();
@ -28,21 +25,9 @@ namespace osu.Game.Overlays.BeatmapSet
} }
} }
public BeatmapRulesetSelector()
{
AutoSizeAxes = Axes.Both;
}
protected override TabItem<RulesetInfo> CreateTabItem(RulesetInfo value) => new BeatmapRulesetTabItem(value) protected override TabItem<RulesetInfo> CreateTabItem(RulesetInfo value) => new BeatmapRulesetTabItem(value)
{ {
BeatmapSet = { BindTarget = beatmapSet } BeatmapSet = { BindTarget = beatmapSet }
}; };
protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10, 0),
};
} }
} }

View File

@ -3,143 +3,74 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osuTK;
using osuTK.Graphics;
using System.Linq; using System.Linq;
namespace osu.Game.Overlays.BeatmapSet namespace osu.Game.Overlays.BeatmapSet
{ {
public class BeatmapRulesetTabItem : TabItem<RulesetInfo> public class BeatmapRulesetTabItem : OverlayRulesetTabItem
{ {
private readonly OsuSpriteText name, count;
private readonly Box bar;
public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>(); public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>();
public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; [Resolved]
private OverlayColourProvider colourProvider { get; set; }
private OsuSpriteText count;
private Container countContainer;
public BeatmapRulesetTabItem(RulesetInfo value) public BeatmapRulesetTabItem(RulesetInfo value)
: base(value) : base(value)
{ {
AutoSizeAxes = Axes.Both; }
FillFlowContainer nameContainer; [BackgroundDependencyLoader]
private void load()
Children = new Drawable[] {
Add(countContainer = new Container
{ {
nameContainer = new FillFlowContainer AutoSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Masking = true,
CornerRadius = 4f,
Children = new Drawable[]
{ {
Anchor = Anchor.Centre, new Box
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Margin = new MarginPadding { Bottom = 7.5f },
Spacing = new Vector2(2.5f),
Children = new Drawable[]
{ {
name = new OsuSpriteText RelativeSizeAxes = Axes.Both,
{ Colour = colourProvider.Background6
Anchor = Anchor.Centre, },
Origin = Anchor.Centre, count = new OsuSpriteText
Text = value.Name, {
Font = OsuFont.Default.With(size: 18), Anchor = Anchor.Centre,
}, Origin = Anchor.Centre,
new Container Margin = new MarginPadding { Horizontal = 5f },
{ Font = OsuFont.Default.With(weight: FontWeight.SemiBold),
Anchor = Anchor.Centre, Colour = colourProvider.Foreground1,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 4f,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.5f),
},
count = new OsuSpriteText
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Margin = new MarginPadding { Horizontal = 5f },
Font = OsuFont.Default.With(weight: FontWeight.SemiBold),
}
}
}
} }
}, }
bar = new Box });
{ }
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, protected override void LoadComplete()
RelativeSizeAxes = Axes.X, {
}, base.LoadComplete();
new HoverClickSounds(),
};
BeatmapSet.BindValueChanged(setInfo => BeatmapSet.BindValueChanged(setInfo =>
{ {
var beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.Equals(Value)) ?? 0; var beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.Equals(Value)) ?? 0;
count.Text = beatmapsCount.ToString(); count.Text = beatmapsCount.ToString();
count.Alpha = beatmapsCount > 0 ? 1f : 0f; countContainer.FadeTo(beatmapsCount > 0 ? 1 : 0);
Enabled.Value = beatmapsCount > 0; Enabled.Value = beatmapsCount > 0;
}, true); }, true);
Enabled.BindValueChanged(v => nameContainer.Alpha = v.NewValue ? 1f : 0.5f, true);
} }
[Resolved]
private OsuColour colour { get; set; }
protected override void LoadComplete()
{
base.LoadComplete();
count.Colour = colour.Gray9;
bar.Colour = colour.Blue;
updateState();
}
private void updateState()
{
var isHoveredOrActive = IsHovered || Active.Value;
bar.ResizeHeightTo(isHoveredOrActive ? 4 : 0, 200, Easing.OutQuint);
name.Colour = isHoveredOrActive ? colour.GrayE : colour.GrayC;
name.Font = name.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular);
}
#region Hovering and activation logic
protected override void OnActivated() => updateState();
protected override void OnDeactivated() => updateState();
protected override bool OnHover(HoverEvent e)
{
updateState();
return false;
}
protected override void OnHoverLost(HoverLostEvent e) => updateState();
#endregion
} }
} }

View File

@ -0,0 +1,35 @@
// 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.Bindables;
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets;
namespace osu.Game.Overlays.BeatmapSet
{
public class BeatmapSetHeader : OverlayHeader
{
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
public BeatmapRulesetSelector RulesetSelector { get; private set; }
protected override ScreenTitle CreateTitle() => new BeatmapHeaderTitle();
protected override Drawable CreateTitleContent() => RulesetSelector = new BeatmapRulesetSelector
{
Current = Ruleset
};
private class BeatmapHeaderTitle : ScreenTitle
{
public BeatmapHeaderTitle()
{
Title = @"beatmap";
Section = @"info";
}
protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog");
}
}
}

View File

@ -26,11 +26,9 @@ namespace osu.Game.Overlays.BeatmapSet
public class Header : BeatmapDownloadTrackingComposite public class Header : BeatmapDownloadTrackingComposite
{ {
private const float transition_duration = 200; private const float transition_duration = 200;
private const float tabs_height = 50;
private const float buttons_height = 45; private const float buttons_height = 45;
private const float buttons_spacing = 5; private const float buttons_spacing = 5;
private readonly Box tabsBg;
private readonly UpdateableBeatmapSetCover cover; private readonly UpdateableBeatmapSetCover cover;
private readonly OsuSpriteText title, artist; private readonly OsuSpriteText title, artist;
private readonly AuthorInfo author; private readonly AuthorInfo author;
@ -41,14 +39,13 @@ namespace osu.Game.Overlays.BeatmapSet
public bool DownloadButtonsVisible => downloadButtonsContainer.Any(); public bool DownloadButtonsVisible => downloadButtonsContainer.Any();
public readonly BeatmapRulesetSelector RulesetSelector; public BeatmapRulesetSelector RulesetSelector => beatmapSetHeader.RulesetSelector;
public readonly BeatmapPicker Picker; public readonly BeatmapPicker Picker;
private readonly FavouriteButton favouriteButton; private readonly FavouriteButton favouriteButton;
private readonly FillFlowContainer fadeContent; private readonly FillFlowContainer fadeContent;
private readonly LoadingAnimation loading; private readonly LoadingAnimation loading;
private readonly BeatmapSetHeader beatmapSetHeader;
[Cached(typeof(IBindable<RulesetInfo>))] [Cached(typeof(IBindable<RulesetInfo>))]
private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>(); private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
@ -69,154 +66,145 @@ namespace osu.Game.Overlays.BeatmapSet
Offset = new Vector2(0f, 1f), Offset = new Vector2(0f, 1f),
}; };
InternalChildren = new Drawable[] InternalChild = new FillFlowContainer
{ {
new Container RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.X, beatmapSetHeader = new BeatmapSetHeader
Height = tabs_height,
Children = new Drawable[]
{ {
tabsBg = new Box Ruleset = { BindTarget = ruleset },
{
RelativeSizeAxes = Axes.Both,
},
RulesetSelector = new BeatmapRulesetSelector
{
Current = ruleset,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
}
}, },
}, new Container
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Top = tabs_height },
Children = new Drawable[]
{ {
new Container RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.Both, new Container
Children = new Drawable[]
{ {
cover = new UpdateableBeatmapSetCover RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.Both, cover = new UpdateableBeatmapSetCover
Masking = true,
},
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.3f), Color4.Black.Opacity(0.8f)),
},
},
},
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding
{
Top = 20,
Bottom = 30,
Left = BeatmapSetOverlay.X_PADDING,
Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH,
},
Children = new Drawable[]
{
fadeContent = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{ {
new Container RelativeSizeAxes = Axes.Both,
Masking = true,
},
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.3f), Color4.Black.Opacity(0.8f)),
},
},
},
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding
{
Top = 20,
Bottom = 30,
Left = BeatmapSetOverlay.X_PADDING,
Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH,
},
Children = new Drawable[]
{
fadeContent = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.X, new Container
AutoSizeAxes = Axes.Y,
Child = Picker = new BeatmapPicker(),
},
new FillFlowContainer
{
Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{ {
title = new OsuSpriteText RelativeSizeAxes = Axes.X,
{ AutoSizeAxes = Axes.Y,
Font = OsuFont.GetFont(size: 37, weight: FontWeight.Bold, italics: true) Child = Picker = new BeatmapPicker(),
}, },
externalLink = new ExternalLinkButton new FillFlowContainer
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Margin = new MarginPadding { Left = 3, Bottom = 4 }, //To better lineup with the font
},
}
},
artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.SemiBold, italics: true) },
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = 20 },
Child = author = new AuthorInfo(),
},
beatmapAvailability = new BeatmapAvailability(),
new Container
{
RelativeSizeAxes = Axes.X,
Height = buttons_height,
Margin = new MarginPadding { Top = 10 },
Children = new Drawable[]
{ {
favouriteButton = new FavouriteButton Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{ {
BeatmapSet = { BindTarget = BeatmapSet } title = new OsuSpriteText
}, {
downloadButtonsContainer = new FillFlowContainer Font = OsuFont.GetFont(size: 37, weight: FontWeight.Bold, italics: true)
},
externalLink = new ExternalLinkButton
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Margin = new MarginPadding { Left = 3, Bottom = 4 }, //To better lineup with the font
},
}
},
artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.SemiBold, italics: true) },
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = 20 },
Child = author = new AuthorInfo(),
},
beatmapAvailability = new BeatmapAvailability(),
new Container
{
RelativeSizeAxes = Axes.X,
Height = buttons_height,
Margin = new MarginPadding { Top = 10 },
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.Both, favouriteButton = new FavouriteButton
Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, {
Spacing = new Vector2(buttons_spacing), BeatmapSet = { BindTarget = BeatmapSet }
},
downloadButtonsContainer = new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = buttons_height + buttons_spacing },
Spacing = new Vector2(buttons_spacing),
},
}, },
}, },
}, },
}, },
}, }
} },
}, loading = new LoadingAnimation
loading = new LoadingAnimation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1.5f),
},
new FillFlowContainer
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Top = BeatmapSetOverlay.TOP_PADDING, Right = BeatmapSetOverlay.X_PADDING },
Direction = FillDirection.Vertical,
Spacing = new Vector2(10),
Children = new Drawable[]
{ {
onlineStatusPill = new BeatmapSetOnlineStatusPill Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1.5f),
},
new FillFlowContainer
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Top = BeatmapSetOverlay.TOP_PADDING, Right = BeatmapSetOverlay.X_PADDING },
Direction = FillDirection.Vertical,
Spacing = new Vector2(10),
Children = new Drawable[]
{ {
Anchor = Anchor.TopRight, onlineStatusPill = new BeatmapSetOnlineStatusPill
Origin = Anchor.TopRight, {
TextSize = 14, Anchor = Anchor.TopRight,
TextPadding = new MarginPadding { Horizontal = 25, Vertical = 8 } Origin = Anchor.TopRight,
TextSize = 14,
TextPadding = new MarginPadding { Horizontal = 25, Vertical = 8 }
},
Details = new Details(),
}, },
Details = new Details(),
}, },
}, },
}, },
}, }
}; };
Picker.Beatmap.ValueChanged += b => Picker.Beatmap.ValueChanged += b =>
@ -229,8 +217,6 @@ namespace osu.Game.Overlays.BeatmapSet
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
tabsBg.Colour = colours.Gray3;
State.BindValueChanged(_ => updateDownloadButtons()); State.BindValueChanged(_ => updateDownloadButtons());
BeatmapSet.BindValueChanged(setInfo => BeatmapSet.BindValueChanged(setInfo =>

View File

@ -24,6 +24,7 @@ namespace osu.Game.Overlays.BeatmapSet
private const float spacing = 20; private const float spacing = 20;
private readonly Box successRateBackground; private readonly Box successRateBackground;
private readonly Box background;
private readonly SuccessRate successRate; private readonly SuccessRate successRate;
public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>(); public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>();
@ -50,10 +51,9 @@ namespace osu.Game.Overlays.BeatmapSet
Children = new Drawable[] Children = new Drawable[]
{ {
new Box background = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both
Colour = Color4.White,
}, },
new Container new Container
{ {
@ -126,14 +126,14 @@ namespace osu.Game.Overlays.BeatmapSet
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
successRateBackground.Colour = colours.GrayE; successRateBackground.Colour = colourProvider.Background4;
background.Colour = colourProvider.Background5;
} }
private class MetadataSection : FillFlowContainer private class MetadataSection : FillFlowContainer
{ {
private readonly OsuSpriteText header;
private readonly TextFlowContainer textFlow; private readonly TextFlowContainer textFlow;
public string Text public string Text
@ -148,7 +148,7 @@ namespace osu.Game.Overlays.BeatmapSet
this.FadeIn(transition_duration); this.FadeIn(transition_duration);
textFlow.Clear(); textFlow.Clear();
textFlow.AddText(value, s => s.Font = s.Font.With(size: 14)); textFlow.AddText(value, s => s.Font = s.Font.With(size: 12));
} }
} }
@ -160,11 +160,10 @@ namespace osu.Game.Overlays.BeatmapSet
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
header = new OsuSpriteText new OsuSpriteText
{ {
Text = title, Text = title,
Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black),
Shadow = false,
Margin = new MarginPadding { Top = 20 }, Margin = new MarginPadding { Top = 20 },
}, },
textFlow = new OsuTextFlowContainer textFlow = new OsuTextFlowContainer
@ -174,12 +173,6 @@ namespace osu.Game.Overlays.BeatmapSet
}, },
}; };
} }
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
header.Colour = textFlow.Colour = colours.Gray5;
}
} }
} }
} }

View File

@ -7,8 +7,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Scoring; using osu.Game.Scoring;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -17,11 +15,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
public class DrawableTopScore : CompositeDrawable public class DrawableTopScore : CompositeDrawable
{ {
private const float fade_duration = 100;
private Color4 backgroundIdleColour;
private Color4 backgroundHoveredColour;
private readonly Box background; private readonly Box background;
public DrawableTopScore(ScoreInfo score, int position = 1) public DrawableTopScore(ScoreInfo score, int position = 1)
@ -30,7 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
Masking = true; Masking = true;
CornerRadius = 10; CornerRadius = 5;
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
{ {
Type = EdgeEffectType.Shadow, Type = EdgeEffectType.Shadow,
@ -84,24 +77,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
backgroundIdleColour = colours.Gray3; background.Colour = colourProvider.Background4;
backgroundHoveredColour = colours.Gray4;
background.Colour = backgroundIdleColour;
}
protected override bool OnHover(HoverEvent e)
{
background.FadeColour(backgroundHoveredColour, fade_duration, Easing.OutQuint);
return base.OnHover(e);
}
protected override void OnHoverLost(HoverLostEvent e)
{
background.FadeColour(backgroundIdleColour, fade_duration, Easing.OutQuint);
base.OnHoverLost(e);
} }
private class AutoSizingGrid : GridContainer private class AutoSizingGrid : GridContainer

View File

@ -23,7 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
private const float horizontal_inset = 20; private const float horizontal_inset = 20;
private const float row_height = 25; private const float row_height = 25;
private const int text_size = 14; private const int text_size = 12;
private readonly FillFlowContainer backgroundFlow; private readonly FillFlowContainer backgroundFlow;
@ -116,7 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
new OsuSpriteText new OsuSpriteText
{ {
Margin = new MarginPadding { Right = horizontal_inset }, Margin = new MarginPadding { Right = horizontal_inset },
Text = $@"{score.Accuracy:P2}", Text = score.DisplayAccuracy,
Font = OsuFont.GetFont(size: text_size), Font = OsuFont.GetFont(size: text_size),
Colour = score.Accuracy == 1 ? highAccuracyColour : Color4.White Colour = score.Accuracy == 1 ? highAccuracyColour : Color4.White
}, },
@ -190,7 +190,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
public HeaderText(string text) public HeaderText(string text)
{ {
Text = text.ToUpper(); Text = text.ToUpper();
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold);
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
Colour = colourProvider.Foreground1;
} }
} }
} }

View File

@ -48,18 +48,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, IAPIProvider api) private void load(OsuColour colours, OverlayColourProvider colourProvider, IAPIProvider api)
{ {
var isOwnScore = api.LocalUser.Value.Id == score.UserID; var isOwnScore = api.LocalUser.Value.Id == score.UserID;
if (isOwnScore) if (isOwnScore)
background.Colour = colours.GreenDarker; background.Colour = colours.GreenDarker;
else if (index % 2 == 0) else if (index % 2 == 0)
background.Colour = colours.Gray3; background.Colour = colourProvider.Background4;
else else
background.Alpha = 0; background.Alpha = 0;
hoveredBackground.Colour = isOwnScore ? colours.GreenDark : colours.Gray4; hoveredBackground.Colour = isOwnScore ? colours.GreenDark : colourProvider.Background3;
} }
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)

View File

@ -5,7 +5,6 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osuTK; using osuTK;
using System.Linq; using System.Linq;
@ -179,9 +178,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
background.Colour = colours.Gray2; background.Colour = colourProvider.Background5;
user.BindTo(api.LocalUser); user.BindTo(api.LocalUser);
} }

View File

@ -24,8 +24,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
private const float margin = 10; private const float margin = 10;
private readonly FontUsage smallFont = OsuFont.GetFont(size: 20); private readonly FontUsage smallFont = OsuFont.GetFont(size: 16);
private readonly FontUsage largeFont = OsuFont.GetFont(size: 25); private readonly FontUsage largeFont = OsuFont.GetFont(size: 22);
private readonly TextColumn totalScoreColumn; private readonly TextColumn totalScoreColumn;
private readonly TextColumn accuracyColumn; private readonly TextColumn accuracyColumn;
@ -92,7 +92,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
set set
{ {
totalScoreColumn.Text = $@"{value.TotalScore:N0}"; totalScoreColumn.Text = $@"{value.TotalScore:N0}";
accuracyColumn.Text = $@"{value.Accuracy:P2}"; accuracyColumn.Text = value.DisplayAccuracy;
maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; maxComboColumn.Text = $@"{value.MaxCombo:N0}x";
ppColumn.Text = $@"{value.PP:N0}"; ppColumn.Text = $@"{value.PP:N0}";
@ -109,6 +109,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private class InfoColumn : CompositeDrawable private class InfoColumn : CompositeDrawable
{ {
private readonly Box separator; private readonly Box separator;
private readonly OsuSpriteText text;
public InfoColumn(string title, Drawable content) public InfoColumn(string title, Drawable content)
{ {
@ -121,15 +122,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Spacing = new Vector2(0, 2), Spacing = new Vector2(0, 2),
Children = new[] Children = new[]
{ {
new OsuSpriteText text = new OsuSpriteText
{ {
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black), Font = OsuFont.GetFont(size: 10, weight: FontWeight.Black),
Text = title.ToUpper() Text = title.ToUpper()
}, },
separator = new Box separator = new Box
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 2 Height = 1
}, },
content content
} }
@ -137,9 +138,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
separator.Colour = colours.Gray5; separator.Colour = text.Colour = colourProvider.Foreground1;
} }
} }
@ -189,15 +190,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
set set
{ {
modsContainer.Clear(); modsContainer.Clear();
modsContainer.Children = value.Select(mod => new ModIcon(mod)
foreach (Mod mod in value)
{ {
modsContainer.Add(new ModIcon(mod) AutoSizeAxes = Axes.Both,
{ Scale = new Vector2(0.25f),
AutoSizeAxes = Axes.Both, }).ToList();
Scale = new Vector2(0.3f),
});
}
} }
} }
} }

View File

@ -1,7 +1,6 @@
// 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 osu.Framework.Allocation;
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;
@ -51,13 +50,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Font = OsuFont.GetFont(size: 24, weight: FontWeight.Bold, italics: true) Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold)
}, },
rank = new UpdateableRank(ScoreRank.D) rank = new UpdateableRank(ScoreRank.D)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(40), Size = new Vector2(28),
FillMode = FillMode.Fit, FillMode = FillMode.Fit,
}, },
} }
@ -66,7 +65,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(80), Size = new Vector2(70),
Masking = true, Masking = true,
CornerRadius = 5, CornerRadius = 5,
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
@ -87,7 +86,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Spacing = new Vector2(0, 3), Spacing = new Vector2(0, 3),
Children = new Drawable[] Children = new Drawable[]
{ {
usernameText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold, italics: true)) usernameText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true))
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
@ -97,13 +96,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold)
}, },
flag = new UpdateableFlag flag = new UpdateableFlag
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Size = new Vector2(20, 13), Size = new Vector2(19, 13),
ShowPlaceholderOnNull = false, ShowPlaceholderOnNull = false,
}, },
} }
@ -112,12 +111,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
}; };
} }
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
rankText.Colour = colours.Yellow;
}
public int ScorePosition public int ScorePosition
{ {
set => rankText.Text = $"#{value}"; set => rankText.Text = $"#{value}";

View File

@ -17,7 +17,7 @@ namespace osu.Game.Overlays.BeatmapSet
protected readonly FailRetryGraph Graph; protected readonly FailRetryGraph Graph;
private readonly FillFlowContainer header; private readonly FillFlowContainer header;
private readonly OsuSpriteText successRateLabel, successPercent, graphLabel; private readonly OsuSpriteText successPercent;
private readonly Bar successRate; private readonly Bar successRate;
private readonly Container percentContainer; private readonly Container percentContainer;
@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
successRateLabel = new OsuSpriteText new OsuSpriteText
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
@ -85,7 +85,7 @@ namespace osu.Game.Overlays.BeatmapSet
Font = OsuFont.GetFont(size: 13), Font = OsuFont.GetFont(size: 13),
}, },
}, },
graphLabel = new OsuSpriteText new OsuSpriteText
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
@ -107,7 +107,6 @@ namespace osu.Game.Overlays.BeatmapSet
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
successRateLabel.Colour = successPercent.Colour = graphLabel.Colour = colours.Gray5;
successRate.AccentColour = colours.Green; successRate.AccentColour = colours.Green;
successRate.BackgroundColour = colours.GrayD; successRate.BackgroundColour = colours.GrayD;

View File

@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet;
@ -33,6 +32,8 @@ namespace osu.Game.Overlays
// receive input outside our bounds so we can trigger a close event on ourselves. // receive input outside our bounds so we can trigger a close event on ourselves.
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
private readonly Box background;
public BeatmapSetOverlay() public BeatmapSetOverlay()
: base(OverlayColourScheme.Blue) : base(OverlayColourScheme.Blue)
{ {
@ -41,10 +42,9 @@ namespace osu.Game.Overlays
Children = new Drawable[] Children = new Drawable[]
{ {
new Box background = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both
Colour = OsuColour.Gray(0.2f)
}, },
scroll = new OsuScrollContainer scroll = new OsuScrollContainer
{ {
@ -55,10 +55,20 @@ namespace osu.Game.Overlays
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 20),
Children = new Drawable[] Children = new Drawable[]
{ {
Header = new Header(), new ReverseChildIDFillFlowContainer<Drawable>
info = new Info(), {
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
Header = new Header(),
info = new Info()
}
},
new ScoresContainer new ScoresContainer
{ {
Beatmap = { BindTarget = Header.Picker.Beatmap } Beatmap = { BindTarget = Header.Picker.Beatmap }
@ -83,6 +93,8 @@ namespace osu.Game.Overlays
private void load(RulesetStore rulesets) private void load(RulesetStore rulesets)
{ {
this.rulesets = rulesets; this.rulesets = rulesets;
background.Colour = ColourProvider.Background6;
} }
protected override void PopOutComplete() protected override void PopOutComplete()

View File

@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Changelog
{ {
public class ChangelogHeader : BreadcrumbControlOverlayHeader public class ChangelogHeader : BreadcrumbControlOverlayHeader
{ {
public readonly Bindable<APIChangelogBuild> Current = new Bindable<APIChangelogBuild>(); public readonly Bindable<APIChangelogBuild> Build = new Bindable<APIChangelogBuild>();
public Action ListingSelected; public Action ListingSelected;
@ -25,18 +25,18 @@ namespace osu.Game.Overlays.Changelog
public ChangelogHeader() public ChangelogHeader()
{ {
TabControl.AddItem(listing_string); TabControl.AddItem(listing_string);
TabControl.Current.ValueChanged += e => Current.ValueChanged += e =>
{ {
if (e.NewValue == listing_string) if (e.NewValue == listing_string)
ListingSelected?.Invoke(); ListingSelected?.Invoke();
}; };
Current.ValueChanged += showBuild; Build.ValueChanged += showBuild;
Streams.Current.ValueChanged += e => Streams.Current.ValueChanged += e =>
{ {
if (e.NewValue?.LatestBuild != null && !e.NewValue.Equals(Current.Value?.UpdateStream)) if (e.NewValue?.LatestBuild != null && !e.NewValue.Equals(Build.Value?.UpdateStream))
Current.Value = e.NewValue.LatestBuild; Build.Value = e.NewValue.LatestBuild;
}; };
} }
@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Changelog
if (e.NewValue != null) if (e.NewValue != null)
{ {
TabControl.AddItem(e.NewValue.ToString()); TabControl.AddItem(e.NewValue.ToString());
TabControl.Current.Value = e.NewValue.ToString(); Current.Value = e.NewValue.ToString();
updateCurrentStream(); updateCurrentStream();
@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Changelog
} }
else else
{ {
TabControl.Current.Value = listing_string; Current.Value = listing_string;
Streams.Current.Value = null; Streams.Current.Value = null;
title.Version = null; title.Version = null;
} }
@ -86,10 +86,10 @@ namespace osu.Game.Overlays.Changelog
private void updateCurrentStream() private void updateCurrentStream()
{ {
if (Current.Value == null) if (Build.Value == null)
return; return;
Streams.Current.Value = Streams.Items.FirstOrDefault(s => s.Name == Current.Value.UpdateStream.Name); Streams.Current.Value = Streams.Items.FirstOrDefault(s => s.Name == Build.Value.UpdateStream.Name);
} }
private class ChangelogHeaderTitle : ScreenTitle private class ChangelogHeaderTitle : ScreenTitle

View File

@ -78,7 +78,7 @@ namespace osu.Game.Overlays
sampleBack = audio.Samples.Get(@"UI/generic-select-soft"); sampleBack = audio.Samples.Get(@"UI/generic-select-soft");
Header.Current.BindTo(Current); Header.Build.BindTo(Current);
Current.BindValueChanged(e => Current.BindValueChanged(e =>
{ {

View File

@ -30,6 +30,8 @@ namespace osu.Game.Overlays.Mods
{ {
public class ModSelectOverlay : WaveOverlayContainer public class ModSelectOverlay : WaveOverlayContainer
{ {
public const float HEIGHT = 510;
protected readonly TriangleButton DeselectAllButton; protected readonly TriangleButton DeselectAllButton;
protected readonly TriangleButton CustomiseButton; protected readonly TriangleButton CustomiseButton;
protected readonly TriangleButton CloseButton; protected readonly TriangleButton CloseButton;
@ -66,7 +68,8 @@ namespace osu.Game.Overlays.Mods
Waves.ThirdWaveColour = OsuColour.FromHex(@"005774"); Waves.ThirdWaveColour = OsuColour.FromHex(@"005774");
Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e"); Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e");
Height = 510; RelativeSizeAxes = Axes.Both;
Padding = new MarginPadding { Horizontal = -OsuScreen.HORIZONTAL_OVERFLOW_PADDING }; Padding = new MarginPadding { Horizontal = -OsuScreen.HORIZONTAL_OVERFLOW_PADDING };
Children = new Drawable[] Children = new Drawable[]
@ -85,8 +88,7 @@ namespace osu.Game.Overlays.Mods
new Triangles new Triangles
{ {
TriangleScale = 5, TriangleScale = 5,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.Both,
Height = Height, //set the height from the start to ensure correct triangle density.
ColourLight = new Color4(53, 66, 82, 255), ColourLight = new Color4(53, 66, 82, 255),
ColourDark = new Color4(41, 54, 70, 255), ColourDark = new Color4(41, 54, 70, 255),
}, },

View File

@ -14,7 +14,7 @@ namespace osu.Game.Overlays.News
private NewsHeaderTitle title; private NewsHeaderTitle title;
public readonly Bindable<string> Current = new Bindable<string>(null); public readonly Bindable<string> Post = new Bindable<string>(null);
public Action ShowFrontPage; public Action ShowFrontPage;
@ -22,13 +22,13 @@ namespace osu.Game.Overlays.News
{ {
TabControl.AddItem(front_page_string); TabControl.AddItem(front_page_string);
TabControl.Current.ValueChanged += e => Current.ValueChanged += e =>
{ {
if (e.NewValue == front_page_string) if (e.NewValue == front_page_string)
ShowFrontPage?.Invoke(); ShowFrontPage?.Invoke();
}; };
Current.ValueChanged += showPost; Post.ValueChanged += showPost;
} }
private void showPost(ValueChangedEvent<string> e) private void showPost(ValueChangedEvent<string> e)
@ -39,13 +39,13 @@ namespace osu.Game.Overlays.News
if (e.NewValue != null) if (e.NewValue != null)
{ {
TabControl.AddItem(e.NewValue); TabControl.AddItem(e.NewValue);
TabControl.Current.Value = e.NewValue; Current.Value = e.NewValue;
title.IsReadingPost = true; title.IsReadingPost = true;
} }
else else
{ {
TabControl.Current.Value = front_page_string; Current.Value = front_page_string;
title.IsReadingPost = false; title.IsReadingPost = false;
} }
} }

View File

@ -60,7 +60,7 @@ namespace osu.Game.Overlays
}, },
}; };
header.Current.BindTo(Current); header.Post.BindTo(Current);
Current.TriggerChange(); Current.TriggerChange();
} }

View File

@ -61,12 +61,14 @@ namespace osu.Game.Overlays
Enabled.Value = true; Enabled.Value = true;
} }
[BackgroundDependencyLoader] protected override void LoadComplete()
private void load()
{ {
updateState(); base.LoadComplete();
Enabled.BindValueChanged(_ => updateState(), true);
} }
public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree;
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
{ {
base.OnHover(e); base.OnHover(e);
@ -87,7 +89,9 @@ namespace osu.Game.Overlays
private void updateState() private void updateState()
{ {
text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium);
AccentColour = IsHovered || Active.Value ? Color4.White : colourProvider.Highlight1; AccentColour = Enabled.Value ? getActiveColour() : colourProvider.Foreground1;
} }
private Color4 getActiveColour() => IsHovered || Active.Value ? Color4.White : colourProvider.Highlight1;
} }
} }

View File

@ -1,7 +1,6 @@
// 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 osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -178,7 +177,7 @@ namespace osu.Game.Overlays.Profile.Header
if (user?.Statistics != null) if (user?.Statistics != null)
{ {
userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0"))); userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0")));
userStats.Add(new UserStatsLine("Hit Accuracy", Math.Round(user.Statistics.Accuracy, 2).ToString("#0.00'%'"))); userStats.Add(new UserStatsLine("Hit Accuracy", user.Statistics.DisplayAccuracy));
userStats.Add(new UserStatsLine("Play Count", user.Statistics.PlayCount.ToString("#,##0"))); userStats.Add(new UserStatsLine("Play Count", user.Statistics.PlayCount.ToString("#,##0")));
userStats.Add(new UserStatsLine("Total Score", user.Statistics.TotalScore.ToString("#,##0"))); userStats.Add(new UserStatsLine("Total Score", user.Statistics.TotalScore.ToString("#,##0")));
userStats.Add(new UserStatsLine("Total Hits", user.Statistics.TotalHits.ToString("#,##0"))); userStats.Add(new UserStatsLine("Total Hits", user.Statistics.TotalHits.ToString("#,##0")));

View File

@ -182,7 +182,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
protected OsuSpriteText CreateDrawableAccuracy() => new OsuSpriteText protected OsuSpriteText CreateDrawableAccuracy() => new OsuSpriteText
{ {
Text = $"{Score.Accuracy:0.00%}", Text = Score.DisplayAccuracy,
Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true),
Colour = colours.Yellow, Colour = colours.Yellow,
}; };

View File

@ -76,9 +76,9 @@ namespace osu.Game.Overlays.Rankings
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
background.Colour = colours.GreySeafoam; background.Colour = colourProvider.Dark3;
} }
protected override void LoadComplete() protected override void LoadComplete()

View File

@ -100,9 +100,9 @@ namespace osu.Game.Overlays.Rankings
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
background.Colour = colours.GreySeafoamDarker; background.Colour = colourProvider.Background5;
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -154,9 +154,9 @@ namespace osu.Game.Overlays.Rankings
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
IdleColour = colours.GreySeafoamLighter; IdleColour = colourProvider.Light2;
HoverColour = Color4.White; HoverColour = Color4.White;
} }
} }

View File

@ -1,55 +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.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Users.Drawables;
using osuTK.Graphics;
using osuTK;
using osu.Framework.Input.Events;
using System;
namespace osu.Game.Overlays.Rankings
{
public class DismissableFlag : UpdateableFlag
{
private const int duration = 200;
public Action Action;
private readonly SpriteIcon hoverIcon;
public DismissableFlag()
{
AddInternal(hoverIcon = new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Depth = -1,
Alpha = 0,
Size = new Vector2(10),
Icon = FontAwesome.Solid.Times,
});
}
protected override bool OnHover(HoverEvent e)
{
hoverIcon.FadeIn(duration, Easing.OutQuint);
this.FadeColour(Color4.Gray, duration, Easing.OutQuint);
return base.OnHover(e);
}
protected override void OnHoverLost(HoverLostEvent e)
{
base.OnHoverLost(e);
hoverIcon.FadeOut(duration, Easing.OutQuint);
this.FadeColour(Color4.White, duration, Easing.OutQuint);
}
protected override bool OnClick(ClickEvent e)
{
Action?.Invoke();
return true;
}
}
}

View File

@ -1,91 +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.Bindables;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Users;
using osu.Framework.Graphics;
using osuTK;
using osu.Game.Graphics;
using osu.Framework.Allocation;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Overlays.Rankings
{
public class HeaderTitle : CompositeDrawable
{
private const int spacing = 10;
private const int flag_margin = 5;
private const int text_size = 40;
public readonly Bindable<RankingsScope> Scope = new Bindable<RankingsScope>();
public readonly Bindable<Country> Country = new Bindable<Country>();
private readonly SpriteText scopeText;
private readonly DismissableFlag flag;
public HeaderTitle()
{
AutoSizeAxes = Axes.Both;
InternalChild = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(spacing, 0),
Children = new Drawable[]
{
flag = new DismissableFlag
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Margin = new MarginPadding { Bottom = flag_margin },
Size = new Vector2(30, 20),
},
scopeText = new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light)
},
new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light),
Text = @"Ranking"
}
}
};
flag.Action += () => Country.Value = null;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
scopeText.Colour = colours.Lime;
}
protected override void LoadComplete()
{
Scope.BindValueChanged(onScopeChanged, true);
Country.BindValueChanged(onCountryChanged, true);
base.LoadComplete();
}
private void onScopeChanged(ValueChangedEvent<RankingsScope> scope) => scopeText.Text = scope.NewValue.ToString();
private void onCountryChanged(ValueChangedEvent<Country> country)
{
if (country.NewValue == null)
{
flag.Hide();
return;
}
flag.Country = country.NewValue;
flag.Show();
}
}
}

View File

@ -1,129 +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.Graphics.Containers;
using osu.Framework.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Rulesets;
using osu.Game.Users;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osuTK;
using osu.Game.Graphics.UserInterface;
using System.Collections.Generic;
namespace osu.Game.Overlays.Rankings
{
public class RankingsHeader : CompositeDrawable
{
private const int content_height = 250;
public IEnumerable<Spotlight> Spotlights
{
get => dropdown.Items;
set => dropdown.Items = value;
}
public readonly Bindable<RankingsScope> Scope = new Bindable<RankingsScope>();
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
public readonly Bindable<Country> Country = new Bindable<Country>();
public readonly Bindable<Spotlight> Spotlight = new Bindable<Spotlight>();
private readonly OsuDropdown<Spotlight> dropdown;
public RankingsHeader()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
AddInternal(new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new RankingsRulesetSelector
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Current = Ruleset
},
new Container
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
Height = content_height,
Children = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Child = new HeaderBackground(),
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 20),
Children = new Drawable[]
{
new RankingsScopeSelector
{
Margin = new MarginPadding { Top = 10 },
Current = Scope
},
new HeaderTitle
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Margin = new MarginPadding { Top = 10 },
Scope = { BindTarget = Scope },
Country = { BindTarget = Country },
},
dropdown = new OsuDropdown<Spotlight>
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
Width = 0.8f,
Current = Spotlight,
}
}
},
}
}
}
});
}
protected override void LoadComplete()
{
Scope.BindValueChanged(onScopeChanged, true);
base.LoadComplete();
}
private void onScopeChanged(ValueChangedEvent<RankingsScope> scope) =>
dropdown.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint);
private class HeaderBackground : Sprite
{
public HeaderBackground()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
FillMode = FillMode.Fill;
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
Texture = textures.Get(@"Headers/rankings");
}
}
}
}

View File

@ -0,0 +1,135 @@
// 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.Framework.Bindables;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets;
using osu.Game.Users;
using System.Collections.Generic;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Allocation;
namespace osu.Game.Overlays.Rankings
{
public class RankingsOverlayHeader : TabControlOverlayHeader<RankingsScope>
{
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
public readonly Bindable<Spotlight> Spotlight = new Bindable<Spotlight>();
public readonly Bindable<Country> Country = new Bindable<Country>();
public IEnumerable<Spotlight> Spotlights
{
get => spotlightsContainer.Spotlights;
set => spotlightsContainer.Spotlights = value;
}
protected override ScreenTitle CreateTitle() => new RankingsTitle
{
Scope = { BindTarget = Current }
};
protected override Drawable CreateTitleContent() => new OverlayRulesetSelector
{
Current = Ruleset
};
private SpotlightsContainer spotlightsContainer;
protected override Drawable CreateContent() => new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new CountryFilter
{
Current = Country
},
spotlightsContainer = new SpotlightsContainer
{
Spotlight = { BindTarget = Spotlight }
}
}
};
protected override void LoadComplete()
{
Current.BindValueChanged(onCurrentChanged, true);
base.LoadComplete();
}
private void onCurrentChanged(ValueChangedEvent<RankingsScope> scope) =>
spotlightsContainer.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint);
private class RankingsTitle : ScreenTitle
{
public readonly Bindable<RankingsScope> Scope = new Bindable<RankingsScope>();
public RankingsTitle()
{
Title = "ranking";
}
protected override void LoadComplete()
{
base.LoadComplete();
Scope.BindValueChanged(scope => Section = scope.NewValue.ToString().ToLowerInvariant(), true);
}
protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/rankings");
}
private class SpotlightsContainer : CompositeDrawable
{
public readonly Bindable<Spotlight> Spotlight = new Bindable<Spotlight>();
public IEnumerable<Spotlight> Spotlights
{
get => dropdown.Items;
set => dropdown.Items = value;
}
private readonly OsuDropdown<Spotlight> dropdown;
private readonly Box background;
public SpotlightsContainer()
{
Height = 100;
RelativeSizeAxes = Axes.X;
InternalChildren = new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both,
},
dropdown = new OsuDropdown<Spotlight>
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
Width = 0.8f,
Current = Spotlight,
Y = 20,
}
};
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
background.Colour = colourProvider.Dark3;
}
}
}
public enum RankingsScope
{
Performance,
Spotlights,
Score,
Country
}
}

View File

@ -1,56 +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.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets;
using osuTK;
using System.Linq;
namespace osu.Game.Overlays.Rankings
{
public class RankingsRulesetSelector : PageTabControl<RulesetInfo>
{
protected override TabItem<RulesetInfo> CreateTabItem(RulesetInfo value) => new RankingsTabItem(value);
protected override Dropdown<RulesetInfo> CreateDropdown() => null;
public RankingsRulesetSelector()
{
AutoSizeAxes = Axes.X;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, RulesetStore rulesets)
{
foreach (var r in rulesets.AvailableRulesets)
AddItem(r);
AccentColour = colours.Lime;
SelectTab(TabContainer.FirstOrDefault());
}
protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer
{
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(20, 0),
};
private class RankingsTabItem : PageTabItem
{
public RankingsTabItem(RulesetInfo value)
: base(value)
{
}
protected override string CreateText() => $"{Value.Name}";
}
}
}

View File

@ -1,26 +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.Game.Graphics.UserInterface;
using osu.Framework.Allocation;
using osuTK.Graphics;
namespace osu.Game.Overlays.Rankings
{
public class RankingsScopeSelector : GradientLineTabControl<RankingsScope>
{
[BackgroundDependencyLoader]
private void load()
{
AccentColour = LineColour = Color4.Black;
}
}
public enum RankingsScope
{
Performance,
Spotlights,
Score,
Country
}
}

View File

@ -0,0 +1,161 @@
// 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.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
using osuTK;
using System;
using System.Collections.Generic;
using osu.Framework.Graphics.UserInterface;
namespace osu.Game.Overlays.Rankings
{
public class SpotlightSelector : CompositeDrawable, IHasCurrentValue<APISpotlight>
{
private readonly Box background;
private readonly SpotlightsDropdown dropdown;
private readonly BindableWithCurrent<APISpotlight> current = new BindableWithCurrent<APISpotlight>();
public Bindable<APISpotlight> Current
{
get => current.Current;
set => current.Current = value;
}
public IEnumerable<APISpotlight> Spotlights
{
get => dropdown.Items;
set => dropdown.Items = value;
}
private readonly InfoColumn startDateColumn;
private readonly InfoColumn endDateColumn;
public SpotlightSelector()
{
RelativeSizeAxes = Axes.X;
Height = 100;
InternalChildren = new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 },
Children = new Drawable[]
{
dropdown = new SpotlightsDropdown
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
Current = Current,
Depth = -float.MaxValue
},
new FillFlowContainer
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(15, 0),
Children = new Drawable[]
{
startDateColumn = new InfoColumn(@"Start Date"),
endDateColumn = new InfoColumn(@"End Date"),
}
}
}
},
};
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
background.Colour = colourProvider.Dark3;
}
protected override void LoadComplete()
{
base.LoadComplete();
Current.BindValueChanged(onCurrentChanged);
}
private void onCurrentChanged(ValueChangedEvent<APISpotlight> spotlight)
{
startDateColumn.Value = dateToString(spotlight.NewValue.StartDate);
endDateColumn.Value = dateToString(spotlight.NewValue.EndDate);
}
private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd");
private class InfoColumn : FillFlowContainer
{
public string Value
{
set => valueText.Text = value;
}
private readonly OsuSpriteText valueText;
public InfoColumn(string name)
{
AutoSizeAxes = Axes.Both;
Direction = FillDirection.Vertical;
Children = new Drawable[]
{
new OsuSpriteText
{
Text = name,
Font = OsuFont.GetFont(size: 10),
},
new Container
{
AutoSizeAxes = Axes.X,
Height = 20,
Child = valueText = new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Font = OsuFont.GetFont(size: 18, weight: FontWeight.Light),
}
}
};
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
valueText.Colour = colourProvider.Content2;
}
}
private class SpotlightsDropdown : OsuDropdown<APISpotlight>
{
private DropdownMenu menu;
protected override DropdownMenu CreateMenu() => menu = base.CreateMenu().With(m => m.MaxHeight = 400);
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
menu.BackgroundColour = colourProvider.Background5;
AccentColour = colourProvider.Background6;
}
}
}
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Rankings.Tables
{ {
public abstract class RankingsTable<TModel> : TableContainer public abstract class RankingsTable<TModel> : TableContainer
{ {
protected const int TEXT_SIZE = 14; protected const int TEXT_SIZE = 12;
private const float horizontal_inset = 20; private const float horizontal_inset = 20;
private const float row_height = 25; private const float row_height = 25;
private const int items_per_page = 50; private const int items_per_page = 50;
@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Rankings.Tables
private static TableColumn[] mainHeaders => new[] private static TableColumn[] mainHeaders => new[]
{ {
new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 40)), // place
new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username (country name) new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username (country name)
}; };
@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Rankings.Tables
private OsuSpriteText createIndexDrawable(int index) => new OsuSpriteText private OsuSpriteText createIndexDrawable(int index) => new OsuSpriteText
{ {
Text = $"#{index + 1}", Text = $"#{index + 1}",
Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.SemiBold)
}; };
private FillFlowContainer createMainContent(TModel item) => new FillFlowContainer private FillFlowContainer createMainContent(TModel item) => new FillFlowContainer
@ -112,10 +112,10 @@ namespace osu.Game.Overlays.Rankings.Tables
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
if (Text != highlighted) if (Text != highlighted)
Colour = colours.GreySeafoamLighter; Colour = colourProvider.Foreground1;
} }
} }
@ -131,9 +131,9 @@ namespace osu.Game.Overlays.Rankings.Tables
protected class ColoredRowText : RowText protected class ColoredRowText : RowText
{ {
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
Colour = colours.GreySeafoamLighter; Colour = colourProvider.Foreground1;
} }
} }
} }

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Overlays.Rankings.Tables namespace osu.Game.Overlays.Rankings.Tables
@ -35,10 +34,10 @@ namespace osu.Game.Overlays.Rankings.Tables
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
background.Colour = idleColour = colours.GreySeafoam; background.Colour = idleColour = colourProvider.Background4;
hoverColour = colours.GreySeafoamLight; hoverColour = colourProvider.Background3;
} }
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)

View File

@ -40,7 +40,7 @@ namespace osu.Game.Overlays.Rankings.Tables
protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[]
{ {
new ColoredRowText { Text = $@"{item.Accuracy:F2}%", }, new ColoredRowText { Text = item.DisplayAccuracy, },
new ColoredRowText { Text = $@"{item.PlayCount:N0}", }, new ColoredRowText { Text = $@"{item.PlayCount:N0}", },
}.Concat(CreateUniqueContent(item)).Concat(new[] }.Concat(CreateUniqueContent(item)).Concat(new[]
{ {

View File

@ -6,7 +6,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Overlays.Rankings; using osu.Game.Overlays.Rankings;
using osu.Game.Users; using osu.Game.Users;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -27,6 +26,7 @@ namespace osu.Game.Overlays
private readonly BasicScrollContainer scrollFlow; private readonly BasicScrollContainer scrollFlow;
private readonly Container tableContainer; private readonly Container tableContainer;
private readonly DimmedLoadingLayer loading; private readonly DimmedLoadingLayer loading;
private readonly Box background;
private APIRequest lastRequest; private APIRequest lastRequest;
private CancellationTokenSource cancellationToken; private CancellationTokenSource cancellationToken;
@ -39,10 +39,9 @@ namespace osu.Game.Overlays
{ {
Children = new Drawable[] Children = new Drawable[]
{ {
new Box background = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both
Colour = OsuColour.Gray(0.1f),
}, },
scrollFlow = new BasicScrollContainer scrollFlow = new BasicScrollContainer
{ {
@ -55,12 +54,13 @@ namespace osu.Game.Overlays
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
new RankingsHeader new RankingsOverlayHeader
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Depth = -float.MaxValue,
Country = { BindTarget = Country }, Country = { BindTarget = Country },
Scope = { BindTarget = Scope }, Current = { BindTarget = Scope },
Ruleset = { BindTarget = ruleset } Ruleset = { BindTarget = ruleset }
}, },
new Container new Container
@ -86,6 +86,12 @@ namespace osu.Game.Overlays
}; };
} }
[BackgroundDependencyLoader]
private void load()
{
background.Colour = ColourProvider.Background5;
}
protected override void LoadComplete() protected override void LoadComplete()
{ {
Country.BindValueChanged(_ => Country.BindValueChanged(_ =>

View File

@ -3,6 +3,7 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -17,10 +18,18 @@ namespace osu.Game.Overlays
/// An overlay header which contains a <see cref="OsuTabControl{T}"/>. /// An overlay header which contains a <see cref="OsuTabControl{T}"/>.
/// </summary> /// </summary>
/// <typeparam name="T">The type of item to be represented by tabs.</typeparam> /// <typeparam name="T">The type of item to be represented by tabs.</typeparam>
public abstract class TabControlOverlayHeader<T> : OverlayHeader public abstract class TabControlOverlayHeader<T> : OverlayHeader, IHasCurrentValue<T>
{ {
protected OsuTabControl<T> TabControl; protected OsuTabControl<T> TabControl;
private readonly BindableWithCurrent<T> current = new BindableWithCurrent<T>();
public Bindable<T> Current
{
get => current.Current;
set => current.Current = value;
}
private readonly Box controlBackground; private readonly Box controlBackground;
protected TabControlOverlayHeader() protected TabControlOverlayHeader()
@ -35,7 +44,11 @@ namespace osu.Game.Overlays
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
TabControl = CreateTabControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) TabControl = CreateTabControl().With(control =>
{
control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN };
control.Current = Current;
})
} }
}); });
} }

View File

@ -13,6 +13,7 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Users; using osu.Game.Users;
using osu.Game.Utils;
namespace osu.Game.Scoring namespace osu.Game.Scoring
{ {
@ -31,6 +32,9 @@ namespace osu.Game.Scoring
[Column(TypeName = "DECIMAL(1,4)")] [Column(TypeName = "DECIMAL(1,4)")]
public double Accuracy { get; set; } public double Accuracy { get; set; }
[JsonIgnore]
public string DisplayAccuracy => Accuracy.FormatAccuracy();
[JsonProperty(@"pp")] [JsonProperty(@"pp")]
public double? PP { get; set; } public double? PP { get; set; }

View File

@ -28,7 +28,7 @@ namespace osu.Game.Screens.Multi.Match.Components
protected override IEnumerable<LeaderboardScoreStatistic> GetStatistics(ScoreInfo model) => new[] protected override IEnumerable<LeaderboardScoreStatistic> GetStatistics(ScoreInfo model) => new[]
{ {
new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:0%}" : @"{0:0.00%}", model.Accuracy)), new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", model.DisplayAccuracy),
new LeaderboardScoreStatistic(FontAwesome.Solid.Sync, "Total Attempts", score.TotalAttempts.ToString()), new LeaderboardScoreStatistic(FontAwesome.Solid.Sync, "Total Attempts", score.TotalAttempts.ToString()),
new LeaderboardScoreStatistic(FontAwesome.Solid.Check, "Completed Beatmaps", score.CompletedBeatmaps.ToString()), new LeaderboardScoreStatistic(FontAwesome.Solid.Check, "Completed Beatmaps", score.CompletedBeatmaps.ToString()),
}; };

View File

@ -14,18 +14,32 @@ using osuTK.Graphics;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
{ {
public class KeyCounterDisplay : FillFlowContainer<KeyCounter> public class KeyCounterDisplay : Container<KeyCounter>
{ {
private const int duration = 100; private const int duration = 100;
private const double key_fade_time = 80; private const double key_fade_time = 80;
public readonly Bindable<bool> Visible = new Bindable<bool>(true);
private readonly Bindable<bool> configVisibility = new Bindable<bool>(); private readonly Bindable<bool> configVisibility = new Bindable<bool>();
protected readonly FillFlowContainer<KeyCounter> KeyFlow;
protected override Container<KeyCounter> Content => KeyFlow;
/// <summary>
/// Whether the key counter should be visible regardless of the configuration value.
/// This is true by default, but can be changed.
/// </summary>
public readonly Bindable<bool> AlwaysVisible = new Bindable<bool>(true);
public KeyCounterDisplay() public KeyCounterDisplay()
{ {
Direction = FillDirection.Horizontal;
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
InternalChild = KeyFlow = new FillFlowContainer<KeyCounter>
{
Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both,
};
} }
public override void Add(KeyCounter key) public override void Add(KeyCounter key)
@ -49,7 +63,7 @@ namespace osu.Game.Screens.Play
{ {
base.LoadComplete(); base.LoadComplete();
Visible.BindValueChanged(_ => updateVisibility()); AlwaysVisible.BindValueChanged(_ => updateVisibility());
configVisibility.BindValueChanged(_ => updateVisibility(), true); configVisibility.BindValueChanged(_ => updateVisibility(), true);
} }
@ -100,7 +114,9 @@ namespace osu.Game.Screens.Play
} }
} }
private void updateVisibility() => this.FadeTo(Visible.Value || configVisibility.Value ? 1 : 0, duration); private void updateVisibility() =>
// Isolate changing visibility of the key counters from fading this component.
KeyFlow.FadeTo(AlwaysVisible.Value || configVisibility.Value ? 1 : 0, duration);
public override bool HandleNonPositionalInput => receptor == null; public override bool HandleNonPositionalInput => receptor == null;
public override bool HandlePositionalInput => receptor == null; public override bool HandlePositionalInput => receptor == null;

View File

@ -219,7 +219,7 @@ namespace osu.Game.Screens.Play
IsPaused = { BindTarget = GameplayClockContainer.IsPaused } IsPaused = { BindTarget = GameplayClockContainer.IsPaused }
}, },
PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } },
KeyCounter = { Visible = { BindTarget = DrawableRuleset.HasReplayLoaded } }, KeyCounter = { AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded } },
RequestSeek = GameplayClockContainer.Seek, RequestSeek = GameplayClockContainer.Seek,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre

View File

@ -211,7 +211,7 @@ namespace osu.Game.Screens.Ranking
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
Text = $"{Score.Accuracy:P2}", Text = Score.DisplayAccuracy,
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40),
RelativePositionAxes = Axes.X, RelativePositionAxes = Axes.X,
X = 0.9f, X = 0.9f,

View File

@ -32,8 +32,7 @@ namespace osu.Game.Screens.Select
BeatmapInfo beatmap = beatmapManager.QueryBeatmap(b => b.ID == score.BeatmapInfoID); BeatmapInfo beatmap = beatmapManager.QueryBeatmap(b => b.ID == score.BeatmapInfoID);
Debug.Assert(beatmap != null); Debug.Assert(beatmap != null);
string accuracy = string.Format(score.Accuracy == 1 ? "{0:0%}" : "{0:0.00%}", score.Accuracy); BodyText = $"{score.User} ({score.DisplayAccuracy}, {score.Rank})";
BodyText = $"{score.User} ({accuracy}, {score.Rank})";
Icon = FontAwesome.Regular.TrashAlt; Icon = FontAwesome.Regular.TrashAlt;
HeaderText = "Confirm deletion of local score"; HeaderText = "Confirm deletion of local score";

View File

@ -224,23 +224,37 @@ namespace osu.Game.Screens.Select
if (ShowFooter) if (ShowFooter)
{ {
AddRangeInternal(new[] AddRangeInternal(new Drawable[]
{ {
FooterPanels = new Container new GridContainer // used for max height implementation
{ {
Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both,
Origin = Anchor.BottomLeft, RowDimensions = new[]
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Bottom = Footer.HEIGHT },
Children = new Drawable[]
{ {
BeatmapOptions = new BeatmapOptionsOverlay(), new Dimension(),
ModSelect = new ModSelectOverlay new Dimension(GridSizeMode.Relative, 1f, maxSize: ModSelectOverlay.HEIGHT + Footer.HEIGHT),
},
Content = new[]
{
null,
new Drawable[]
{ {
RelativeSizeAxes = Axes.X, FooterPanels = new Container
Origin = Anchor.BottomCentre, {
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Bottom = Footer.HEIGHT },
Children = new Drawable[]
{
BeatmapOptions = new BeatmapOptionsOverlay(),
ModSelect = new ModSelectOverlay
{
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
}
}
}
} }
} }
}, },

View File

@ -4,6 +4,7 @@
using System; using System;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Utils;
using static osu.Game.Users.User; using static osu.Game.Users.User;
namespace osu.Game.Users namespace osu.Game.Users
@ -43,6 +44,9 @@ namespace osu.Game.Users
[JsonProperty(@"hit_accuracy")] [JsonProperty(@"hit_accuracy")]
public decimal Accuracy; public decimal Accuracy;
[JsonIgnore]
public string DisplayAccuracy => Accuracy.FormatAccuracy();
[JsonProperty(@"play_count")] [JsonProperty(@"play_count")]
public int PlayCount; public int PlayCount;

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.
namespace osu.Game.Utils
{
public static class FormatUtils
{
/// <summary>
/// Turns the provided accuracy into a percentage with 2 decimal places.
/// Omits all decimal places when <paramref name="accuracy"/> equals 1d.
/// </summary>
/// <param name="accuracy">The accuracy to be formatted</param>
/// <returns>formatted accuracy in percentage</returns>
public static string FormatAccuracy(this double accuracy) => accuracy == 1 ? "100%" : $"{accuracy:0.00%}";
/// <summary>
/// Turns the provided accuracy into a percentage with 2 decimal places.
/// Omits all decimal places when <paramref name="accuracy"/> equals 100m.
/// </summary>
/// <param name="accuracy">The accuracy to be formatted</param>
/// <returns>formatted accuracy in percentage</returns>
public static string FormatAccuracy(this decimal accuracy) => accuracy == 100 ? "100%" : $"{accuracy:0.00}%";
}
}