mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 07:42:57 +08:00
Merge branch 'master' into rewrite-standalone-chat
This commit is contained in:
commit
2c97409e2e
@ -26,9 +26,6 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
if (slider == null)
|
||||
return;
|
||||
|
||||
slider.HeadCircle.Position = new Vector2(slider.HeadCircle.Position.X, OsuPlayfield.BASE_SIZE.Y - slider.HeadCircle.Position.Y);
|
||||
slider.TailCircle.Position = new Vector2(slider.TailCircle.Position.X, OsuPlayfield.BASE_SIZE.Y - slider.TailCircle.Position.Y);
|
||||
|
||||
slider.NestedHitObjects.OfType<SliderTick>().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y));
|
||||
slider.NestedHitObjects.OfType<RepeatPoint>().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y));
|
||||
|
||||
|
@ -31,8 +31,8 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
new KeyBinding(InputKey.A, OsuAction.LeftButton),
|
||||
new KeyBinding(InputKey.S, OsuAction.RightButton),
|
||||
new KeyBinding(InputKey.Z, OsuAction.LeftButton),
|
||||
new KeyBinding(InputKey.X, OsuAction.RightButton),
|
||||
new KeyBinding(InputKey.MouseLeft, OsuAction.LeftButton),
|
||||
new KeyBinding(InputKey.MouseRight, OsuAction.RightButton),
|
||||
};
|
||||
|
67
osu.Game.Tests/Visual/TestCaseDrawableDate.cs
Normal file
67
osu.Game.Tests/Visual/TestCaseDrawableDate.cs
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseDrawableDate : OsuTestCase
|
||||
{
|
||||
public TestCaseDrawableDate()
|
||||
{
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new PokeyDrawableDate(DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(60))),
|
||||
new PokeyDrawableDate(DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(55))),
|
||||
new PokeyDrawableDate(DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(50))),
|
||||
new PokeyDrawableDate(DateTimeOffset.Now),
|
||||
new PokeyDrawableDate(DateTimeOffset.Now.Add(TimeSpan.FromSeconds(60))),
|
||||
new PokeyDrawableDate(DateTimeOffset.Now.Add(TimeSpan.FromSeconds(65))),
|
||||
new PokeyDrawableDate(DateTimeOffset.Now.Add(TimeSpan.FromSeconds(70))),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class PokeyDrawableDate : CompositeDrawable
|
||||
{
|
||||
public PokeyDrawableDate(DateTimeOffset date)
|
||||
{
|
||||
const float box_size = 10;
|
||||
|
||||
DrawableDate drawableDate;
|
||||
Box flash;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
flash = new Box
|
||||
{
|
||||
Colour = Color4.Yellow,
|
||||
Size = new Vector2(box_size),
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Alpha = 0
|
||||
},
|
||||
drawableDate = new DrawableDate(date)
|
||||
{
|
||||
X = box_size + 2,
|
||||
}
|
||||
};
|
||||
|
||||
drawableDate.Current.ValueChanged += v => flash.FadeOutFromOne(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ using osu.Framework.Allocation;
|
||||
using osuTK;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
@ -36,7 +37,7 @@ namespace osu.Game.Tests.Visual
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(550f, 450f),
|
||||
Scope = LeaderboardScope.Global,
|
||||
Scope = BeatmapLeaderboardScope.Global,
|
||||
});
|
||||
|
||||
AddStep(@"New Scores", newScores);
|
||||
@ -275,7 +276,7 @@ namespace osu.Game.Tests.Visual
|
||||
};
|
||||
}
|
||||
|
||||
private class FailableLeaderboard : Leaderboard
|
||||
private class FailableLeaderboard : BeatmapLeaderboard
|
||||
{
|
||||
public void SetRetrievalState(PlaceholderState state)
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
@ -11,13 +12,27 @@ namespace osu.Game.Graphics
|
||||
{
|
||||
public class DrawableDate : OsuSpriteText, IHasTooltip
|
||||
{
|
||||
protected readonly DateTimeOffset Date;
|
||||
private DateTimeOffset date;
|
||||
|
||||
public DateTimeOffset Date
|
||||
{
|
||||
get => date;
|
||||
set
|
||||
{
|
||||
if (date == value)
|
||||
return;
|
||||
date = value.ToLocalTime();
|
||||
|
||||
if (LoadState >= LoadState.Ready)
|
||||
updateTime();
|
||||
}
|
||||
}
|
||||
|
||||
public DrawableDate(DateTimeOffset date)
|
||||
{
|
||||
Font = "Exo2.0-RegularItalic";
|
||||
|
||||
Date = date.ToLocalTime();
|
||||
Date = date;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -39,14 +54,14 @@ namespace osu.Game.Graphics
|
||||
var diffToNow = DateTimeOffset.Now.Subtract(Date);
|
||||
|
||||
double timeUntilNextUpdate = 1000;
|
||||
if (diffToNow.TotalSeconds > 60)
|
||||
if (Math.Abs(diffToNow.TotalSeconds) > 120)
|
||||
{
|
||||
timeUntilNextUpdate *= 60;
|
||||
if (diffToNow.TotalMinutes > 60)
|
||||
if (Math.Abs(diffToNow.TotalMinutes) > 120)
|
||||
{
|
||||
timeUntilNextUpdate *= 60;
|
||||
|
||||
if (diffToNow.TotalHours > 24)
|
||||
if (Math.Abs(diffToNow.TotalHours) > 48)
|
||||
timeUntilNextUpdate *= 24;
|
||||
}
|
||||
}
|
||||
|
@ -13,15 +13,15 @@ namespace osu.Game.Online.API.Requests
|
||||
public class GetScoresRequest : APIRequest<APIScores>
|
||||
{
|
||||
private readonly BeatmapInfo beatmap;
|
||||
private readonly LeaderboardScope scope;
|
||||
private readonly BeatmapLeaderboardScope scope;
|
||||
private readonly RulesetInfo ruleset;
|
||||
|
||||
public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, LeaderboardScope scope = LeaderboardScope.Global)
|
||||
public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global)
|
||||
{
|
||||
if (!beatmap.OnlineBeatmapID.HasValue)
|
||||
throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}.");
|
||||
|
||||
if (scope == LeaderboardScope.Local)
|
||||
if (scope == BeatmapLeaderboardScope.Local)
|
||||
throw new InvalidOperationException("Should not attempt to request online scores for a local scoped leaderboard");
|
||||
|
||||
this.beatmap = beatmap;
|
||||
|
@ -2,14 +2,14 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public class DrawableRank : Container
|
||||
{
|
@ -3,27 +3,22 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public class Leaderboard : Container
|
||||
public abstract class Leaderboard<TScope, ScoreInfo> : Container
|
||||
{
|
||||
private const double fade_duration = 300;
|
||||
|
||||
@ -32,10 +27,6 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
|
||||
private FillFlowContainer<LeaderboardScore> scrollFlow;
|
||||
|
||||
private readonly IBindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
public Action<ScoreInfo> ScoreSelected;
|
||||
|
||||
private readonly LoadingAnimation loading;
|
||||
|
||||
private ScheduledDelegate showScoresDelegate;
|
||||
@ -70,7 +61,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 5f),
|
||||
Padding = new MarginPadding { Top = 10, Bottom = 5 },
|
||||
ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) })
|
||||
ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1))
|
||||
};
|
||||
|
||||
// schedule because we may not be loaded yet (LoadComponentAsync complains).
|
||||
@ -96,18 +87,18 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
}
|
||||
}
|
||||
|
||||
private LeaderboardScope scope;
|
||||
private TScope scope;
|
||||
|
||||
public LeaderboardScope Scope
|
||||
public TScope Scope
|
||||
{
|
||||
get { return scope; }
|
||||
set
|
||||
{
|
||||
if (value == scope)
|
||||
if (value.Equals(scope))
|
||||
return;
|
||||
|
||||
scope = value;
|
||||
updateScores();
|
||||
UpdateScores();
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +128,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
case PlaceholderState.NetworkFailure:
|
||||
replacePlaceholder(new RetrievalFailurePlaceholder
|
||||
{
|
||||
OnRetry = updateScores,
|
||||
OnRetry = UpdateScores,
|
||||
});
|
||||
break;
|
||||
case PlaceholderState.Unavailable:
|
||||
@ -159,7 +150,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
}
|
||||
}
|
||||
|
||||
public Leaderboard()
|
||||
protected Leaderboard()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -177,36 +168,14 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
}
|
||||
|
||||
private APIAccess api;
|
||||
private BeatmapInfo beatmap;
|
||||
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; }
|
||||
|
||||
private ScheduledDelegate pendingUpdateScores;
|
||||
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
get { return beatmap; }
|
||||
set
|
||||
{
|
||||
if (beatmap == value)
|
||||
return;
|
||||
|
||||
beatmap = value;
|
||||
Scores = null;
|
||||
|
||||
updateScores();
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(permitNulls: true)]
|
||||
private void load(APIAccess api, IBindable<RulesetInfo> parentRuleset)
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(APIAccess api)
|
||||
{
|
||||
this.api = api;
|
||||
|
||||
ruleset.BindTo(parentRuleset);
|
||||
ruleset.ValueChanged += _ => updateScores();
|
||||
|
||||
if (api != null)
|
||||
api.OnStateChange += handleApiStateChange;
|
||||
}
|
||||
@ -219,21 +188,17 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
api.OnStateChange -= handleApiStateChange;
|
||||
}
|
||||
|
||||
public void RefreshScores() => updateScores();
|
||||
public void RefreshScores() => UpdateScores();
|
||||
|
||||
private GetScoresRequest getScoresRequest;
|
||||
private APIRequest getScoresRequest;
|
||||
|
||||
private void handleApiStateChange(APIState oldState, APIState newState)
|
||||
{
|
||||
if (Scope == LeaderboardScope.Local)
|
||||
// No need to respond to API state change while current scope is local
|
||||
return;
|
||||
|
||||
if (newState == APIState.Online)
|
||||
updateScores();
|
||||
UpdateScores();
|
||||
}
|
||||
|
||||
private void updateScores()
|
||||
protected void UpdateScores()
|
||||
{
|
||||
// don't display any scores or placeholder until the first Scores_Set has been called.
|
||||
// this avoids scope changes flickering a "no scores" placeholder before initialisation of song select is finished.
|
||||
@ -245,40 +210,23 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
pendingUpdateScores?.Cancel();
|
||||
pendingUpdateScores = Schedule(() =>
|
||||
{
|
||||
if (Scope == LeaderboardScope.Local)
|
||||
{
|
||||
Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray();
|
||||
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Beatmap?.OnlineBeatmapID == null)
|
||||
{
|
||||
PlaceholderState = PlaceholderState.Unavailable;
|
||||
return;
|
||||
}
|
||||
|
||||
if (api?.IsLoggedIn != true)
|
||||
{
|
||||
PlaceholderState = PlaceholderState.NotLoggedIn;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Scope != LeaderboardScope.Global && !api.LocalUser.Value.IsSupporter)
|
||||
{
|
||||
PlaceholderState = PlaceholderState.NotSupporter;
|
||||
return;
|
||||
}
|
||||
|
||||
PlaceholderState = PlaceholderState.Retrieving;
|
||||
loading.Show();
|
||||
|
||||
getScoresRequest = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope);
|
||||
getScoresRequest.Success += r => Schedule(() =>
|
||||
getScoresRequest = FetchScores(scores => Schedule(() =>
|
||||
{
|
||||
Scores = r.Scores;
|
||||
Scores = scores;
|
||||
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
|
||||
});
|
||||
}));
|
||||
|
||||
if (getScoresRequest == null)
|
||||
return;
|
||||
|
||||
getScoresRequest.Failure += e => Schedule(() =>
|
||||
{
|
||||
@ -292,6 +240,8 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback);
|
||||
|
||||
private Placeholder currentPlaceholder;
|
||||
|
||||
private void replacePlaceholder(Placeholder placeholder)
|
||||
@ -344,5 +294,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract LeaderboardScore CreateDrawableScore(ScoreInfo model, int index);
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -17,35 +16,40 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public class LeaderboardScore : OsuClickableContainer
|
||||
{
|
||||
public static readonly float HEIGHT = 60;
|
||||
|
||||
public readonly int RankPosition;
|
||||
public readonly ScoreInfo Score;
|
||||
|
||||
public const float HEIGHT = 60;
|
||||
|
||||
private const float corner_radius = 5;
|
||||
private const float edge_margin = 5;
|
||||
private const float background_alpha = 0.25f;
|
||||
private const float rank_width = 30;
|
||||
|
||||
protected Container RankContainer { get; private set; }
|
||||
|
||||
private readonly ScoreInfo score;
|
||||
|
||||
private Box background;
|
||||
private Container content;
|
||||
private Drawable avatar;
|
||||
private DrawableRank scoreRank;
|
||||
private Drawable scoreRank;
|
||||
private OsuSpriteText nameLabel;
|
||||
private GlowingSpriteText scoreLabel;
|
||||
private ScoreComponentLabel maxCombo;
|
||||
private ScoreComponentLabel accuracy;
|
||||
private Container flagBadgeContainer;
|
||||
private FillFlowContainer<ModIcon> modsContainer;
|
||||
|
||||
private List<ScoreComponentLabel> statisticsLabels;
|
||||
|
||||
public LeaderboardScore(ScoreInfo score, int rank)
|
||||
{
|
||||
Score = score;
|
||||
this.score = score;
|
||||
RankPosition = rank;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
@ -55,6 +59,10 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var user = score.User;
|
||||
|
||||
statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s)).ToList();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
@ -102,7 +110,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
Children = new[]
|
||||
{
|
||||
avatar = new DelayedLoadWrapper(
|
||||
new Avatar(Score.User)
|
||||
new Avatar(user)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = corner_radius,
|
||||
@ -128,7 +136,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
{
|
||||
nameLabel = new OsuSpriteText
|
||||
{
|
||||
Text = Score.User.Username,
|
||||
Text = user.Username,
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
TextSize = 23,
|
||||
},
|
||||
@ -149,7 +157,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new DrawableFlag(Score.User?.Country)
|
||||
new DrawableFlag(user.Country)
|
||||
{
|
||||
Width = 30,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
@ -164,11 +172,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(10f, 0f),
|
||||
Margin = new MarginPadding { Left = edge_margin },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
maxCombo = new ScoreComponentLabel(FontAwesome.fa_link, Score.MaxCombo.ToString(), "Max Combo"),
|
||||
accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(Score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", Score.Accuracy), "Accuracy"),
|
||||
},
|
||||
Children = statisticsLabels
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -183,17 +187,17 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
Spacing = new Vector2(5f, 0f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
scoreLabel = new GlowingSpriteText(Score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")),
|
||||
new Container
|
||||
scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")),
|
||||
RankContainer = new Container
|
||||
{
|
||||
Size = new Vector2(40f, 20f),
|
||||
Children = new[]
|
||||
{
|
||||
scoreRank = new DrawableRank(Score.Rank)
|
||||
scoreRank = new DrawableRank(score.Rank)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(40f),
|
||||
Size = new Vector2(40f)
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -205,7 +209,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
Origin = Anchor.BottomRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
ChildrenEnumerable = Score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) })
|
||||
ChildrenEnumerable = score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) })
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -216,7 +220,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
|
||||
public override void Show()
|
||||
{
|
||||
foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, maxCombo, accuracy, modsContainer })
|
||||
foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, modsContainer }.Concat(statisticsLabels))
|
||||
d.FadeOut();
|
||||
|
||||
Alpha = 0;
|
||||
@ -243,7 +247,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
|
||||
using (BeginDelayedSequence(50, true))
|
||||
{
|
||||
var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, };
|
||||
var drawables = new Drawable[] { flagBadgeContainer, modsContainer }.Concat(statisticsLabels).ToArray();
|
||||
for (int i = 0; i < drawables.Length; i++)
|
||||
drawables[i].FadeIn(100 + i * 50);
|
||||
}
|
||||
@ -251,6 +255,12 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<LeaderboardScoreStatistic> GetStatistics(ScoreInfo model) => new[]
|
||||
{
|
||||
new LeaderboardScoreStatistic(FontAwesome.fa_link, "Max Combo", model.MaxCombo.ToString()),
|
||||
new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy))
|
||||
};
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
background.FadeTo(0.5f, 300, Easing.OutQuint);
|
||||
@ -321,11 +331,10 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
|
||||
public string TooltipText => name;
|
||||
|
||||
public ScoreComponentLabel(FontAwesome icon, string value, string name)
|
||||
public ScoreComponentLabel(LeaderboardScoreStatistic statistic)
|
||||
{
|
||||
this.name = name;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Width = 60;
|
||||
name = statistic.Name;
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Child = content = new FillFlowContainer
|
||||
{
|
||||
@ -356,11 +365,11 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(icon_size - 6),
|
||||
Colour = OsuColour.FromHex(@"a4edff"),
|
||||
Icon = icon,
|
||||
Icon = statistic.Icon,
|
||||
},
|
||||
},
|
||||
},
|
||||
new GlowingSpriteText(value, @"Exo2.0-Bold", 17, Color4.White, OsuColour.FromHex(@"83ccfa"))
|
||||
new GlowingSpriteText(statistic.Value, @"Exo2.0-Bold", 17, Color4.White, OsuColour.FromHex(@"83ccfa"))
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
@ -369,5 +378,19 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class LeaderboardScoreStatistic
|
||||
{
|
||||
public FontAwesome Icon;
|
||||
public string Value;
|
||||
public string Name;
|
||||
|
||||
public LeaderboardScoreStatistic(FontAwesome icon, string name, string value)
|
||||
{
|
||||
Icon = icon;
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public class MessagePlaceholder : Placeholder
|
||||
{
|
@ -5,7 +5,7 @@ using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public abstract class Placeholder : OsuTextFlowContainer, IEquatable<Placeholder>
|
||||
{
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public enum PlaceholderState
|
||||
{
|
@ -8,7 +8,7 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public class RetrievalFailurePlaceholder : Placeholder
|
||||
{
|
@ -9,7 +9,6 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
|
||||
@ -20,7 +19,6 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private const float height = 50;
|
||||
|
||||
private readonly UpdateableAvatar avatar;
|
||||
private readonly ClickableArea clickableArea;
|
||||
private readonly FillFlowContainer fields;
|
||||
|
||||
private BeatmapSetInfo beatmapSet;
|
||||
@ -73,7 +71,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
clickableArea = new ClickableArea
|
||||
new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
CornerRadius = 3,
|
||||
@ -100,14 +98,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(UserProfileOverlay profile)
|
||||
private void load()
|
||||
{
|
||||
clickableArea.Action = () =>
|
||||
{
|
||||
if (avatar.User != null) profile?.ShowUser(avatar.User);
|
||||
};
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,11 @@ using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Overlays.Profile.Sections.Ranks;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
|
@ -12,12 +12,12 @@ using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Overlays.Profile.Sections.Ranks;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
|
@ -82,6 +82,7 @@ namespace osu.Game.Overlays.Profile
|
||||
Origin = Anchor.BottomLeft,
|
||||
Masking = true,
|
||||
CornerRadius = 5,
|
||||
OpenOnClick = { Value = false },
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
@ -114,7 +115,7 @@ namespace osu.Game.Overlays.Profile
|
||||
Y = -48,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
usernameText = new OsuSpriteText
|
||||
{
|
||||
Text = user.Username,
|
||||
Font = @"Exo2.0-RegularItalic",
|
||||
@ -316,6 +317,8 @@ namespace osu.Game.Overlays.Profile
|
||||
levelBadge.Texture = textures.Get(@"Profile/levelbadge");
|
||||
}
|
||||
|
||||
private readonly OsuSpriteText usernameText;
|
||||
|
||||
private User user;
|
||||
|
||||
public User User
|
||||
@ -343,6 +346,8 @@ namespace osu.Game.Overlays.Profile
|
||||
if (user.IsSupporter)
|
||||
SupporterTag.Show();
|
||||
|
||||
usernameText.Text = user.Username;
|
||||
|
||||
if (!string.IsNullOrEmpty(user.Colour))
|
||||
{
|
||||
colourBar.Colour = OsuColour.FromHex(user.Colour);
|
||||
|
@ -6,8 +6,8 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
|
@ -10,7 +10,7 @@ using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
|
||||
namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
CornerRadius = 4,
|
||||
OpenOnClick = { Value = false },
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Screens.Ranking
|
||||
Colour = colours.GrayE,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Leaderboard
|
||||
new BeatmapLeaderboard
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
|
@ -19,11 +19,11 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Ranking
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
public readonly BeatmapDetails Details;
|
||||
public readonly Leaderboard Leaderboard;
|
||||
public readonly BeatmapLeaderboard Leaderboard;
|
||||
|
||||
private WorkingBeatmap beatmap;
|
||||
public WorkingBeatmap Beatmap
|
||||
@ -52,7 +52,7 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
default:
|
||||
Details.Hide();
|
||||
Leaderboard.Scope = (LeaderboardScope)tab - 1;
|
||||
Leaderboard.Scope = (BeatmapLeaderboardScope)tab - 1;
|
||||
Leaderboard.Show();
|
||||
break;
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select
|
||||
Alpha = 0,
|
||||
Margin = new MarginPadding { Top = details_padding },
|
||||
},
|
||||
Leaderboard = new Leaderboard
|
||||
Leaderboard = new BeatmapLeaderboard
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
|
87
osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
Normal file
87
osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
{
|
||||
public class BeatmapLeaderboard : Leaderboard<BeatmapLeaderboardScope, ScoreInfo>
|
||||
{
|
||||
public Action<ScoreInfo> ScoreSelected;
|
||||
|
||||
private BeatmapInfo beatmap;
|
||||
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
get { return beatmap; }
|
||||
set
|
||||
{
|
||||
if (beatmap == value)
|
||||
return;
|
||||
|
||||
beatmap = value;
|
||||
Scores = null;
|
||||
|
||||
UpdateScores();
|
||||
}
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ruleset.ValueChanged += _ => UpdateScores();
|
||||
}
|
||||
|
||||
protected override APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback)
|
||||
{
|
||||
if (Scope == BeatmapLeaderboardScope.Local)
|
||||
{
|
||||
Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray();
|
||||
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Beatmap?.OnlineBeatmapID == null)
|
||||
{
|
||||
PlaceholderState = PlaceholderState.Unavailable;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Scope != BeatmapLeaderboardScope.Global && !api.LocalUser.Value.IsSupporter)
|
||||
{
|
||||
PlaceholderState = PlaceholderState.NotSupporter;
|
||||
return null;
|
||||
}
|
||||
|
||||
var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope);
|
||||
|
||||
req.Success += r => scoresCallback?.Invoke(r.Scores);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index)
|
||||
{
|
||||
Action = () => ScoreSelected?.Invoke(model)
|
||||
};
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
|
||||
namespace osu.Game.Screens.Select.Leaderboards
|
||||
{
|
||||
public enum LeaderboardScope
|
||||
public enum BeatmapLeaderboardScope
|
||||
{
|
||||
Local,
|
||||
Country,
|
@ -3,17 +3,29 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Users
|
||||
{
|
||||
public class Avatar : Container
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether to open the user's profile when clicked.
|
||||
/// </summary>
|
||||
public readonly BindableBool OpenOnClick = new BindableBool(true);
|
||||
|
||||
private readonly User user;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuGame game { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An avatar for specified user.
|
||||
/// </summary>
|
||||
@ -33,14 +45,43 @@ namespace osu.Game.Users
|
||||
if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}");
|
||||
if (texture == null) texture = textures.Get(@"Online/avatar-guest");
|
||||
|
||||
Add(new Sprite
|
||||
ClickableArea clickableArea;
|
||||
Add(clickableArea = new ClickableArea
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = texture,
|
||||
FillMode = FillMode.Fit,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
Child = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = texture,
|
||||
FillMode = FillMode.Fit,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
Action = openProfile
|
||||
});
|
||||
|
||||
clickableArea.Enabled.BindTo(OpenOnClick);
|
||||
}
|
||||
|
||||
private void openProfile()
|
||||
{
|
||||
if (!OpenOnClick)
|
||||
return;
|
||||
|
||||
if (user != null)
|
||||
game?.ShowUser(user.Id);
|
||||
}
|
||||
|
||||
private class ClickableArea : OsuClickableContainer, IHasTooltip
|
||||
{
|
||||
public string TooltipText => Enabled.Value ? @"View Profile" : null;
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (!Enabled)
|
||||
return false;
|
||||
return base.OnClick(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
@ -35,6 +36,11 @@ namespace osu.Game.Users
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether to open the user's profile when clicked.
|
||||
/// </summary>
|
||||
public readonly BindableBool OpenOnClick = new BindableBool(true);
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -45,15 +51,18 @@ namespace osu.Game.Users
|
||||
{
|
||||
displayedAvatar?.FadeOut(300);
|
||||
displayedAvatar?.Expire();
|
||||
|
||||
if (user != null || ShowGuestOnNull)
|
||||
{
|
||||
Add(displayedAvatar = new DelayedLoadWrapper(
|
||||
new Avatar(user)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint),
|
||||
})
|
||||
);
|
||||
var avatar = new Avatar(user)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint),
|
||||
};
|
||||
|
||||
avatar.OpenOnClick.BindTo(OpenOnClick);
|
||||
|
||||
Add(displayedAvatar = new DelayedLoadWrapper(avatar));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ namespace osu.Game.Users
|
||||
User = user,
|
||||
Masking = true,
|
||||
CornerRadius = 5,
|
||||
OpenOnClick = { Value = false },
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
|
Loading…
Reference in New Issue
Block a user