Merge remote-tracking branch 'origin/master' into slider-controlpoint-deletion

# Conflicts:
#	osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
This commit is contained in:
smoogipoo
2019-11-05 13:07:06 +09:00
14 changed files with 375 additions and 269 deletions

View File

@ -29,8 +29,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
private readonly Container marker; private readonly Container marker;
private readonly Drawable markerRing; private readonly Drawable markerRing;
private bool isClicked;
[Resolved] [Resolved]
private OsuColour colours { get; set; } private OsuColour colours { get; set; }
@ -101,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
markerRing.Alpha = IsSelected.Value ? 1 : 0; markerRing.Alpha = IsSelected.Value ? 1 : 0;
Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow;
if (IsHovered || isClicked || IsSelected.Value) if (IsHovered || IsSelected.Value)
colour = Color4.White; colour = Color4.White;
marker.Colour = colour; marker.Colour = colour;
} }
@ -127,21 +125,18 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
protected override bool OnMouseDown(MouseDownEvent e) protected override bool OnMouseDown(MouseDownEvent e)
{ {
isClicked = true; if (RequestSelection != null)
{
RequestSelection.Invoke(Index);
return true; return true;
} }
protected override bool OnMouseUp(MouseUpEvent e) return false;
{
isClicked = false;
return true;
} }
protected override bool OnClick(ClickEvent e) protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null;
{
RequestSelection?.Invoke(Index); protected override bool OnClick(ClickEvent e) => RequestSelection != null;
return true;
}
protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDragStart(DragStartEvent e) => true;

View File

@ -21,15 +21,17 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
internal readonly Container<PathControlPointPiece> Pieces; internal readonly Container<PathControlPointPiece> Pieces;
private readonly Slider slider; private readonly Slider slider;
private readonly bool allowSelection;
private InputManager inputManager; private InputManager inputManager;
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
private IPlacementHandler placementHandler { get; set; } private IPlacementHandler placementHandler { get; set; }
public PathControlPointVisualiser(Slider slider) public PathControlPointVisualiser(Slider slider, bool allowSelection)
{ {
this.slider = slider; this.slider = slider;
this.allowSelection = allowSelection;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
@ -49,11 +51,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
while (slider.Path.ControlPoints.Length > Pieces.Count) while (slider.Path.ControlPoints.Length > Pieces.Count)
{ {
Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) var piece = new PathControlPointPiece(slider, Pieces.Count)
{ {
ControlPointsChanged = c => ControlPointsChanged?.Invoke(c), ControlPointsChanged = c => ControlPointsChanged?.Invoke(c),
RequestSelection = selectPiece };
});
if (allowSelection)
piece.RequestSelection = selectPiece;
Pieces.Add(piece);
} }
while (slider.Path.ControlPoints.Length < Pieces.Count) while (slider.Path.ControlPoints.Length < Pieces.Count)

View File

@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
bodyPiece = new SliderBodyPiece(), bodyPiece = new SliderBodyPiece(),
headCirclePiece = new HitCirclePiece(), headCirclePiece = new HitCirclePiece(),
tailCirclePiece = new HitCirclePiece(), tailCirclePiece = new HitCirclePiece(),
new PathControlPointVisualiser(HitObject) { ControlPointsChanged = _ => updateSlider() }, new PathControlPointVisualiser(HitObject, false) { ControlPointsChanged = _ => updateSlider() },
}; };
setState(PlacementState.Initial); setState(PlacementState.Initial);

View File

@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
BodyPiece = new SliderBodyPiece(), BodyPiece = new SliderBodyPiece(),
HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start),
TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End),
ControlPointVisualiser = new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, ControlPointVisualiser = new PathControlPointVisualiser(sliderObject, true) { ControlPointsChanged = onNewControlPoints },
}; };
} }

View File

@ -3,11 +3,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
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.Containers;
using osu.Framework.Screens;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osu.Game.Screens.Ranking.Pages; using osu.Game.Screens.Ranking.Pages;
@ -27,7 +32,8 @@ namespace osu.Game.Tests.Visual.Gameplay
typeof(ScoreResultsPage), typeof(ScoreResultsPage),
typeof(RetryButton), typeof(RetryButton),
typeof(ReplayDownloadButton), typeof(ReplayDownloadButton),
typeof(LocalLeaderboardPage) typeof(LocalLeaderboardPage),
typeof(TestPlayer)
}; };
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -43,8 +49,9 @@ namespace osu.Game.Tests.Visual.Gameplay
var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0); var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0);
if (beatmapInfo != null) if (beatmapInfo != null)
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
}
LoadScreen(new SoloResults(new ScoreInfo private TestSoloResults createResultsScreen() => new TestSoloResults(new ScoreInfo
{ {
TotalScore = 2845370, TotalScore = 2845370,
Accuracy = 0.98, Accuracy = 0.98,
@ -62,7 +69,62 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
Username = "peppy", Username = "peppy",
} }
})); });
[Test]
public void ResultsWithoutPlayer()
{
TestSoloResults screen = null;
AddStep("load results", () => Child = new OsuScreenStack(screen = createResultsScreen())
{
RelativeSizeAxes = Axes.Both
});
AddUntilStep("wait for loaded", () => screen.IsLoaded);
AddAssert("retry overlay not present", () => screen.RetryOverlay == null);
}
[Test]
public void ResultsWithPlayer()
{
TestSoloResults screen = null;
AddStep("load results", () => Child = new TestResultsContainer(screen = createResultsScreen()));
AddUntilStep("wait for loaded", () => screen.IsLoaded);
AddAssert("retry overlay present", () => screen.RetryOverlay != null);
}
private class TestResultsContainer : Container
{
[Cached(typeof(Player))]
private readonly Player player = new TestPlayer();
public TestResultsContainer(IScreen screen)
{
RelativeSizeAxes = Axes.Both;
InternalChild = new OsuScreenStack(screen)
{
RelativeSizeAxes = Axes.Both,
};
}
}
private class TestSoloResults : SoloResults
{
public HotkeyRetryOverlay RetryOverlay;
public TestSoloResults(ScoreInfo score)
: base(score)
{
}
protected override void LoadComplete()
{
base.LoadComplete();
RetryOverlay = InternalChildren.OfType<HotkeyRetryOverlay>().SingleOrDefault();
}
} }
} }
} }

View File

@ -8,9 +8,6 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Graphics.Containers namespace osu.Game.Graphics.Containers
@ -23,21 +20,12 @@ namespace osu.Game.Graphics.Containers
} }
private OsuGame game; private OsuGame game;
private ChannelManager channelManager;
private Action showNotImplementedError;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(OsuGame game, NotificationOverlay notifications, ChannelManager channelManager) private void load(OsuGame game)
{ {
// will be null in tests // will be null in tests
this.game = game; this.game = game;
this.channelManager = channelManager;
showNotImplementedError = () => notifications?.Post(new SimpleNotification
{
Text = @"This link type is not yet supported!",
Icon = FontAwesome.Solid.LifeRing,
});
} }
public void AddLinks(string text, List<Link> links) public void AddLinks(string text, List<Link> links)
@ -56,85 +44,47 @@ namespace osu.Game.Graphics.Containers
foreach (var link in links) foreach (var link in links)
{ {
AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd));
AddLink(text.Substring(link.Index, link.Length), link.Url, link.Action, link.Argument); AddLink(text.Substring(link.Index, link.Length), link.Action, link.Argument ?? link.Url);
previousLinkEnd = link.Index + link.Length; previousLinkEnd = link.Index + link.Length;
} }
AddText(text.Substring(previousLinkEnd)); AddText(text.Substring(previousLinkEnd));
} }
public IEnumerable<Drawable> AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action<SpriteText> creationParameters = null) public void AddLink(string text, string url, Action<SpriteText> creationParameters = null) =>
=> createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), url);
public IEnumerable<Drawable> AddLink(string text, Action action, string tooltipText = null, Action<SpriteText> creationParameters = null) public void AddLink(string text, Action action, string tooltipText = null, Action<SpriteText> creationParameters = null)
=> createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action);
public IEnumerable<Drawable> AddLink(IEnumerable<SpriteText> text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action<SpriteText> creationParameters = null)
=> createLink(AddText(text, creationParameters), new LinkDetails(action, argument), null);
public void AddLink(IEnumerable<SpriteText> text, LinkAction action = LinkAction.External, string linkArgument = null, string tooltipText = null)
{ {
foreach (var t in text) foreach (var t in text)
AddArbitraryDrawable(t); AddArbitraryDrawable(t);
return createLink(text, null, url, linkType, linkArgument, tooltipText); createLink(text, new LinkDetails(action, linkArgument), tooltipText);
} }
public IEnumerable<Drawable> AddUserLink(User user, Action<SpriteText> creationParameters = null) public void AddUserLink(User user, Action<SpriteText> creationParameters = null)
=> createLink(AddText(user.Username, creationParameters), user.Username, null, LinkAction.OpenUserProfile, user.Id.ToString(), "View profile"); => createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "View Profile");
private IEnumerable<Drawable> createLink(IEnumerable<Drawable> drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) private void createLink(IEnumerable<Drawable> drawables, LinkDetails link, string tooltipText, Action action = null)
{ {
AddInternal(new DrawableLinkCompiler(drawables.OfType<SpriteText>().ToList()) AddInternal(new DrawableLinkCompiler(drawables.OfType<SpriteText>().ToList())
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
TooltipText = tooltipText ?? (url != text ? url : string.Empty), TooltipText = tooltipText,
Action = action ?? (() => Action = () =>
{ {
switch (linkType) if (action != null)
{ action();
case LinkAction.OpenBeatmap: else
// TODO: proper query params handling game.HandleLink(link);
if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) },
game?.ShowBeatmap(beatmapId);
break;
case LinkAction.OpenBeatmapSet:
if (int.TryParse(linkArgument, out int setId))
game?.ShowBeatmapSet(setId);
break;
case LinkAction.OpenChannel:
try
{
channelManager?.OpenChannel(linkArgument);
}
catch (ChannelNotFoundException)
{
Logger.Log($"The requested channel \"{linkArgument}\" does not exist");
}
break;
case LinkAction.OpenEditorTimestamp:
case LinkAction.JoinMultiplayerMatch:
case LinkAction.Spectate:
showNotImplementedError?.Invoke();
break;
case LinkAction.External:
game?.OpenUrlExternally(url);
break;
case LinkAction.OpenUserProfile:
if (long.TryParse(linkArgument, out long userId))
game?.ShowUser(userId);
break;
default:
throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action.");
}
}),
}); });
return drawables;
} }
// We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used. // We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used.

View File

@ -81,7 +81,7 @@ namespace osu.Game.Online.Chat
//since we just changed the line display text, offset any already processed links. //since we just changed the line display text, offset any already processed links.
result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0); result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0);
var details = getLinkDetails(linkText); var details = GetLinkDetails(linkText);
result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument)); result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument));
//adjust the offset for processing the current matches group. //adjust the offset for processing the current matches group.
@ -98,7 +98,7 @@ namespace osu.Game.Online.Chat
var linkText = m.Groups["link"].Value; var linkText = m.Groups["link"].Value;
var indexLength = linkText.Length; var indexLength = linkText.Length;
var details = getLinkDetails(linkText); var details = GetLinkDetails(linkText);
var link = new Link(linkText, index, indexLength, details.Action, details.Argument); var link = new Link(linkText, index, indexLength, details.Action, details.Argument);
// sometimes an already-processed formatted link can reduce to a simple URL, too // sometimes an already-processed formatted link can reduce to a simple URL, too
@ -109,7 +109,7 @@ namespace osu.Game.Online.Chat
} }
} }
private static LinkDetails getLinkDetails(string url) public static LinkDetails GetLinkDetails(string url)
{ {
var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
args[0] = args[0].TrimEnd(':'); args[0] = args[0].TrimEnd(':');
@ -255,6 +255,7 @@ namespace osu.Game.Online.Chat
OriginalText = Text = text; OriginalText = Text = text;
} }
} }
}
public class LinkDetails public class LinkDetails
{ {
@ -267,7 +268,6 @@ namespace osu.Game.Online.Chat
Argument = argument; Argument = argument;
} }
} }
}
public enum LinkAction public enum LinkAction
{ {
@ -279,6 +279,7 @@ namespace osu.Game.Online.Chat
JoinMultiplayerMatch, JoinMultiplayerMatch,
Spectate, Spectate,
OpenUserProfile, OpenUserProfile,
Custom
} }
public class Link : IComparable<Link> public class Link : IComparable<Link>

View File

@ -21,6 +21,7 @@ using osu.Game.Users.Drawables;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using Humanizer; using Humanizer;
using osu.Game.Online.API;
namespace osu.Game.Online.Leaderboards namespace osu.Game.Online.Leaderboards
{ {
@ -37,6 +38,7 @@ namespace osu.Game.Online.Leaderboards
private readonly ScoreInfo score; private readonly ScoreInfo score;
private readonly int rank; private readonly int rank;
private readonly bool allowHighlight;
private Box background; private Box background;
private Container content; private Container content;
@ -49,17 +51,18 @@ namespace osu.Game.Online.Leaderboards
private List<ScoreComponentLabel> statisticsLabels; private List<ScoreComponentLabel> statisticsLabels;
public LeaderboardScore(ScoreInfo score, int rank) public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true)
{ {
this.score = score; this.score = score;
this.rank = rank; this.rank = rank;
this.allowHighlight = allowHighlight;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = HEIGHT; Height = HEIGHT;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load(IAPIProvider api, OsuColour colour)
{ {
var user = score.User; var user = score.User;
@ -100,7 +103,7 @@ namespace osu.Game.Online.Leaderboards
background = new Box background = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = Color4.Black, Colour = user.Id == api.LocalUser.Value.Id && allowHighlight ? colour.Green : Color4.Black,
Alpha = background_alpha, Alpha = background_alpha,
}, },
}, },

View File

@ -215,31 +215,102 @@ namespace osu.Game
private ExternalLinkOpener externalLinkOpener; private ExternalLinkOpener externalLinkOpener;
public void OpenUrlExternally(string url) /// <summary>
/// Handle an arbitrary URL. Displays via in-game overlays where possible.
/// This can be called from a non-thread-safe non-game-loaded state.
/// </summary>
/// <param name="url">The URL to load.</param>
public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url));
/// <summary>
/// Handle a specific <see cref="LinkDetails"/>.
/// This can be called from a non-thread-safe non-game-loaded state.
/// </summary>
/// <param name="link">The link to load.</param>
public void HandleLink(LinkDetails link) => Schedule(() =>
{
switch (link.Action)
{
case LinkAction.OpenBeatmap:
// TODO: proper query params handling
if (link.Argument != null && int.TryParse(link.Argument.Contains('?') ? link.Argument.Split('?')[0] : link.Argument, out int beatmapId))
ShowBeatmap(beatmapId);
break;
case LinkAction.OpenBeatmapSet:
if (int.TryParse(link.Argument, out int setId))
ShowBeatmapSet(setId);
break;
case LinkAction.OpenChannel:
ShowChannel(link.Argument);
break;
case LinkAction.OpenEditorTimestamp:
case LinkAction.JoinMultiplayerMatch:
case LinkAction.Spectate:
waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification
{
Text = @"This link type is not yet supported!",
Icon = FontAwesome.Solid.LifeRing,
}));
break;
case LinkAction.External:
OpenUrlExternally(link.Argument);
break;
case LinkAction.OpenUserProfile:
if (long.TryParse(link.Argument, out long userId))
ShowUser(userId);
break;
default:
throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action.");
}
});
public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ =>
{ {
if (url.StartsWith("/")) if (url.StartsWith("/"))
url = $"{API.Endpoint}{url}"; url = $"{API.Endpoint}{url}";
externalLinkOpener.OpenUrlExternally(url); externalLinkOpener.OpenUrlExternally(url);
});
/// <summary>
/// Open a specific channel in chat.
/// </summary>
/// <param name="channel">The channel to display.</param>
public void ShowChannel(string channel) => waitForReady(() => channelManager, _ =>
{
try
{
channelManager.OpenChannel(channel);
} }
catch (ChannelNotFoundException)
{
Logger.Log($"The requested channel \"{channel}\" does not exist");
}
});
/// <summary> /// <summary>
/// Show a beatmap set as an overlay. /// Show a beatmap set as an overlay.
/// </summary> /// </summary>
/// <param name="setId">The set to display.</param> /// <param name="setId">The set to display.</param>
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); public void ShowBeatmapSet(int setId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmapSet(setId));
/// <summary> /// <summary>
/// Show a user's profile as an overlay. /// Show a user's profile as an overlay.
/// </summary> /// </summary>
/// <param name="userId">The user to display.</param> /// <param name="userId">The user to display.</param>
public void ShowUser(long userId) => userProfile.ShowUser(userId); public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId));
/// <summary> /// <summary>
/// Show a beatmap's set as an overlay, displaying the given beatmap. /// Show a beatmap's set as an overlay, displaying the given beatmap.
/// </summary> /// </summary>
/// <param name="beatmapId">The beatmap to show.</param> /// <param name="beatmapId">The beatmap to show.</param>
public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId));
/// <summary> /// <summary>
/// Present a beatmap at song select immediately. /// Present a beatmap at song select immediately.
@ -397,6 +468,23 @@ namespace osu.Game
performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName));
} }
/// <summary>
/// Wait for the game (and target component) to become loaded and then run an action.
/// </summary>
/// <param name="retrieveInstance">A function to retrieve a (potentially not-yet-constructed) target instance.</param>
/// <param name="action">The action to perform on the instance when load is confirmed.</param>
/// <typeparam name="T">The type of the target instance.</typeparam>
private void waitForReady<T>(Func<T> retrieveInstance, Action<T> action)
where T : Drawable
{
var instance = retrieveInstance();
if (ScreenStack == null || ScreenStack.CurrentScreen is StartupScreen || instance?.IsLoaded != true)
Schedule(() => waitForReady(retrieveInstance, action));
else
action(instance);
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);

View File

@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Changelog
t.Font = fontLarge; t.Font = fontLarge;
t.Colour = entryColour; t.Colour = entryColour;
}); });
title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl,
creationParameters: t => creationParameters: t =>
{ {
t.Font = fontLarge; t.Font = fontLarge;
@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Changelog
t.Colour = entryColour; t.Colour = entryColour;
}); });
else if (entry.GithubUser.GithubUrl != null) else if (entry.GithubUser.GithubUrl != null)
title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t =>
{ {
t.Font = fontMedium; t.Font = fontMedium;
t.Colour = entryColour; t.Colour = entryColour;

View File

@ -81,7 +81,7 @@ namespace osu.Game.Screens.Multi.Components
Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)),
Font = OsuFont.GetFont(size: TextSize), Font = OsuFont.GetFont(size: TextSize),
} }
}, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); }, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap");
} }
} }
} }

View File

@ -116,9 +116,7 @@ namespace osu.Game.Screens.Ranking
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
InternalChildren = new Drawable[] InternalChild = new AspectContainer
{
new AspectContainer
{ {
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
@ -254,8 +252,11 @@ namespace osu.Game.Screens.Ranking
} }
} }
} }
}, };
new HotkeyRetryOverlay
if (player != null)
{
AddInternal(new HotkeyRetryOverlay
{ {
Action = () => Action = () =>
{ {
@ -263,8 +264,8 @@ namespace osu.Game.Screens.Ranking
player?.Restart(); player?.Restart();
}, },
}, });
}; }
var pages = CreateResultPages(); var pages = CreateResultPages();

View File

@ -179,7 +179,7 @@ namespace osu.Game.Screens.Select.Leaderboards
return req; return req;
} }
protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index) protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope)
{ {
Action = () => ScoreSelected?.Invoke(model) Action = () => ScoreSelected?.Invoke(model)
}; };

View File

@ -77,7 +77,7 @@ namespace osu.Game.Screens.Select.Leaderboards
if (newScore == null) if (newScore == null)
return; return;
LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position) LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position, false)
{ {
Action = () => ScoreSelected?.Invoke(newScore.Score) Action = () => ScoreSelected?.Invoke(newScore.Score)
}, drawableScore => }, drawableScore =>