mirror of
https://github.com/ppy/osu.git
synced 2025-03-17 22:17:25 +08:00
Merge pull request #10405 from peppy/ruleset-result-types
Allow ruleset to specify custom names for bonus/tick types
This commit is contained in:
commit
8432de9403
@ -141,6 +141,35 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
HitResult.SmallTickHit,
|
||||
HitResult.LargeBonus,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetDisplayNameForHitResult(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.LargeTickHit:
|
||||
return "large droplet";
|
||||
|
||||
case HitResult.SmallTickHit:
|
||||
return "small droplet";
|
||||
|
||||
case HitResult.LargeBonus:
|
||||
return "banana";
|
||||
}
|
||||
|
||||
return base.GetDisplayNameForHitResult(result);
|
||||
}
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
||||
|
||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new CatchLegacySkinTransformer(source);
|
||||
|
@ -319,6 +319,31 @@ namespace osu.Game.Rulesets.Mania
|
||||
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderByDescending(i => i).First(v => variant >= v);
|
||||
}
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Perfect,
|
||||
HitResult.Great,
|
||||
HitResult.Good,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetDisplayNameForHitResult(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.LargeTickHit:
|
||||
return "hold tick";
|
||||
}
|
||||
|
||||
return base.GetDisplayNameForHitResult(result);
|
||||
}
|
||||
|
||||
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[]
|
||||
{
|
||||
new StatisticRow
|
||||
|
@ -191,6 +191,41 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new OsuRulesetConfigManager(settings, RulesetInfo);
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
HitResult.SmallTickHit,
|
||||
HitResult.SmallBonus,
|
||||
HitResult.LargeBonus,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetDisplayNameForHitResult(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.LargeTickHit:
|
||||
return "slider tick";
|
||||
|
||||
case HitResult.SmallTickHit:
|
||||
return "slider end";
|
||||
|
||||
case HitResult.SmallBonus:
|
||||
return "spinner spin";
|
||||
|
||||
case HitResult.LargeBonus:
|
||||
return "spinner bonus";
|
||||
}
|
||||
|
||||
return base.GetDisplayNameForHitResult(result);
|
||||
}
|
||||
|
||||
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
|
||||
{
|
||||
var timedHitEvents = score.HitEvents.Where(e => e.HitObject is HitCircle && !(e.HitObject is SliderTailCircle)).ToList();
|
||||
|
@ -159,6 +159,33 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new TaikoReplayFrame();
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Ok,
|
||||
|
||||
HitResult.SmallTickHit,
|
||||
|
||||
HitResult.SmallBonus,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetDisplayNameForHitResult(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.SmallTickHit:
|
||||
return "drum tick";
|
||||
|
||||
case HitResult.SmallBonus:
|
||||
return "strong bonus";
|
||||
}
|
||||
|
||||
return base.GetDisplayNameForHitResult(result);
|
||||
}
|
||||
|
||||
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
|
||||
{
|
||||
var timedHitEvents = score.HitEvents.Where(e => e.HitObject is Hit).ToList();
|
||||
|
@ -193,6 +193,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
|
||||
AddStep("Transition to Results", () => player.Push(results = new FadeAccessibleResults(new ScoreInfo
|
||||
{
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
User = new User { Username = "osu!" },
|
||||
Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
|
||||
})));
|
||||
|
@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
/// <summary>
|
||||
/// The statistics that appear in the table, in order of appearance.
|
||||
/// </summary>
|
||||
private readonly List<HitResult> statisticResultTypes = new List<HitResult>();
|
||||
private readonly List<(HitResult result, string displayName)> statisticResultTypes = new List<(HitResult, string)>();
|
||||
|
||||
private bool showPerformancePoints;
|
||||
|
||||
@ -101,15 +101,24 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
};
|
||||
|
||||
// All statistics across all scores, unordered.
|
||||
var allScoreStatistics = scores.SelectMany(s => s.GetStatisticsForDisplay().Select(stat => stat.result)).ToHashSet();
|
||||
var allScoreStatistics = scores.SelectMany(s => s.GetStatisticsForDisplay().Select(stat => stat.Result)).ToHashSet();
|
||||
|
||||
var ruleset = scores.First().Ruleset.CreateInstance();
|
||||
|
||||
foreach (var result in OrderAttributeUtils.GetValuesInOrder<HitResult>())
|
||||
{
|
||||
if (!allScoreStatistics.Contains(result))
|
||||
continue;
|
||||
|
||||
columns.Add(new TableColumn(result.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 35, maxSize: 60)));
|
||||
statisticResultTypes.Add(result);
|
||||
// for the time being ignore bonus result types.
|
||||
// this is not being sent from the API and will be empty in all cases.
|
||||
if (result.IsBonus())
|
||||
continue;
|
||||
|
||||
string displayName = ruleset.GetDisplayNameForHitResult(result);
|
||||
|
||||
columns.Add(new TableColumn(displayName, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 35, maxSize: 60)));
|
||||
statisticResultTypes.Add((result, displayName));
|
||||
}
|
||||
|
||||
if (showPerformancePoints)
|
||||
@ -163,18 +172,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
}
|
||||
};
|
||||
|
||||
var availableStatistics = score.GetStatisticsForDisplay().ToDictionary(tuple => tuple.result);
|
||||
var availableStatistics = score.GetStatisticsForDisplay().ToDictionary(tuple => tuple.Result);
|
||||
|
||||
foreach (var result in statisticResultTypes)
|
||||
{
|
||||
if (!availableStatistics.TryGetValue(result, out var stat))
|
||||
stat = (result, 0, null);
|
||||
if (!availableStatistics.TryGetValue(result.result, out var stat))
|
||||
stat = new HitResultDisplayStatistic(result.result, 0, null, result.displayName);
|
||||
|
||||
content.Add(new OsuSpriteText
|
||||
{
|
||||
Text = stat.maxCount == null ? $"{stat.count}" : $"{stat.count}/{stat.maxCount}",
|
||||
Text = stat.MaxCount == null ? $"{stat.Count}" : $"{stat.Count}/{stat.MaxCount}",
|
||||
Font = OsuFont.GetFont(size: text_size),
|
||||
Colour = stat.count == 0 ? Color4.Gray : Color4.White
|
||||
Colour = stat.Count == 0 ? Color4.Gray : Color4.White
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -15,7 +14,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osuTK;
|
||||
@ -117,7 +115,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
ppColumn.Alpha = value.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked ? 1 : 0;
|
||||
ppColumn.Text = $@"{value.PP:N0}";
|
||||
|
||||
statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(s => createStatisticsColumn(s.result, s.count, s.maxCount));
|
||||
statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn);
|
||||
modsColumn.Mods = value.Mods;
|
||||
|
||||
if (scoreManager != null)
|
||||
@ -125,9 +123,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
}
|
||||
}
|
||||
|
||||
private TextColumn createStatisticsColumn(HitResult hitResult, int count, int? maxCount) => new TextColumn(hitResult.GetDescription(), smallFont, bottom_columns_min_width)
|
||||
private TextColumn createStatisticsColumn(HitResultDisplayStatistic stat) => new TextColumn(stat.DisplayName, smallFont, bottom_columns_min_width)
|
||||
{
|
||||
Text = maxCount == null ? $"{count}" : $"{count}/{maxCount}"
|
||||
Text = stat.MaxCount == null ? $"{stat.Count}" : $"{stat.Count}/{stat.MaxCount}"
|
||||
};
|
||||
|
||||
private class InfoColumn : CompositeDrawable
|
||||
|
@ -23,8 +23,10 @@ using osu.Game.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Users;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Ranking.Statistics;
|
||||
using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Rulesets
|
||||
{
|
||||
@ -241,5 +243,52 @@ namespace osu.Game.Rulesets
|
||||
/// <returns>The <see cref="StatisticRow"/>s to display. Each <see cref="StatisticRow"/> may contain 0 or more <see cref="StatisticItem"/>.</returns>
|
||||
[NotNull]
|
||||
public virtual StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => Array.Empty<StatisticRow>();
|
||||
|
||||
/// <summary>
|
||||
/// Get all valid <see cref="HitResult"/>s for this ruleset.
|
||||
/// Generally used for results display purposes, where it can't be determined if zero-count means the user has not achieved any or the type is not used by this ruleset.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// All valid <see cref="HitResult"/>s along with a display-friendly name.
|
||||
/// </returns>
|
||||
public IEnumerable<(HitResult result, string displayName)> GetHitResults()
|
||||
{
|
||||
var validResults = GetValidHitResults();
|
||||
|
||||
// enumerate over ordered list to guarantee return order is stable.
|
||||
foreach (var result in OrderAttributeUtils.GetValuesInOrder<HitResult>())
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
// hard blocked types, should never be displayed even if the ruleset tells us to.
|
||||
case HitResult.None:
|
||||
case HitResult.IgnoreHit:
|
||||
case HitResult.IgnoreMiss:
|
||||
// display is handled as a completion count with corresponding "hit" type.
|
||||
case HitResult.LargeTickMiss:
|
||||
case HitResult.SmallTickMiss:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result == HitResult.Miss || validResults.Contains(result))
|
||||
yield return (result, GetDisplayNameForHitResult(result));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all valid <see cref="HitResult"/>s for this ruleset.
|
||||
/// Generally used for results display purposes, where it can't be determined if zero-count means the user has not achieved any or the type is not used by this ruleset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="HitResult.Miss"/> is implicitly included. Special types like <see cref="HitResult.IgnoreHit"/> are ignored even when specified.
|
||||
/// </remarks>
|
||||
protected virtual IEnumerable<HitResult> GetValidHitResults() => OrderAttributeUtils.GetValuesInOrder<HitResult>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a display friendly name for the specified result type.
|
||||
/// </summary>
|
||||
/// <param name="result">The result type to get the name for.</param>
|
||||
/// <returns>The display name.</returns>
|
||||
public virtual string GetDisplayNameForHitResult(HitResult result) => result.GetDescription();
|
||||
}
|
||||
}
|
||||
|
41
osu.Game/Scoring/HitResultDisplayStatistic.cs
Normal file
41
osu.Game/Scoring/HitResultDisplayStatistic.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Scoring
|
||||
{
|
||||
/// <summary>
|
||||
/// Compiled result data for a specific <see cref="HitResult"/> in a score.
|
||||
/// </summary>
|
||||
public class HitResultDisplayStatistic
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated result type.
|
||||
/// </summary>
|
||||
public HitResult Result { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The count of successful hits of this type.
|
||||
/// </summary>
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum achievable hits of this type. May be null if undetermined.
|
||||
/// </summary>
|
||||
public int? MaxCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A custom display name for the result type. May be provided by rulesets to give better clarity.
|
||||
/// </summary>
|
||||
public string DisplayName { get; }
|
||||
|
||||
public HitResultDisplayStatistic(HitResult result, int count, int? maxCount, string displayName)
|
||||
{
|
||||
Result = result;
|
||||
Count = count;
|
||||
MaxCount = maxCount;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
}
|
||||
}
|
@ -213,22 +213,19 @@ namespace osu.Game.Scoring
|
||||
set => isLegacyScore = value;
|
||||
}
|
||||
|
||||
public IEnumerable<(HitResult result, int count, int? maxCount)> GetStatisticsForDisplay()
|
||||
public IEnumerable<HitResultDisplayStatistic> GetStatisticsForDisplay()
|
||||
{
|
||||
foreach (var key in OrderAttributeUtils.GetValuesInOrder<HitResult>())
|
||||
foreach (var r in Ruleset.CreateInstance().GetHitResults())
|
||||
{
|
||||
if (key.IsBonus())
|
||||
continue;
|
||||
int value = Statistics.GetOrDefault(r.result);
|
||||
|
||||
int value = Statistics.GetOrDefault(key);
|
||||
|
||||
switch (key)
|
||||
switch (r.result)
|
||||
{
|
||||
case HitResult.SmallTickHit:
|
||||
{
|
||||
int total = value + Statistics.GetOrDefault(HitResult.SmallTickMiss);
|
||||
if (total > 0)
|
||||
yield return (key, value, total);
|
||||
yield return new HitResultDisplayStatistic(r.result, value, total, r.displayName);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -237,7 +234,7 @@ namespace osu.Game.Scoring
|
||||
{
|
||||
int total = value + Statistics.GetOrDefault(HitResult.LargeTickMiss);
|
||||
if (total > 0)
|
||||
yield return (key, value, total);
|
||||
yield return new HitResultDisplayStatistic(r.result, value, total, r.displayName);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -247,8 +244,7 @@ namespace osu.Game.Scoring
|
||||
break;
|
||||
|
||||
default:
|
||||
if (value > 0 || key == HitResult.Miss)
|
||||
yield return (key, value, null);
|
||||
yield return new HitResultDisplayStatistic(r.result, value, null, r.displayName);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
@ -117,7 +116,7 @@ namespace osu.Game.Screens.Ranking.Contracted
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
ChildrenEnumerable = score.GetStatisticsForDisplay().Select(s => createStatistic(s.result, s.count, s.maxCount))
|
||||
ChildrenEnumerable = score.GetStatisticsForDisplay().Where(s => !s.Result.IsBonus()).Select(createStatistic)
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
@ -199,8 +198,8 @@ namespace osu.Game.Screens.Ranking.Contracted
|
||||
};
|
||||
}
|
||||
|
||||
private Drawable createStatistic(HitResult result, int count, int? maxCount)
|
||||
=> createStatistic(result.GetDescription(), maxCount == null ? $"{count}" : $"{count}/{maxCount}");
|
||||
private Drawable createStatistic(HitResultDisplayStatistic result)
|
||||
=> createStatistic(result.DisplayName, result.MaxCount == null ? $"{result.Count}" : $"{result.Count}/{result.MaxCount}");
|
||||
|
||||
private Drawable createStatistic(string key, string value) => new Container
|
||||
{
|
||||
|
@ -64,155 +64,168 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
new CounterStatistic("pp", (int)(score.PP ?? 0)),
|
||||
};
|
||||
|
||||
var bottomStatistics = new List<StatisticDisplay>();
|
||||
var bottomStatistics = new List<HitResultStatistic>();
|
||||
|
||||
foreach (var (key, value, maxCount) in score.GetStatisticsForDisplay())
|
||||
bottomStatistics.Add(new HitResultStatistic(key, value, maxCount));
|
||||
foreach (var result in score.GetStatisticsForDisplay())
|
||||
bottomStatistics.Add(new HitResultStatistic(result));
|
||||
|
||||
statisticDisplays.AddRange(topStatistics);
|
||||
statisticDisplays.AddRange(bottomStatistics);
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(20),
|
||||
Children = new Drawable[]
|
||||
new FillFlowContainer
|
||||
{
|
||||
new FillFlowContainer
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
new FillFlowContainer
|
||||
{
|
||||
new OsuSpriteText
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)),
|
||||
Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold),
|
||||
MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2,
|
||||
Truncate = true,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)),
|
||||
Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold),
|
||||
MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2,
|
||||
Truncate = true,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Margin = new MarginPadding { Top = 40 },
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 230,
|
||||
Child = new AccuracyCircle(score)
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
}
|
||||
},
|
||||
scoreCounter = new TotalScoreCounter
|
||||
{
|
||||
Margin = new MarginPadding { Top = 0, Bottom = 5 },
|
||||
Current = { Value = 0 },
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
},
|
||||
starAndModDisplay = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new Drawable[]
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)),
|
||||
Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold),
|
||||
MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2,
|
||||
Truncate = true,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
new StarRatingDisplay(beatmap)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft
|
||||
},
|
||||
}
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)),
|
||||
Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold),
|
||||
MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2,
|
||||
Truncate = true,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
new OsuSpriteText
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Margin = new MarginPadding { Top = 40 },
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 230,
|
||||
Child = new AccuracyCircle(score)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = beatmap.Version,
|
||||
Font = OsuFont.Torus.With(size: 16, weight: FontWeight.SemiBold),
|
||||
},
|
||||
new OsuTextFlowContainer(s => s.Font = OsuFont.Torus.With(size: 12))
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
}
|
||||
},
|
||||
scoreCounter = new TotalScoreCounter
|
||||
{
|
||||
Margin = new MarginPadding { Top = 0, Bottom = 5 },
|
||||
Current = { Value = 0 },
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
},
|
||||
starAndModDisplay = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
}.With(t =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(creator))
|
||||
new StarRatingDisplay(beatmap)
|
||||
{
|
||||
t.AddText("mapped by ");
|
||||
t.AddText(creator, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft
|
||||
},
|
||||
}
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = beatmap.Version,
|
||||
Font = OsuFont.Torus.With(size: 16, weight: FontWeight.SemiBold),
|
||||
},
|
||||
new OsuTextFlowContainer(s => s.Font = OsuFont.Torus.With(size: 12))
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
}.With(t =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(creator))
|
||||
{
|
||||
t.AddText("mapped by ");
|
||||
t.AddText(creator, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
new GridContainer
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[] { topStatistics.Cast<Drawable>().ToArray() },
|
||||
RowDimensions = new[]
|
||||
new GridContainer
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
}
|
||||
},
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[] { bottomStatistics.Cast<Drawable>().ToArray() },
|
||||
RowDimensions = new[]
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[] { topStatistics.Cast<Drawable>().ToArray() },
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
}
|
||||
},
|
||||
new GridContainer
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[] { bottomStatistics.Where(s => s.Result <= HitResult.Perfect).ToArray() },
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
}
|
||||
},
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[] { bottomStatistics.Where(s => s.Result > HitResult.Perfect).ToArray() },
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
|
||||
Text = $"Played on {score.Date.ToLocalTime():d MMMM yyyy HH:mm}"
|
||||
}
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
|
||||
Text = $"Played on {score.Date.ToLocalTime():d MMMM yyyy HH:mm}"
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,26 +2,26 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Ranking.Expanded.Statistics
|
||||
{
|
||||
public class HitResultStatistic : CounterStatistic
|
||||
{
|
||||
private readonly HitResult result;
|
||||
public readonly HitResult Result;
|
||||
|
||||
public HitResultStatistic(HitResult result, int count, int? maxCount = null)
|
||||
: base(result.GetDescription(), count, maxCount)
|
||||
public HitResultStatistic(HitResultDisplayStatistic result)
|
||||
: base(result.DisplayName, result.Count, result.MaxCount)
|
||||
{
|
||||
this.result = result;
|
||||
Result = result.Result;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
HeaderText.Colour = colours.ForHitResult(result);
|
||||
HeaderText.Colour = colours.ForHitResult(Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Screens.Ranking
|
||||
/// <summary>
|
||||
/// Height of the panel when contracted.
|
||||
/// </summary>
|
||||
private const float contracted_height = 355;
|
||||
private const float contracted_height = 385;
|
||||
|
||||
/// <summary>
|
||||
/// Width of the panel when expanded.
|
||||
@ -39,7 +39,7 @@ namespace osu.Game.Screens.Ranking
|
||||
/// <summary>
|
||||
/// Height of the panel when expanded.
|
||||
/// </summary>
|
||||
private const float expanded_height = 560;
|
||||
private const float expanded_height = 586;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the top layer when the panel is expanded.
|
||||
@ -105,11 +105,16 @@ namespace osu.Game.Screens.Ranking
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
// ScorePanel doesn't include the top extruding area in its own size.
|
||||
// Adding a manual offset here allows the expanded version to take on an "acceptable" vertical centre when at 100% UI scale.
|
||||
const float vertical_fudge = 20;
|
||||
|
||||
InternalChild = content = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(40),
|
||||
Y = vertical_fudge,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
topLayerContainer = new Container
|
||||
|
Loading…
x
Reference in New Issue
Block a user