mirror of
https://github.com/ppy/osu.git
synced 2025-02-10 08:52:54 +08:00
Merge pull request #16743 from hlysine/extended-statistics-without-replay
Allow statistic items in results screen to display without needing to watch a replay
This commit is contained in:
commit
63064d682b
@ -370,21 +370,21 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
Columns = new[]
|
Columns = new[]
|
||||||
{
|
{
|
||||||
new StatisticItem("Timing Distribution", new HitEventTimingDistributionGraph(score.HitEvents)
|
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 250
|
Height = 250
|
||||||
}),
|
}, true),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new StatisticRow
|
new StatisticRow
|
||||||
{
|
{
|
||||||
Columns = new[]
|
Columns = new[]
|
||||||
{
|
{
|
||||||
new StatisticItem(string.Empty, new SimpleStatisticTable(3, new SimpleStatisticItem[]
|
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
|
||||||
{
|
{
|
||||||
new UnstableRate(score.HitEvents)
|
new UnstableRate(score.HitEvents)
|
||||||
}))
|
}), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -279,33 +279,32 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
{
|
{
|
||||||
Columns = new[]
|
Columns = new[]
|
||||||
{
|
{
|
||||||
new StatisticItem("Timing Distribution",
|
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents)
|
||||||
new HitEventTimingDistributionGraph(timedHitEvents)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 250
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new StatisticRow
|
|
||||||
{
|
|
||||||
Columns = new[]
|
|
||||||
{
|
|
||||||
new StatisticItem("Accuracy Heatmap", new AccuracyHeatmap(score, playableBeatmap)
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 250
|
Height = 250
|
||||||
}),
|
}, true),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new StatisticRow
|
new StatisticRow
|
||||||
{
|
{
|
||||||
Columns = new[]
|
Columns = new[]
|
||||||
{
|
{
|
||||||
new StatisticItem(string.Empty, new SimpleStatisticTable(3, new SimpleStatisticItem[]
|
new StatisticItem("Accuracy Heatmap", () => new AccuracyHeatmap(score, playableBeatmap)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 250
|
||||||
|
}, true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new StatisticRow
|
||||||
|
{
|
||||||
|
Columns = new[]
|
||||||
|
{
|
||||||
|
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
|
||||||
{
|
{
|
||||||
new UnstableRate(timedHitEvents)
|
new UnstableRate(timedHitEvents)
|
||||||
}))
|
}), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -213,21 +213,21 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
{
|
{
|
||||||
Columns = new[]
|
Columns = new[]
|
||||||
{
|
{
|
||||||
new StatisticItem("Timing Distribution", new HitEventTimingDistributionGraph(timedHitEvents)
|
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 250
|
Height = 250
|
||||||
}),
|
}, true),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new StatisticRow
|
new StatisticRow
|
||||||
{
|
{
|
||||||
Columns = new[]
|
Columns = new[]
|
||||||
{
|
{
|
||||||
new StatisticItem(string.Empty, new SimpleStatisticTable(3, new SimpleStatisticItem[]
|
new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[]
|
||||||
{
|
{
|
||||||
new UnstableRate(timedHitEvents)
|
new UnstableRate(timedHitEvents)
|
||||||
}))
|
}), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,10 +6,18 @@ using System.Collections.Generic;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Ranking.Statistics;
|
using osu.Game.Screens.Ranking.Statistics;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Tests.Resources;
|
using osu.Game.Tests.Resources;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -41,6 +49,24 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
loadPanel(TestResources.CreateTestScoreInfo());
|
loadPanel(TestResources.CreateTestScoreInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScoreInRulesetWhereAllStatsRequireHitEvents()
|
||||||
|
{
|
||||||
|
loadPanel(TestResources.CreateTestScoreInfo(new TestRulesetAllStatsRequireHitEvents().RulesetInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScoreInRulesetWhereNoStatsRequireHitEvents()
|
||||||
|
{
|
||||||
|
loadPanel(TestResources.CreateTestScoreInfo(new TestRulesetNoStatsRequireHitEvents().RulesetInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScoreInMixedRuleset()
|
||||||
|
{
|
||||||
|
loadPanel(TestResources.CreateTestScoreInfo(new TestRulesetMixed().RulesetInfo));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestNullScore()
|
public void TestNullScore()
|
||||||
{
|
{
|
||||||
@ -75,5 +101,134 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
|
|
||||||
return hitEvents;
|
return hitEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestRuleset : Ruleset
|
||||||
|
{
|
||||||
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description => string.Empty;
|
||||||
|
|
||||||
|
public override string ShortName => string.Empty;
|
||||||
|
|
||||||
|
protected static Drawable CreatePlaceholderStatistic(string message) => new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 20,
|
||||||
|
Height = 250,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.Gray(0.5f),
|
||||||
|
Alpha = 0.5f
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Text = message,
|
||||||
|
Margin = new MarginPadding { Left = 20 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestRulesetAllStatsRequireHitEvents : TestRuleset
|
||||||
|
{
|
||||||
|
public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestRulesetNoStatsRequireHitEvents : TestRuleset
|
||||||
|
{
|
||||||
|
public override StatisticRow[] 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestRulesetMixed : TestRuleset
|
||||||
|
{
|
||||||
|
public override StatisticRow[] 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Ranking.Statistics
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Margin = new MarginPadding { Top = 15 },
|
Margin = new MarginPadding { Top = 15 },
|
||||||
Child = item.Content
|
Child = item.CreateContent()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -18,25 +19,38 @@ namespace osu.Game.Screens.Ranking.Statistics
|
|||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="Drawable"/> content to be displayed.
|
/// A function returning the <see cref="Drawable"/> content to be displayed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Drawable Content;
|
public readonly Func<Drawable> CreateContent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="Dimension"/> of this row. This can be thought of as the column dimension of an encompassing <see cref="GridContainer"/>.
|
/// The <see cref="Dimension"/> of this row. This can be thought of as the column dimension of an encompassing <see cref="GridContainer"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Dimension Dimension;
|
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;
|
||||||
|
|
||||||
|
[Obsolete("Use constructor which takes creation function instead.")] // Can be removed 20220803.
|
||||||
|
public StatisticItem([NotNull] string name, [NotNull] Drawable content, [CanBeNull] Dimension dimension = null)
|
||||||
|
: this(name, () => content, true, dimension)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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 inside a <see cref="StatisticRow"/> in the results screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name of the item. Can be <see cref="string.Empty"/> to hide the item header.</param>
|
/// <param name="name">The name of the item. Can be <see cref="string.Empty"/> to hide the item header.</param>
|
||||||
/// <param name="content">The <see cref="Drawable"/> content to be displayed.</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>
|
/// <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([NotNull] string name, [NotNull] Drawable content, [CanBeNull] Dimension dimension = null)
|
public StatisticItem([NotNull] string name, [NotNull] Func<Drawable> createContent, bool requiresHitEvents = false, [CanBeNull] Dimension dimension = null)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Content = content;
|
RequiresHitEvents = requiresHitEvents;
|
||||||
|
CreateContent = createContent;
|
||||||
Dimension = dimension;
|
Dimension = dimension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -10,6 +11,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.Placeholders;
|
using osu.Game.Online.Placeholders;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -74,81 +76,136 @@ namespace osu.Game.Screens.Ranking.Statistics
|
|||||||
if (newScore == null)
|
if (newScore == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (newScore.HitEvents.Count == 0)
|
spinner.Show();
|
||||||
{
|
|
||||||
content.Add(new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new MessagePlaceholder("Extended statistics are only available after watching a replay!"),
|
|
||||||
new ReplayDownloadButton(newScore)
|
|
||||||
{
|
|
||||||
Scale = new Vector2(1.5f),
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
spinner.Show();
|
|
||||||
|
|
||||||
var localCancellationSource = loadCancellation = new CancellationTokenSource();
|
var localCancellationSource = loadCancellation = new CancellationTokenSource();
|
||||||
IBeatmap playableBeatmap = null;
|
IBeatmap playableBeatmap = null;
|
||||||
|
|
||||||
// Todo: The placement of this is temporary. Eventually we'll both generate the playable beatmap _and_ run through it in a background task to generate the hit events.
|
// Todo: The placement of this is temporary. Eventually we'll both generate the playable beatmap _and_ run through it in a background task to generate the hit events.
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
playableBeatmap = beatmapManager.GetWorkingBeatmap(newScore.BeatmapInfo).GetPlayableBeatmap(newScore.Ruleset, newScore.Mods);
|
||||||
|
}, loadCancellation.Token).ContinueWith(t => Schedule(() =>
|
||||||
|
{
|
||||||
|
bool hitEventsAvailable = newScore.HitEvents.Count != 0;
|
||||||
|
Container<Drawable> container;
|
||||||
|
|
||||||
|
var statisticRows = newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, playableBeatmap);
|
||||||
|
|
||||||
|
if (!hitEventsAvailable && statisticRows.SelectMany(r => r.Columns).All(c => c.RequiresHitEvents))
|
||||||
{
|
{
|
||||||
playableBeatmap = beatmapManager.GetWorkingBeatmap(newScore.BeatmapInfo).GetPlayableBeatmap(newScore.Ruleset, newScore.Mods);
|
container = new FillFlowContainer
|
||||||
}, loadCancellation.Token).ContinueWith(t => Schedule(() =>
|
|
||||||
{
|
|
||||||
var rows = new FillFlowContainer
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.Both,
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Spacing = new Vector2(30, 15),
|
Children = new Drawable[]
|
||||||
Alpha = 0
|
{
|
||||||
|
new MessagePlaceholder("Extended statistics are only available after watching a replay!"),
|
||||||
|
new ReplayDownloadButton(newScore)
|
||||||
|
{
|
||||||
|
Scale = new Vector2(1.5f),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FillFlowContainer rows;
|
||||||
|
container = new OsuScrollContainer(Direction.Vertical)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Alpha = 0,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
rows = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Spacing = new Vector2(30, 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var row in newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, playableBeatmap))
|
bool anyRequiredHitEvents = false;
|
||||||
|
|
||||||
|
foreach (var row in statisticRows)
|
||||||
{
|
{
|
||||||
|
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 && col.RequiresHitEvents)
|
||||||
|
{
|
||||||
|
anyRequiredHitEvents = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
columnContent.Add(new StatisticContainer(col)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
});
|
||||||
|
|
||||||
|
dimensions.Add(col.Dimension ?? new Dimension());
|
||||||
|
}
|
||||||
|
|
||||||
rows.Add(new GridContainer
|
rows.Add(new GridContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Content = new[]
|
Content = new[] { columnContent.ToArray() },
|
||||||
{
|
ColumnDimensions = dimensions.ToArray(),
|
||||||
row.Columns?.Select(c => new StatisticContainer(c)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
}).Cast<Drawable>().ToArray()
|
|
||||||
},
|
|
||||||
ColumnDimensions = Enumerable.Range(0, row.Columns?.Length ?? 0)
|
|
||||||
.Select(i => row.Columns[i].Dimension ?? new Dimension()).ToArray(),
|
|
||||||
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadComponentAsync(rows, d =>
|
if (anyRequiredHitEvents)
|
||||||
{
|
{
|
||||||
if (!Score.Value.Equals(newScore))
|
rows.Add(new FillFlowContainer
|
||||||
return;
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new MessagePlaceholder("More statistics available after watching a replay!"),
|
||||||
|
new ReplayDownloadButton(newScore)
|
||||||
|
{
|
||||||
|
Scale = new Vector2(1.5f),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spinner.Hide();
|
LoadComponentAsync(container, d =>
|
||||||
content.Add(d);
|
{
|
||||||
d.FadeIn(250, Easing.OutQuint);
|
if (!Score.Value.Equals(newScore))
|
||||||
}, localCancellationSource.Token);
|
return;
|
||||||
}), localCancellationSource.Token);
|
|
||||||
}
|
spinner.Hide();
|
||||||
|
content.Add(d);
|
||||||
|
d.FadeIn(250, Easing.OutQuint);
|
||||||
|
}, localCancellationSource.Token);
|
||||||
|
}), localCancellationSource.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
|
Loading…
Reference in New Issue
Block a user