1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 08:52:55 +08:00

Merge pull request #23718 from peppy/tidy-results-grid-usage

Tidy up results screen statistic item flow
This commit is contained in:
Bartłomiej Dach 2023-06-04 16:57:51 +02:00 committed by GitHub
commit d0167cb324
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 234 deletions

View File

@ -389,41 +389,23 @@ namespace osu.Game.Rulesets.Mania
return base.GetDisplayNameForHitResult(result);
}
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[]
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[]
{
new StatisticRow
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{
Columns = new[]
{
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}),
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents)
{
Columns = new[]
{
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents)
{
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
{
Columns = new[]
{
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
{
new AverageHitError(score.HitEvents),
new UnstableRate(score.HitEvents)
}), true)
}
}
new AverageHitError(score.HitEvents),
new UnstableRate(score.HitEvents)
}), true)
};
public override IRulesetFilterCriteria CreateRulesetFilterCriteria()

View File

@ -291,56 +291,32 @@ namespace osu.Game.Rulesets.Osu
return base.GetDisplayNameForHitResult(result);
}
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
{
var timedHitEvents = score.HitEvents.Where(e => e.HitObject is HitCircle && !(e.HitObject is SliderTailCircle)).ToList();
return new[]
{
new StatisticRow
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{
Columns = new[]
{
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}),
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents)
{
Columns = new[]
{
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents)
{
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
new StatisticItem("Accuracy Heatmap", () => new AccuracyHeatmap(score, playableBeatmap)
{
Columns = new[]
{
new StatisticItem("Accuracy Heatmap", () => new AccuracyHeatmap(score, playableBeatmap)
{
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
{
Columns = new[]
{
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
{
new AverageHitError(timedHitEvents),
new UnstableRate(timedHitEvents)
}), true)
}
}
new AverageHitError(timedHitEvents),
new UnstableRate(timedHitEvents)
}), true)
};
}

View File

@ -229,45 +229,27 @@ namespace osu.Game.Rulesets.Taiko
return base.GetDisplayNameForHitResult(result);
}
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
{
var timedHitEvents = score.HitEvents.Where(e => e.HitObject is Hit).ToList();
return new[]
{
new StatisticRow
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{
Columns = new[]
{
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}),
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents)
{
Columns = new[]
{
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents)
{
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
}
},
new StatisticRow
RelativeSizeAxes = Axes.X,
Height = 250
}, true),
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
{
Columns = new[]
{
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
{
new AverageHitError(timedHitEvents),
new UnstableRate(timedHitEvents)
}), true)
}
}
new AverageHitError(timedHitEvents),
new UnstableRate(timedHitEvents)
}), true)
};
}
}

View File

@ -174,78 +174,33 @@ namespace osu.Game.Tests.Visual.Ranking
private class TestRulesetAllStatsRequireHitEvents : TestRuleset
{
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[]
{
return new[]
{
new StatisticRow
{
Columns = new[]
{
new StatisticItem("Statistic Requiring Hit Events 1",
() => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true)
}
},
new StatisticRow
{
Columns = new[]
{
new StatisticItem("Statistic Requiring Hit Events 2",
() => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true)
}
}
};
}
new StatisticItem("Statistic Requiring Hit Events 1", () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true),
new StatisticItem("Statistic Requiring Hit Events 2", () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true)
};
}
private class TestRulesetNoStatsRequireHitEvents : TestRuleset
{
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
{
return new[]
{
new StatisticRow
{
Columns = new[]
{
new StatisticItem("Statistic Not Requiring Hit Events 1",
() => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events"))
}
},
new StatisticRow
{
Columns = new[]
{
new StatisticItem("Statistic Not Requiring Hit Events 2",
() => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events"))
}
}
new StatisticItem("Statistic Not Requiring Hit Events 1", () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")),
new StatisticItem("Statistic Not Requiring Hit Events 2", () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events"))
};
}
}
private class TestRulesetMixed : TestRuleset
{
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
{
return new[]
{
new StatisticRow
{
Columns = new[]
{
new StatisticItem("Statistic Requiring Hit Events",
() => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true)
}
},
new StatisticRow
{
Columns = new[]
{
new StatisticItem("Statistic Not Requiring Hit Events",
() => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events"))
}
}
new StatisticItem("Statistic Requiring Hit Events", () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true),
new StatisticItem("Statistic Not Requiring Hit Events", () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events"))
};
}
}

View File

@ -321,8 +321,8 @@ namespace osu.Game.Rulesets
/// </summary>
/// <param name="score">The <see cref="ScoreInfo"/> to create the statistics for. The score is guaranteed to have <see cref="ScoreInfo.HitEvents"/> populated.</param>
/// <param name="playableBeatmap">The <see cref="IBeatmap"/>, converted for this <see cref="Ruleset"/> with all relevant <see cref="Mod"/>s applied.</param>
/// <returns>The <see cref="StatisticRow"/>s to display. Each <see cref="StatisticRow"/> may contain 0 or more <see cref="StatisticItem"/>.</returns>
public virtual StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => Array.Empty<StatisticRow>();
/// <returns>The <see cref="StatisticItem"/>s to display.</returns>
public virtual StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => Array.Empty<StatisticItem>();
/// <summary>
/// Get all valid <see cref="HitResult"/>s for this ruleset.

View File

@ -17,7 +17,7 @@ namespace osu.Game.Screens.Ranking.Statistics
{
/// <summary>
/// Represents a table with simple statistics (ones that only need textual display).
/// Richer visualisations should be done with <see cref="StatisticRow"/>s and <see cref="StatisticItem"/>s.
/// Richer visualisations should be done with <see cref="StatisticItem"/>s.
/// </summary>
public partial class SimpleStatisticTable : CompositeDrawable
{

View File

@ -23,32 +23,26 @@ namespace osu.Game.Screens.Ranking.Statistics
public Bindable<SoloStatisticsUpdate?> StatisticsUpdate { get; } = new Bindable<SoloStatisticsUpdate?>();
protected override ICollection<StatisticRow> CreateStatisticRows(ScoreInfo newScore, IBeatmap playableBeatmap)
protected override ICollection<StatisticItem> CreateStatisticItems(ScoreInfo newScore, IBeatmap playableBeatmap)
{
var rows = base.CreateStatisticRows(newScore, playableBeatmap);
var items = base.CreateStatisticItems(newScore, playableBeatmap);
if (newScore.UserID > 1
&& newScore.UserID == achievedScore.UserID
&& newScore.OnlineID > 0
&& newScore.OnlineID == achievedScore.OnlineID)
{
rows = rows.Append(new StatisticRow
items = items.Append(new StatisticItem("Overall Ranking", () => new OverallRanking
{
Columns = new[]
{
new StatisticItem("Overall Ranking", () => new OverallRanking
{
RelativeSizeAxes = Axes.X,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 0.5f,
StatisticsUpdate = { BindTarget = StatisticsUpdate }
})
}
}).ToArray();
RelativeSizeAxes = Axes.X,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 0.5f,
StatisticsUpdate = { BindTarget = StatisticsUpdate }
})).ToArray();
}
return rows;
return items;
}
}
}

View File

@ -6,7 +6,6 @@
using System;
using JetBrains.Annotations;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Localisation;
namespace osu.Game.Screens.Ranking.Statistics
@ -26,29 +25,22 @@ namespace osu.Game.Screens.Ranking.Statistics
/// </summary>
public readonly Func<Drawable> CreateContent;
/// <summary>
/// The <see cref="Dimension"/> of this row. This can be thought of as the column dimension of an encompassing <see cref="GridContainer"/>.
/// </summary>
public readonly Dimension Dimension;
/// <summary>
/// Whether this item requires hit events. If true, <see cref="CreateContent"/> will not be called if no hit events are available.
/// </summary>
public readonly bool RequiresHitEvents;
/// <summary>
/// Creates a new <see cref="StatisticItem"/>, to be displayed inside a <see cref="StatisticRow"/> in the results screen.
/// Creates a new <see cref="StatisticItem"/>, to be displayed in the results screen.
/// </summary>
/// <param name="name">The name of the item. Can be <see langword="null"/> to hide the item header.</param>
/// <param name="createContent">A function returning the <see cref="Drawable"/> content to be displayed.</param>
/// <param name="requiresHitEvents">Whether this item requires hit events. If true, <see cref="CreateContent"/> will not be called if no hit events are available.</param>
/// <param name="dimension">The <see cref="Dimension"/> of this item. This can be thought of as the column dimension of an encompassing <see cref="GridContainer"/>.</param>
public StatisticItem(LocalisableString name, [NotNull] Func<Drawable> createContent, bool requiresHitEvents = false, [CanBeNull] Dimension dimension = null)
public StatisticItem(LocalisableString name, [NotNull] Func<Drawable> createContent, bool requiresHitEvents = false)
{
Name = name;
RequiresHitEvents = requiresHitEvents;
CreateContent = createContent;
Dimension = dimension;
}
}
}

View File

@ -1,21 +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.
#nullable disable
using JetBrains.Annotations;
namespace osu.Game.Screens.Ranking.Statistics
{
/// <summary>
/// A row of statistics to be displayed in the results screen.
/// </summary>
public class StatisticRow
{
/// <summary>
/// The columns of this <see cref="StatisticRow"/>.
/// </summary>
[ItemNotNull]
public StatisticItem[] Columns;
}
}

View File

@ -100,9 +100,9 @@ namespace osu.Game.Screens.Ranking.Statistics
bool hitEventsAvailable = newScore.HitEvents.Count != 0;
Container<Drawable> container;
var statisticRows = CreateStatisticRows(newScore, task.GetResultSafely());
var statisticItems = CreateStatisticItems(newScore, task.GetResultSafely());
if (!hitEventsAvailable && statisticRows.SelectMany(r => r.Columns).All(c => c.RequiresHitEvents))
if (!hitEventsAvailable && statisticItems.All(c => c.RequiresHitEvents))
{
container = new FillFlowContainer
{
@ -144,33 +144,22 @@ namespace osu.Game.Screens.Ranking.Statistics
bool anyRequiredHitEvents = false;
foreach (var row in statisticRows)
foreach (var item in statisticItems)
{
var columns = row.Columns;
if (columns.Length == 0)
continue;
var columnContent = new List<Drawable>();
var dimensions = new List<Dimension>();
foreach (var col in columns)
if (!hitEventsAvailable && item.RequiresHitEvents)
{
if (!hitEventsAvailable && col.RequiresHitEvents)
{
anyRequiredHitEvents = true;
continue;
}
columnContent.Add(new StatisticContainer(col)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
});
dimensions.Add(col.Dimension ?? new Dimension());
anyRequiredHitEvents = true;
continue;
}
columnContent.Add(new StatisticContainer(item)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
});
rows.Add(new GridContainer
{
Anchor = Anchor.TopCentre,
@ -178,7 +167,7 @@ namespace osu.Game.Screens.Ranking.Statistics
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Content = new[] { columnContent.ToArray() },
ColumnDimensions = dimensions.ToArray(),
ColumnDimensions = new[] { new Dimension() },
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
});
}
@ -219,11 +208,11 @@ namespace osu.Game.Screens.Ranking.Statistics
}
/// <summary>
/// Creates the <see cref="StatisticRow"/>s to be displayed in this panel for a given <paramref name="newScore"/>.
/// Creates the <see cref="StatisticItem"/>s to be displayed in this panel for a given <paramref name="newScore"/>.
/// </summary>
/// <param name="newScore">The score to create the rows for.</param>
/// <param name="playableBeatmap">The beatmap on which the score was set.</param>
protected virtual ICollection<StatisticRow> CreateStatisticRows(ScoreInfo newScore, IBeatmap playableBeatmap)
protected virtual ICollection<StatisticItem> CreateStatisticItems(ScoreInfo newScore, IBeatmap playableBeatmap)
=> newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, playableBeatmap);
protected override bool OnClick(ClickEvent e)