mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 15:12:57 +08:00
Merge branch 'master' into update-placement-more-often
This commit is contained in:
commit
4b7a053544
@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
public class CatchModDifficultyAdjust : ModDifficultyAdjust
|
||||
{
|
||||
[SettingSource("Fruit Size", "Override a beatmap's set CS.")]
|
||||
[SettingSource("Circle Size", "Override a beatmap's set CS.", FIRST_SETTING_ORDER - 1)]
|
||||
public BindableNumber<float> CircleSize { get; } = new BindableFloat
|
||||
{
|
||||
Precision = 0.1f,
|
||||
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
Value = 5,
|
||||
};
|
||||
|
||||
[SettingSource("Approach Rate", "Override a beatmap's set AR.")]
|
||||
[SettingSource("Approach Rate", "Override a beatmap's set AR.", LAST_SETTING_ORDER + 1)]
|
||||
public BindableNumber<float> ApproachRate { get; } = new BindableFloat
|
||||
{
|
||||
Precision = 0.1f,
|
||||
|
@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModDifficultyAdjust : ModDifficultyAdjust
|
||||
{
|
||||
[SettingSource("Circle Size", "Override a beatmap's set CS.")]
|
||||
[SettingSource("Circle Size", "Override a beatmap's set CS.", FIRST_SETTING_ORDER - 1)]
|
||||
public BindableNumber<float> CircleSize { get; } = new BindableFloat
|
||||
{
|
||||
Precision = 0.1f,
|
||||
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
Value = 5,
|
||||
};
|
||||
|
||||
[SettingSource("Approach Rate", "Override a beatmap's set AR.")]
|
||||
[SettingSource("Approach Rate", "Override a beatmap's set AR.", LAST_SETTING_ORDER + 1)]
|
||||
public BindableNumber<float> ApproachRate { get; } = new BindableFloat
|
||||
{
|
||||
Precision = 0.1f,
|
||||
|
@ -5,9 +5,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
|
||||
@ -22,6 +24,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private RatingsExposingDetails details;
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
@ -55,8 +60,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(),
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Status = BeatmapSetOnlineStatus.Ranked
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -5,11 +5,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
using osuTK;
|
||||
@ -26,6 +28,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private GraphExposingSuccessRate successRate;
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
|
@ -7,11 +7,16 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneLeaderboardScopeSelector : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(LeaderboardScopeSelector),
|
||||
|
@ -34,25 +34,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
Current = { BindTarget = scope },
|
||||
Country = { BindTarget = countryBindable },
|
||||
Ruleset = { BindTarget = ruleset },
|
||||
Spotlights = new[]
|
||||
{
|
||||
new Spotlight
|
||||
{
|
||||
Id = 1,
|
||||
Text = "Spotlight 1"
|
||||
},
|
||||
new Spotlight
|
||||
{
|
||||
Id = 2,
|
||||
Text = "Spotlight 2"
|
||||
},
|
||||
new Spotlight
|
||||
{
|
||||
Id = 3,
|
||||
Text = "Spotlight 3"
|
||||
}
|
||||
}
|
||||
Ruleset = { BindTarget = ruleset }
|
||||
});
|
||||
|
||||
var country = new Country
|
||||
|
@ -35,6 +35,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Add(selector = new SpotlightSelector());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVisibility()
|
||||
{
|
||||
AddStep("Toggle Visibility", selector.ToggleVisibility);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLocalSpotlights()
|
||||
{
|
||||
|
55
osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs
Normal file
55
osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Rankings;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneSpotlightsLayout : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(SpotlightsLayout),
|
||||
typeof(SpotlightSelector),
|
||||
};
|
||||
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Green);
|
||||
|
||||
public TestSceneSpotlightsLayout()
|
||||
{
|
||||
var ruleset = new Bindable<RulesetInfo>(new OsuRuleset().RulesetInfo);
|
||||
|
||||
Add(new BasicScrollContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.8f,
|
||||
Child = new SpotlightsLayout
|
||||
{
|
||||
Ruleset = { BindTarget = ruleset }
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("Osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo);
|
||||
AddStep("Mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo);
|
||||
AddStep("Taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo);
|
||||
AddStep("Catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -426,6 +427,44 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddAssert("start not requested", () => !startRequested);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestExternalBeatmapChangeWhileFiltered(bool differentRuleset)
|
||||
{
|
||||
createSongSelect();
|
||||
addManyTestMaps();
|
||||
|
||||
changeRuleset(0);
|
||||
|
||||
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap != null);
|
||||
|
||||
AddStep("set filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = "nonono");
|
||||
|
||||
AddUntilStep("dummy selected", () => Beatmap.Value is DummyWorkingBeatmap);
|
||||
|
||||
AddUntilStep("has no selection", () => songSelect.Carousel.SelectedBeatmap == null);
|
||||
|
||||
BeatmapInfo target = null;
|
||||
|
||||
AddStep("select beatmap externally", () =>
|
||||
{
|
||||
target = manager.GetAllUsableBeatmapSets().Where(b => b.Beatmaps.Any(bi => bi.RulesetID == (differentRuleset ? 1 : 0)))
|
||||
.ElementAt(5).Beatmaps.First();
|
||||
|
||||
Beatmap.Value = manager.GetWorkingBeatmap(target);
|
||||
});
|
||||
|
||||
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap != null);
|
||||
|
||||
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmap?.OnlineBeatmapID == target.OnlineBeatmapID);
|
||||
AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.OnlineBeatmapID == target.OnlineBeatmapID);
|
||||
|
||||
AddStep("reset filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = string.Empty);
|
||||
|
||||
AddAssert("game still correct", () => Beatmap.Value?.BeatmapInfo.OnlineBeatmapID == target.OnlineBeatmapID);
|
||||
AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmap.OnlineBeatmapID == target.OnlineBeatmapID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAutoplayViaCtrlEnter()
|
||||
{
|
||||
@ -468,6 +507,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait();
|
||||
|
||||
private static int importId;
|
||||
|
||||
private int getImportId() => ++importId;
|
||||
|
||||
private void checkMusicPlaying(bool playing) =>
|
||||
@ -551,6 +591,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
||||
|
||||
public new FilterControl FilterControl => base.FilterControl;
|
||||
|
||||
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
|
||||
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
|
||||
public new BeatmapCarousel Carousel => base.Carousel;
|
||||
|
40
osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs
Normal file
40
osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneModDisplay : OsuTestScene
|
||||
{
|
||||
[TestCase(ExpansionMode.ExpandOnHover)]
|
||||
[TestCase(ExpansionMode.AlwaysExpanded)]
|
||||
[TestCase(ExpansionMode.AlwaysContracted)]
|
||||
public void TestMode(ExpansionMode mode)
|
||||
{
|
||||
AddStep("create mod display", () =>
|
||||
{
|
||||
Child = new ModDisplay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
ExpansionMode = mode,
|
||||
Current =
|
||||
{
|
||||
Value = new Mod[]
|
||||
{
|
||||
new OsuModHardRock(),
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModDifficultyAdjust(),
|
||||
new OsuModEasy(),
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
public class BeatmapSetOnlineStatusPill : CircularContainer
|
||||
{
|
||||
private readonly OsuSpriteText statusText;
|
||||
private readonly Box background;
|
||||
|
||||
private BeatmapSetOnlineStatus status;
|
||||
|
||||
@ -43,6 +44,12 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
set => statusText.Padding = value;
|
||||
}
|
||||
|
||||
public Color4 BackgroundColour
|
||||
{
|
||||
get => background.Colour;
|
||||
set => background.Colour = value;
|
||||
}
|
||||
|
||||
public BeatmapSetOnlineStatusPill()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
@ -50,7 +57,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Bindables;
|
||||
@ -16,6 +17,10 @@ namespace osu.Game.Configuration
|
||||
/// An attribute to mark a bindable as being exposed to the user via settings controls.
|
||||
/// Can be used in conjunction with <see cref="SettingSourceExtensions.CreateSettingsControls"/> to automatically create UI controls.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All controls with <see cref="OrderPosition"/> set will be placed first in ascending order.
|
||||
/// All controls with no <see cref="OrderPosition"/> will come afterward in default order.
|
||||
/// </remarks>
|
||||
[MeansImplicitUse]
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class SettingSourceAttribute : Attribute
|
||||
@ -24,18 +29,26 @@ namespace osu.Game.Configuration
|
||||
|
||||
public string Description { get; }
|
||||
|
||||
public int? OrderPosition { get; }
|
||||
|
||||
public SettingSourceAttribute(string label, string description = null)
|
||||
{
|
||||
Label = label ?? string.Empty;
|
||||
Description = description ?? string.Empty;
|
||||
}
|
||||
|
||||
public SettingSourceAttribute(string label, string description, int orderPosition)
|
||||
: this(label, description)
|
||||
{
|
||||
OrderPosition = orderPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SettingSourceExtensions
|
||||
{
|
||||
public static IEnumerable<Drawable> CreateSettingsControls(this object obj)
|
||||
{
|
||||
foreach (var (attr, property) in obj.GetSettingsSourceProperties())
|
||||
foreach (var (attr, property) in obj.GetOrderedSettingsSourceProperties())
|
||||
{
|
||||
object value = property.GetValue(obj);
|
||||
|
||||
@ -116,5 +129,15 @@ namespace osu.Game.Configuration
|
||||
yield return (attr, property);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<(SettingSourceAttribute, PropertyInfo)> GetOrderedSettingsSourceProperties(this object obj)
|
||||
{
|
||||
var original = obj.GetSettingsSourceProperties();
|
||||
|
||||
var orderedRelative = original.Where(attr => attr.Item1.OrderPosition != null).OrderBy(attr => attr.Item1.OrderPosition);
|
||||
var unordered = original.Except(orderedRelative);
|
||||
|
||||
return orderedRelative.Concat(unordered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,14 +49,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
public GradientLine()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Size = new Vector2(0.8f, 1.5f);
|
||||
|
||||
ColumnDimensions = new[]
|
||||
{
|
||||
new Dimension(),
|
||||
new Dimension(mode: GridSizeMode.Relative, size: 0.4f),
|
||||
new Dimension(),
|
||||
};
|
||||
Size = new Vector2(0.8f, 1f);
|
||||
|
||||
Content = new[]
|
||||
{
|
||||
@ -65,16 +58,12 @@ namespace osu.Game.Graphics.UserInterface
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.White)
|
||||
Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Colour)
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.Transparent)
|
||||
Colour = ColourInfo.GradientHorizontal(Colour, Color4.Transparent)
|
||||
},
|
||||
}
|
||||
};
|
||||
|
@ -26,6 +26,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"end_date")]
|
||||
public DateTimeOffset EndDate;
|
||||
|
||||
[JsonProperty(@"participant_count")]
|
||||
public int? Participants;
|
||||
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = BeatmapSet.Value.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty,
|
||||
Text = getVideoSuffixText(),
|
||||
Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold)
|
||||
},
|
||||
};
|
||||
@ -163,5 +163,13 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
private void userChanged(ValueChangedEvent<User> e) => button.Enabled.Value = !(e.NewValue is GuestUser);
|
||||
|
||||
private void enabledChanged(ValueChangedEvent<bool> e) => this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint);
|
||||
|
||||
private string getVideoSuffixText()
|
||||
{
|
||||
if (!BeatmapSet.Value.OnlineInfo.HasVideo)
|
||||
return string.Empty;
|
||||
|
||||
return noVideo ? "without Video" : "with Video";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -14,7 +13,6 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
{
|
||||
@ -22,7 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
{
|
||||
private const float transition_duration = 500;
|
||||
|
||||
private readonly Box bg, progress;
|
||||
private readonly Box background, progress;
|
||||
private readonly PlayButton playButton;
|
||||
|
||||
private PreviewTrack preview => playButton.Preview;
|
||||
@ -40,10 +38,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
bg = new Box
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.25f),
|
||||
Alpha = 0.5f
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -71,9 +69,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, OverlayColourProvider colourProvider)
|
||||
{
|
||||
progress.Colour = colours.Yellow;
|
||||
background.Colour = colourProvider.Background6;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
@ -91,13 +90,13 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
bg.FadeColour(Color4.Black.Opacity(0.5f), 100);
|
||||
background.FadeTo(0.75f, 80);
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
bg.FadeColour(Color4.Black.Opacity(0.25f), 100);
|
||||
background.FadeTo(0.5f, 80);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -10,7 +9,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.BeatmapSet.Buttons;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
@ -21,6 +19,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private readonly PreviewButton preview;
|
||||
private readonly BasicStats basic;
|
||||
private readonly AdvancedStats advanced;
|
||||
private readonly DetailBox ratingBox;
|
||||
|
||||
private BeatmapSetInfo beatmapSet;
|
||||
|
||||
@ -54,6 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private void updateDisplay()
|
||||
{
|
||||
Ratings.Metrics = BeatmapSet?.Metrics;
|
||||
ratingBox.Alpha = BeatmapSet?.OnlineInfo?.Status > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
public Details()
|
||||
@ -86,7 +86,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Margin = new MarginPadding { Vertical = 7.5f },
|
||||
},
|
||||
},
|
||||
new DetailBox
|
||||
ratingBox = new DetailBox
|
||||
{
|
||||
Child = Ratings = new UserRatings
|
||||
{
|
||||
@ -107,6 +107,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private class DetailBox : Container
|
||||
{
|
||||
private readonly Container content;
|
||||
private readonly Box background;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
public DetailBox()
|
||||
@ -116,10 +118,10 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.5f),
|
||||
Alpha = 0.5f
|
||||
},
|
||||
content = new Container
|
||||
{
|
||||
@ -129,6 +131,12 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
background.Colour = colourProvider.Background6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
|
||||
using System.Linq;
|
||||
@ -30,6 +30,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private const float buttons_spacing = 5;
|
||||
|
||||
private readonly UpdateableBeatmapSetCover cover;
|
||||
private readonly Box coverGradient;
|
||||
private readonly OsuSpriteText title, artist;
|
||||
private readonly AuthorInfo author;
|
||||
private readonly FillFlowContainer downloadButtonsContainer;
|
||||
@ -93,10 +94,9 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
},
|
||||
new Box
|
||||
coverGradient = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.3f), Color4.Black.Opacity(0.8f)),
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -106,8 +106,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = 20,
|
||||
Bottom = 30,
|
||||
Vertical = BeatmapSetOverlay.Y_PADDING,
|
||||
Left = BeatmapSetOverlay.X_PADDING,
|
||||
Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH,
|
||||
},
|
||||
@ -130,11 +129,12 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Top = 15 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
title = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 37, weight: FontWeight.Bold, italics: true)
|
||||
Font = OsuFont.GetFont(size: 30, weight: FontWeight.SemiBold, italics: true)
|
||||
},
|
||||
externalLink = new ExternalLinkButton
|
||||
{
|
||||
@ -144,7 +144,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
},
|
||||
}
|
||||
},
|
||||
artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.SemiBold, italics: true) },
|
||||
artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true) },
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
@ -187,7 +187,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Top = BeatmapSetOverlay.TOP_PADDING, Right = BeatmapSetOverlay.X_PADDING },
|
||||
Margin = new MarginPadding { Top = BeatmapSetOverlay.Y_PADDING, Right = BeatmapSetOverlay.X_PADDING },
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(10),
|
||||
Children = new Drawable[]
|
||||
@ -197,7 +197,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
TextSize = 14,
|
||||
TextPadding = new MarginPadding { Horizontal = 25, Vertical = 8 }
|
||||
TextPadding = new MarginPadding { Horizontal = 35, Vertical = 10 }
|
||||
},
|
||||
Details = new Details(),
|
||||
},
|
||||
@ -215,8 +215,11 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
coverGradient.Colour = ColourInfo.GradientVertical(colourProvider.Background6.Opacity(0.3f), colourProvider.Background6.Opacity(0.8f));
|
||||
onlineStatusPill.BackgroundColour = colourProvider.Background6;
|
||||
|
||||
State.BindValueChanged(_ => updateDownloadButtons());
|
||||
|
||||
BeatmapSet.BindValueChanged(setInfo =>
|
||||
|
@ -38,6 +38,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
public Info()
|
||||
{
|
||||
MetadataSection source, tags, genre, language;
|
||||
OsuSpriteText unrankedPlaceholder;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 220;
|
||||
Masking = true;
|
||||
@ -110,6 +112,14 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = 20, Horizontal = 15 },
|
||||
},
|
||||
unrankedPlaceholder = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
Text = "Unranked beatmap",
|
||||
Font = OsuFont.GetFont(size: 12)
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -122,6 +132,9 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty;
|
||||
genre.Text = b.NewValue?.OnlineInfo?.Genre?.Name ?? string.Empty;
|
||||
language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? string.Empty;
|
||||
var setHasLeaderboard = b.NewValue?.OnlineInfo?.Status > 0;
|
||||
successRate.Alpha = setHasLeaderboard ? 1 : 0;
|
||||
unrankedPlaceholder.Alpha = setHasLeaderboard ? 0 : 1;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,10 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
AccentColour = colours.Blue;
|
||||
LineColour = Color4.Gray;
|
||||
AccentColour = colourProvider.Highlight1;
|
||||
LineColour = colourProvider.Background1;
|
||||
}
|
||||
|
||||
private class ScopeSelectorTabItem : PageTabItem
|
||||
|
@ -77,9 +77,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
new TableColumn("rank", Anchor.CentreRight, new Dimension(GridSizeMode.AutoSize)),
|
||||
new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), // grade
|
||||
new TableColumn("score", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)),
|
||||
new TableColumn("accuracy", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)),
|
||||
new TableColumn("accuracy", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 60, maxSize: 70)),
|
||||
new TableColumn("player", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 150)),
|
||||
new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 90))
|
||||
new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 110))
|
||||
};
|
||||
|
||||
foreach (var statistic in score.SortedStatistics)
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 25;
|
||||
|
||||
CornerRadius = 3;
|
||||
CornerRadius = 5;
|
||||
Masking = true;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
|
@ -164,7 +164,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = 10,
|
||||
CornerRadius = 5,
|
||||
Child = loading = new DimmedLoadingLayer(iconScale: 0.8f)
|
||||
{
|
||||
Alpha = 0,
|
||||
|
@ -96,13 +96,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold)
|
||||
Font = OsuFont.GetFont(size: 10)
|
||||
},
|
||||
flag = new UpdateableFlag
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Size = new Vector2(19, 13),
|
||||
Margin = new MarginPadding { Top = 3 }, // makes spacing look more even
|
||||
ShowPlaceholderOnNull = false,
|
||||
},
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
int playCount = beatmap?.OnlineInfo?.PlayCount ?? 0;
|
||||
|
||||
var rate = playCount != 0 ? (float)passCount / playCount : 0;
|
||||
successPercent.Text = rate.ToString("0%");
|
||||
successPercent.Text = rate.ToString("0.#%");
|
||||
successRate.Length = rate;
|
||||
percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic);
|
||||
|
||||
@ -105,10 +105,10 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, OverlayColourProvider colourProvider)
|
||||
{
|
||||
successRate.AccentColour = colours.Green;
|
||||
successRate.BackgroundColour = colours.GrayD;
|
||||
successRate.BackgroundColour = colourProvider.Background6;
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Overlays
|
||||
public class BeatmapSetOverlay : FullscreenOverlay
|
||||
{
|
||||
public const float X_PADDING = 40;
|
||||
public const float TOP_PADDING = 25;
|
||||
public const float Y_PADDING = 25;
|
||||
public const float RIGHT_WIDTH = 275;
|
||||
protected readonly Header Header;
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Direct
|
||||
public DownloadProgressBar(BeatmapSetInfo beatmapSet)
|
||||
: base(beatmapSet)
|
||||
{
|
||||
AddInternal(progressBar = new ProgressBar
|
||||
AddInternal(progressBar = new InteractionDisabledProgressBar
|
||||
{
|
||||
Height = 0,
|
||||
Alpha = 0,
|
||||
@ -64,5 +64,11 @@ namespace osu.Game.Overlays.Direct
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
private class InteractionDisabledProgressBar : ProgressBar
|
||||
{
|
||||
public override bool HandlePositionalInput => false;
|
||||
public override bool HandleNonPositionalInput => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,25 +6,14 @@ 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 }
|
||||
@ -35,35 +24,11 @@ namespace osu.Game.Overlays.Rankings
|
||||
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
|
||||
protected override Drawable CreateContent() => 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>();
|
||||
@ -81,48 +46,6 @@ namespace osu.Game.Overlays.Rankings
|
||||
|
||||
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
|
||||
|
@ -1,18 +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 Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
public class Spotlight
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id;
|
||||
|
||||
[JsonProperty("text")]
|
||||
public string Text;
|
||||
|
||||
public override string ToString() => Text;
|
||||
}
|
||||
}
|
@ -14,11 +14,14 @@ using osuTK;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
public class SpotlightSelector : CompositeDrawable, IHasCurrentValue<APISpotlight>
|
||||
public class SpotlightSelector : VisibilityContainer, IHasCurrentValue<APISpotlight>
|
||||
{
|
||||
private const int duration = 300;
|
||||
|
||||
private readonly Box background;
|
||||
private readonly SpotlightsDropdown dropdown;
|
||||
|
||||
@ -36,15 +39,22 @@ namespace osu.Game.Overlays.Rankings
|
||||
set => dropdown.Items = value;
|
||||
}
|
||||
|
||||
protected override bool StartHidden => true;
|
||||
|
||||
private readonly InfoColumn startDateColumn;
|
||||
private readonly InfoColumn endDateColumn;
|
||||
private readonly InfoColumn mapCountColumn;
|
||||
private readonly InfoColumn participantsColumn;
|
||||
private readonly Container content;
|
||||
|
||||
public SpotlightSelector()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 100;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
Add(content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
@ -75,11 +85,14 @@ namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
startDateColumn = new InfoColumn(@"Start Date"),
|
||||
endDateColumn = new InfoColumn(@"End Date"),
|
||||
mapCountColumn = new InfoColumn(@"Map Count"),
|
||||
participantsColumn = new InfoColumn(@"Participants")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -88,18 +101,17 @@ namespace osu.Game.Overlays.Rankings
|
||||
background.Colour = colourProvider.Dark3;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
public void ShowInfo(GetSpotlightRankingsResponse response)
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Current.BindValueChanged(onCurrentChanged);
|
||||
startDateColumn.Value = dateToString(response.Spotlight.StartDate);
|
||||
endDateColumn.Value = dateToString(response.Spotlight.EndDate);
|
||||
mapCountColumn.Value = response.BeatmapSets.Count.ToString();
|
||||
participantsColumn.Value = response.Spotlight.Participants?.ToString("N0");
|
||||
}
|
||||
|
||||
private void onCurrentChanged(ValueChangedEvent<APISpotlight> spotlight)
|
||||
{
|
||||
startDateColumn.Value = dateToString(spotlight.NewValue.StartDate);
|
||||
endDateColumn.Value = dateToString(spotlight.NewValue.EndDate);
|
||||
}
|
||||
protected override void PopIn() => content.FadeIn(duration, Easing.OutQuint);
|
||||
|
||||
protected override void PopOut() => content.FadeOut(duration, Easing.OutQuint);
|
||||
|
||||
private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd");
|
||||
|
||||
|
161
osu.Game/Overlays/Rankings/SpotlightsLayout.cs
Normal file
161
osu.Game/Overlays/Rankings/SpotlightsLayout.cs
Normal 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.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osuTK;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Overlays.Rankings.Tables;
|
||||
using System.Linq;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using System.Threading;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
public class SpotlightsLayout : CompositeDrawable
|
||||
{
|
||||
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
private readonly Bindable<APISpotlight> selectedSpotlight = new Bindable<APISpotlight>();
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
private CancellationTokenSource cancellationToken;
|
||||
private GetSpotlightRankingsRequest getRankingsRequest;
|
||||
private GetSpotlightsRequest spotlightsRequest;
|
||||
|
||||
private SpotlightSelector selector;
|
||||
private Container content;
|
||||
private DimmedLoadingLayer loading;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
InternalChild = new ReverseChildIDFillFlowContainer<Drawable>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
selector = new SpotlightSelector
|
||||
{
|
||||
Current = selectedSpotlight,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding { Vertical = 10 }
|
||||
},
|
||||
loading = new DimmedLoadingLayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
selector.Show();
|
||||
|
||||
selectedSpotlight.BindValueChanged(onSpotlightChanged);
|
||||
Ruleset.BindValueChanged(onRulesetChanged);
|
||||
|
||||
getSpotlights();
|
||||
}
|
||||
|
||||
private void getSpotlights()
|
||||
{
|
||||
spotlightsRequest = new GetSpotlightsRequest();
|
||||
spotlightsRequest.Success += response => selector.Spotlights = response.Spotlights;
|
||||
api.Queue(spotlightsRequest);
|
||||
}
|
||||
|
||||
private void onRulesetChanged(ValueChangedEvent<RulesetInfo> ruleset)
|
||||
{
|
||||
if (!selector.Spotlights.Any())
|
||||
return;
|
||||
|
||||
selectedSpotlight.TriggerChange();
|
||||
}
|
||||
|
||||
private void onSpotlightChanged(ValueChangedEvent<APISpotlight> spotlight)
|
||||
{
|
||||
loading.Show();
|
||||
|
||||
cancellationToken?.Cancel();
|
||||
getRankingsRequest?.Cancel();
|
||||
|
||||
getRankingsRequest = new GetSpotlightRankingsRequest(Ruleset.Value, spotlight.NewValue.Id);
|
||||
getRankingsRequest.Success += onSuccess;
|
||||
api.Queue(getRankingsRequest);
|
||||
}
|
||||
|
||||
private void onSuccess(GetSpotlightRankingsResponse response)
|
||||
{
|
||||
LoadComponentAsync(createContent(response), loaded =>
|
||||
{
|
||||
selector.ShowInfo(response);
|
||||
|
||||
content.Clear();
|
||||
content.Add(loaded);
|
||||
|
||||
loading.Hide();
|
||||
}, (cancellationToken = new CancellationTokenSource()).Token);
|
||||
}
|
||||
|
||||
private Drawable createContent(GetSpotlightRankingsResponse response) => new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ScoresTable(1, response.Users),
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Spacing = new Vector2(10),
|
||||
Children = response.BeatmapSets.Select(b => new DirectGridPanel(b.ToBeatmapSet(rulesets))
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
}).ToList()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
spotlightsRequest?.Cancel();
|
||||
getRankingsRequest?.Cancel();
|
||||
cancellationToken?.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ namespace osu.Game.Overlays
|
||||
private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
private readonly BasicScrollContainer scrollFlow;
|
||||
private readonly Container tableContainer;
|
||||
private readonly Container contentContainer;
|
||||
private readonly DimmedLoadingLayer loading;
|
||||
private readonly Box background;
|
||||
|
||||
@ -69,13 +69,13 @@ namespace osu.Game.Overlays
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
tableContainer = new Container
|
||||
contentContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Margin = new MarginPadding { Vertical = 10 }
|
||||
Margin = new MarginPadding { Bottom = 10 }
|
||||
},
|
||||
loading = new DimmedLoadingLayer(),
|
||||
}
|
||||
@ -112,7 +112,13 @@ namespace osu.Game.Overlays
|
||||
Scheduler.AddOnce(loadNewContent);
|
||||
}, true);
|
||||
|
||||
ruleset.BindValueChanged(_ => Scheduler.AddOnce(loadNewContent), true);
|
||||
ruleset.BindValueChanged(_ =>
|
||||
{
|
||||
if (Scope.Value == RankingsScope.Spotlights)
|
||||
return;
|
||||
|
||||
Scheduler.AddOnce(loadNewContent);
|
||||
}, true);
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
@ -134,17 +140,26 @@ namespace osu.Game.Overlays
|
||||
cancellationToken?.Cancel();
|
||||
lastRequest?.Cancel();
|
||||
|
||||
if (Scope.Value == RankingsScope.Spotlights)
|
||||
{
|
||||
loadContent(new SpotlightsLayout
|
||||
{
|
||||
Ruleset = { BindTarget = ruleset }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var request = createScopedRequest();
|
||||
lastRequest = request;
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
loadTable(null);
|
||||
loadContent(null);
|
||||
return;
|
||||
}
|
||||
|
||||
request.Success += () => loadTable(createTableFromResponse(request));
|
||||
request.Failure += _ => loadTable(null);
|
||||
request.Success += () => loadContent(createTableFromResponse(request));
|
||||
request.Failure += _ => loadContent(null);
|
||||
|
||||
api.Queue(request);
|
||||
}
|
||||
@ -189,21 +204,21 @@ namespace osu.Game.Overlays
|
||||
return null;
|
||||
}
|
||||
|
||||
private void loadTable(Drawable table)
|
||||
private void loadContent(Drawable content)
|
||||
{
|
||||
scrollFlow.ScrollToStart();
|
||||
|
||||
if (table == null)
|
||||
if (content == null)
|
||||
{
|
||||
tableContainer.Clear();
|
||||
contentContainer.Clear();
|
||||
loading.Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
LoadComponentAsync(table, t =>
|
||||
LoadComponentAsync(content, loaded =>
|
||||
{
|
||||
loading.Hide();
|
||||
tableContainer.Child = table;
|
||||
contentContainer.Child = loaded;
|
||||
}, (cancellationToken = new CancellationTokenSource()).Token);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,11 @@ namespace osu.Game.Rulesets.Mods
|
||||
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) };
|
||||
|
||||
[SettingSource("Drain Rate", "Override a beatmap's set HP.")]
|
||||
protected const int FIRST_SETTING_ORDER = 1;
|
||||
|
||||
protected const int LAST_SETTING_ORDER = 2;
|
||||
|
||||
[SettingSource("HP Drain", "Override a beatmap's set HP.", FIRST_SETTING_ORDER)]
|
||||
public BindableNumber<float> DrainRate { get; } = new BindableFloat
|
||||
{
|
||||
Precision = 0.1f,
|
||||
@ -38,7 +42,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
Value = 5,
|
||||
};
|
||||
|
||||
[SettingSource("Overall Difficulty", "Override a beatmap's set OD.")]
|
||||
[SettingSource("Accuracy", "Override a beatmap's set OD.", LAST_SETTING_ORDER)]
|
||||
public BindableNumber<float> OverallDifficulty { get; } = new BindableFloat
|
||||
{
|
||||
Precision = 0.1f,
|
||||
|
@ -6,10 +6,13 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
{
|
||||
@ -52,6 +55,45 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
HoverColour = OsuColour.Gray(0.25f);
|
||||
FlashColour = OsuColour.Gray(0.5f);
|
||||
}
|
||||
|
||||
private ScheduledDelegate repeatSchedule;
|
||||
|
||||
/// <summary>
|
||||
/// The initial delay before mouse down repeat begins.
|
||||
/// </summary>
|
||||
private const int repeat_initial_delay = 250;
|
||||
|
||||
/// <summary>
|
||||
/// The delay between mouse down repeats after the initial repeat.
|
||||
/// </summary>
|
||||
private const int repeat_tick_rate = 70;
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
// don't actuate a click since we are manually handling repeats.
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
if (e.Button == MouseButton.Left)
|
||||
{
|
||||
Action clickAction = () => base.OnClick(new ClickEvent(e.CurrentState, e.Button));
|
||||
|
||||
// run once for initial down
|
||||
clickAction();
|
||||
|
||||
Scheduler.Add(repeatSchedule = new ScheduledDelegate(clickAction, Clock.CurrentTime + repeat_initial_delay, repeat_tick_rate));
|
||||
}
|
||||
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
repeatSchedule?.Cancel();
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
public bool DisplayUnrankedText = true;
|
||||
|
||||
public bool AllowExpand = true;
|
||||
public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover;
|
||||
|
||||
private readonly Bindable<IReadOnlyList<Mod>> current = new Bindable<IReadOnlyList<Mod>>();
|
||||
|
||||
@ -110,11 +110,15 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
private void expand()
|
||||
{
|
||||
if (AllowExpand)
|
||||
if (ExpansionMode != ExpansionMode.AlwaysContracted)
|
||||
IconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void contract() => IconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint);
|
||||
private void contract()
|
||||
{
|
||||
if (ExpansionMode != ExpansionMode.AlwaysExpanded)
|
||||
IconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
@ -128,4 +132,22 @@ namespace osu.Game.Screens.Play.HUD
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
}
|
||||
|
||||
public enum ExpansionMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ModDisplay"/> will expand only when hovered.
|
||||
/// </summary>
|
||||
ExpandOnHover,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ModDisplay"/> will always be expanded.
|
||||
/// </summary>
|
||||
AlwaysExpanded,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ModDisplay"/> will always be contracted.
|
||||
/// </summary>
|
||||
AlwaysContracted
|
||||
}
|
||||
}
|
||||
|
@ -229,6 +229,17 @@ namespace osu.Game.Screens.Select
|
||||
if (item != null)
|
||||
{
|
||||
select(item);
|
||||
|
||||
// if we got here and the set is filtered, it means we were bypassing filters.
|
||||
// in this case, reapplying the filter is necessary to ensure the panel is in the correct place
|
||||
// (since it is forcefully being included in the carousel).
|
||||
if (set.Filtered.Value)
|
||||
{
|
||||
Debug.Assert(bypassFilters);
|
||||
|
||||
applyActiveCriteria(false, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
/// <summary>
|
||||
/// All beatmaps which are not filtered and valid for display.
|
||||
/// </summary>
|
||||
protected IEnumerable<BeatmapInfo> ValidBeatmaps => Beatmaps.Where(b => !b.Filtered.Value).Select(b => b.Beatmap);
|
||||
protected IEnumerable<BeatmapInfo> ValidBeatmaps => Beatmaps.Where(b => !b.Filtered.Value || b.State.Value == CarouselItemState.Selected).Select(b => b.Beatmap);
|
||||
|
||||
private int compareUsingAggregateMax(CarouselBeatmapSet other, Func<BeatmapInfo, double> func)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
/// <summary>
|
||||
/// This item is not in a hidden state.
|
||||
/// </summary>
|
||||
public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered.Value;
|
||||
public bool Visible => State.Value == CarouselItemState.Selected || (State.Value != CarouselItemState.Collapsed && !Filtered.Value);
|
||||
|
||||
public virtual List<DrawableCarouselItem> Drawables
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
public FooterModDisplay()
|
||||
{
|
||||
AllowExpand = false;
|
||||
ExpansionMode = ExpansionMode.AlwaysContracted;
|
||||
IconsContainer.Margin = new MarginPadding();
|
||||
}
|
||||
}
|
||||
|
@ -376,16 +376,22 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
private void workingBeatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
|
||||
{
|
||||
if (e.NewValue is DummyWorkingBeatmap) return;
|
||||
if (e.NewValue is DummyWorkingBeatmap || !this.IsCurrentScreen()) return;
|
||||
|
||||
if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false))
|
||||
if (!Carousel.SelectBeatmap(e.NewValue.BeatmapInfo, false))
|
||||
{
|
||||
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
|
||||
if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value))
|
||||
// A selection may not have been possible with filters applied.
|
||||
|
||||
// There was possibly a ruleset mismatch. This is a case we can help things along by updating the game-wide ruleset to match.
|
||||
if (e.NewValue.BeatmapInfo.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value))
|
||||
{
|
||||
Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset;
|
||||
Carousel.SelectBeatmap(e.NewValue.BeatmapInfo);
|
||||
transferRulesetValue();
|
||||
}
|
||||
|
||||
// Even if a ruleset mismatch was not the cause (ie. a text filter is applied),
|
||||
// we still want to forcefully show the new beatmap, bypassing filters.
|
||||
Carousel.SelectBeatmap(e.NewValue.BeatmapInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user