1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-08 10:03:43 +08:00

Compare commits

...

23 Commits

11 changed files with 181 additions and 64 deletions
@@ -464,7 +464,9 @@ namespace osu.Game.Tests.Visual.SongSelect
manager.Import(testBeatmapSetInfo); manager.Import(testBeatmapSetInfo);
}, 10); }, 10);
AddUntilStep("has selection", () => songSelect!.Carousel.SelectedBeatmapInfo?.BeatmapSet?.OnlineID == originalOnlineSetID); AddStep("Force realm refresh", () => Realm.Run(r => r.Refresh()));
AddUntilStep("has selection", () => songSelect!.Carousel.SelectedBeatmapInfo?.BeatmapSet?.OnlineID, () => Is.EqualTo(originalOnlineSetID));
Task<Live<BeatmapSetInfo>?> updateTask = null!; Task<Live<BeatmapSetInfo>?> updateTask = null!;
@@ -476,7 +478,9 @@ namespace osu.Game.Tests.Visual.SongSelect
}); });
AddUntilStep("wait for update completion", () => updateTask.IsCompleted); AddUntilStep("wait for update completion", () => updateTask.IsCompleted);
AddUntilStep("retained selection", () => songSelect!.Carousel.SelectedBeatmapInfo?.BeatmapSet?.OnlineID == originalOnlineSetID); AddStep("Force realm refresh", () => Realm.Run(r => r.Refresh()));
AddUntilStep("retained selection", () => songSelect!.Carousel.SelectedBeatmapInfo?.BeatmapSet?.OnlineID, () => Is.EqualTo(originalOnlineSetID));
} }
[Test] [Test]
+100 -18
View File
@@ -67,6 +67,7 @@ namespace osu.Game
checkForOutdatedStarRatings(); checkForOutdatedStarRatings();
processBeatmapSetsWithMissingMetrics(); processBeatmapSetsWithMissingMetrics();
// Note that the previous method will also update these on a fresh run.
processBeatmapsWithMissingObjectCounts(); processBeatmapsWithMissingObjectCounts();
processScoresWithMissingStatistics(); processScoresWithMissingStatistics();
convertLegacyTotalScoreToStandardised(); convertLegacyTotalScoreToStandardised();
@@ -144,12 +145,24 @@ namespace osu.Game
} }
}); });
if (beatmapSetIds.Count == 0)
return;
Logger.Log($"Found {beatmapSetIds.Count} beatmap sets which require reprocessing."); Logger.Log($"Found {beatmapSetIds.Count} beatmap sets which require reprocessing.");
int i = 0; // Technically this is doing more than just star ratings, but easier for the end user to understand.
var notification = showProgressNotification(beatmapSetIds.Count, "Reprocessing star rating for beatmaps", "beatmaps' star ratings have been updated");
int processedCount = 0;
int failedCount = 0;
foreach (var id in beatmapSetIds) foreach (var id in beatmapSetIds)
{ {
if (notification?.State == ProgressNotificationState.Cancelled)
break;
updateNotificationProgress(notification, processedCount, beatmapSetIds.Count);
sleepIfRequired(); sleepIfRequired();
realmAccess.Run(r => realmAccess.Run(r =>
@@ -160,16 +173,19 @@ namespace osu.Game
{ {
try try
{ {
Logger.Log($"Background processing {set} ({++i} / {beatmapSetIds.Count})");
beatmapUpdater.Process(set); beatmapUpdater.Process(set);
++processedCount;
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Log($"Background processing failed on {set}: {e}"); Logger.Log($"Background processing failed on {set}: {e}");
++failedCount;
} }
} }
}); });
} }
completeNotification(notification, processedCount, beatmapSetIds.Count, failedCount);
} }
private void processBeatmapsWithMissingObjectCounts() private void processBeatmapsWithMissingObjectCounts()
@@ -184,12 +200,23 @@ namespace osu.Game
beatmapIds.Add(b.ID); beatmapIds.Add(b.ID);
}); });
Logger.Log($"Found {beatmapIds.Count} beatmaps which require reprocessing."); if (beatmapIds.Count == 0)
return;
int i = 0; Logger.Log($"Found {beatmapIds.Count} beatmaps which require statistics population.");
var notification = showProgressNotification(beatmapIds.Count, "Populating missing statistics for beatmaps", "beatmaps have been populated with missing statistics");
int processedCount = 0;
int failedCount = 0;
foreach (var id in beatmapIds) foreach (var id in beatmapIds)
{ {
if (notification?.State == ProgressNotificationState.Cancelled)
break;
updateNotificationProgress(notification, processedCount, beatmapIds.Count);
sleepIfRequired(); sleepIfRequired();
realmAccess.Run(r => realmAccess.Run(r =>
@@ -200,16 +227,19 @@ namespace osu.Game
{ {
try try
{ {
Logger.Log($"Background processing {beatmap} ({++i} / {beatmapIds.Count})");
beatmapUpdater.ProcessObjectCounts(beatmap); beatmapUpdater.ProcessObjectCounts(beatmap);
++processedCount;
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Log($"Background processing failed on {beatmap}: {e}"); Logger.Log($"Background processing failed on {beatmap}: {e}");
++failedCount;
} }
} }
}); });
} }
completeNotification(notification, processedCount, beatmapIds.Count, failedCount);
} }
private void processScoresWithMissingStatistics() private void processScoresWithMissingStatistics()
@@ -231,10 +261,23 @@ namespace osu.Game
} }
}); });
Logger.Log($"Found {scoreIds.Count} scores which require reprocessing."); if (scoreIds.Count == 0)
return;
Logger.Log($"Found {scoreIds.Count} scores which require statistics population.");
var notification = showProgressNotification(scoreIds.Count, "Populating missing statistics for scores", "scores have been populated with missing statistics");
int processedCount = 0;
int failedCount = 0;
foreach (var id in scoreIds) foreach (var id in scoreIds)
{ {
if (notification?.State == ProgressNotificationState.Cancelled)
break;
updateNotificationProgress(notification, processedCount, scoreIds.Count);
sleepIfRequired(); sleepIfRequired();
try try
@@ -250,7 +293,7 @@ namespace osu.Game
r.Find<ScoreInfo>(id)!.MaximumStatisticsJson = JsonConvert.SerializeObject(score.MaximumStatistics); r.Find<ScoreInfo>(id)!.MaximumStatisticsJson = JsonConvert.SerializeObject(score.MaximumStatistics);
}); });
Logger.Log($"Populated maximum statistics for score {id}"); ++processedCount;
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
@@ -260,8 +303,11 @@ namespace osu.Game
{ {
Logger.Log(@$"Failed to populate maximum statistics for {id}: {e}"); Logger.Log(@$"Failed to populate maximum statistics for {id}: {e}");
realmAccess.Write(r => r.Find<ScoreInfo>(id)!.BackgroundReprocessingFailed = true); realmAccess.Write(r => r.Find<ScoreInfo>(id)!.BackgroundReprocessingFailed = true);
++failedCount;
} }
} }
completeNotification(notification, processedCount, scoreIds.Count, failedCount);
} }
private void convertLegacyTotalScoreToStandardised() private void convertLegacyTotalScoreToStandardised()
@@ -279,20 +325,17 @@ namespace osu.Game
if (scoreIds.Count == 0) if (scoreIds.Count == 0)
return; return;
ProgressNotification notification = new ProgressNotification { State = ProgressNotificationState.Active }; var notification = showProgressNotification(scoreIds.Count, "Upgrading scores to new scoring algorithm", "scores have been upgraded to the new scoring algorithm");
notificationOverlay?.Post(notification);
int processedCount = 0; int processedCount = 0;
int failedCount = 0; int failedCount = 0;
foreach (var id in scoreIds) foreach (var id in scoreIds)
{ {
if (notification.State == ProgressNotificationState.Cancelled) if (notification?.State == ProgressNotificationState.Cancelled)
break; break;
notification.Text = $"Upgrading scores to new scoring algorithm ({processedCount} of {scoreIds.Count})"; updateNotificationProgress(notification, processedCount, scoreIds.Count);
notification.Progress = (float)processedCount / scoreIds.Count;
sleepIfRequired(); sleepIfRequired();
@@ -310,7 +353,6 @@ namespace osu.Game
s.TotalScoreVersion = LegacyScoreEncoder.LATEST_VERSION; s.TotalScoreVersion = LegacyScoreEncoder.LATEST_VERSION;
}); });
Logger.Log($"Converted total score for score {id}");
++processedCount; ++processedCount;
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
@@ -325,24 +367,64 @@ namespace osu.Game
} }
} }
if (processedCount == scoreIds.Count) completeNotification(notification, processedCount, scoreIds.Count, failedCount);
}
private void updateNotificationProgress(ProgressNotification? notification, int processedCount, int totalCount)
{
if (notification == null)
return;
notification.Text = notification.Text.ToString().Split('(').First().TrimEnd() + $" ({processedCount} of {totalCount})";
notification.Progress = (float)processedCount / totalCount;
if (processedCount % 100 == 0)
Logger.Log(notification.Text.ToString());
}
private void completeNotification(ProgressNotification? notification, int processedCount, int totalCount, int? failedCount = null)
{
if (notification == null)
return;
if (processedCount == totalCount)
{ {
notification.CompletionText = $"{processedCount} score(s) have been upgraded to the new scoring algorithm"; notification.CompletionText = $"{processedCount} {notification.CompletionText}";
notification.Progress = 1; notification.Progress = 1;
notification.State = ProgressNotificationState.Completed; notification.State = ProgressNotificationState.Completed;
} }
else else
{ {
notification.Text = $"{processedCount} of {scoreIds.Count} score(s) have been upgraded to the new scoring algorithm."; notification.Text = $"{processedCount} of {totalCount} {notification.CompletionText}";
// We may have arrived here due to user cancellation or completion with failures. // We may have arrived here due to user cancellation or completion with failures.
if (failedCount > 0) if (failedCount > 0)
notification.Text += $" Check logs for issues with {failedCount} failed upgrades."; notification.Text += $" Check logs for issues with {failedCount} failed items.";
notification.State = ProgressNotificationState.Cancelled; notification.State = ProgressNotificationState.Cancelled;
} }
} }
private ProgressNotification? showProgressNotification(int totalCount, string running, string completed)
{
if (notificationOverlay == null)
return null;
if (totalCount < 10)
return null;
ProgressNotification notification = new ProgressNotification
{
Text = running,
CompletionText = completed,
State = ProgressNotificationState.Active
};
notificationOverlay?.Post(notification);
return notification;
}
private void sleepIfRequired() private void sleepIfRequired()
{ {
while (localUserPlayInfo?.IsPlaying.Value == true) while (localUserPlayInfo?.IsPlaying.Value == true)
+2
View File
@@ -77,6 +77,8 @@ namespace osu.Game.Beatmaps
beatmap.StarRating = calculator.Calculate().StarRating; beatmap.StarRating = calculator.Calculate().StarRating;
beatmap.Length = working.Beatmap.CalculatePlayableLength(); beatmap.Length = working.Beatmap.CalculatePlayableLength();
beatmap.BPM = 60000 / working.Beatmap.GetMostCommonBeatLength(); beatmap.BPM = 60000 / working.Beatmap.GetMostCommonBeatLength();
beatmap.EndTimeObjectCount = working.Beatmap.HitObjects.Count(h => h is IHasDuration);
beatmap.TotalObjectCount = working.Beatmap.HitObjects.Count;
} }
// And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required. // And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required.
+8 -5
View File
@@ -508,6 +508,11 @@ namespace osu.Game.Overlays.Mods
modSettingsArea.ResizeHeightTo(modAreaHeight, transition_duration, Easing.InOutCubic); modSettingsArea.ResizeHeightTo(modAreaHeight, transition_duration, Easing.InOutCubic);
TopLevelContent.MoveToY(-modAreaHeight, transition_duration, Easing.InOutCubic); TopLevelContent.MoveToY(-modAreaHeight, transition_duration, Easing.InOutCubic);
if (customisationVisible.Value)
GetContainingInputManager().ChangeFocus(modSettingsArea);
else
Scheduler.Add(() => GetContainingInputManager().ChangeFocus(null));
} }
/// <summary> /// <summary>
@@ -622,7 +627,7 @@ namespace osu.Game.Overlays.Mods
} }
if (textSearchStartsActive.Value) if (textSearchStartsActive.Value)
SearchTextBox.TakeFocus(); SearchTextBox.HoldFocus = true;
} }
protected override void PopOut() protected override void PopOut()
@@ -761,11 +766,9 @@ namespace osu.Game.Overlays.Mods
return false; return false;
// TODO: should probably eventually support typical platform search shortcuts (`Ctrl-F`, `/`) // TODO: should probably eventually support typical platform search shortcuts (`Ctrl-F`, `/`)
if (SearchTextBox.HasFocus) SearchTextBox.HoldFocus = !SearchTextBox.HoldFocus;
SearchTextBox.KillFocus(); if (SearchTextBox.HoldFocus)
else
SearchTextBox.TakeFocus(); SearchTextBox.TakeFocus();
return true; return true;
} }
@@ -32,6 +32,8 @@ namespace osu.Game.Overlays.Mods
[Resolved] [Resolved]
private OverlayColourProvider colourProvider { get; set; } = null!; private OverlayColourProvider colourProvider { get; set; } = null!;
public override bool AcceptsFocus => true;
public ModSettingsArea() public ModSettingsArea()
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
@@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Notifications
set set
{ {
text = value; text = value;
Schedule(() => textDrawable.Text = text); Scheduler.AddOnce(t => textDrawable.Text = t, text);
} }
} }
+2 -1
View File
@@ -6,6 +6,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Overlays.Settings;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
@@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Mods
public override ModType Type => ModType.DifficultyReduction; public override ModType Type => ModType.DifficultyReduction;
public override LocalisableString Description => "Whoaaaaa..."; public override LocalisableString Description => "Whoaaaaa...";
[SettingSource("Speed decrease", "The actual decrease to apply")] [SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(0.75) public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(0.75)
{ {
MinValue = 0.5, MinValue = 0.5,
+2 -1
View File
@@ -14,6 +14,7 @@ using osu.Game.Beatmaps.Timing;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Skinning; using osu.Game.Skinning;
@@ -28,7 +29,7 @@ namespace osu.Game.Rulesets.Mods
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override LocalisableString Description => "Uguuuuuuuu..."; public override LocalisableString Description => "Uguuuuuuuu...";
[SettingSource("Speed increase", "The actual increase to apply")] [SettingSource("Speed increase", "The actual increase to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(1.5) public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(1.5)
{ {
MinValue = 1.01, MinValue = 1.01,
+38 -32
View File
@@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select
/// <summary> /// <summary>
/// The total count of non-filtered beatmaps displayed. /// The total count of non-filtered beatmaps displayed.
/// </summary> /// </summary>
public int CountDisplayed => beatmapSets.Where(s => !s.Filtered.Value).Sum(s => s.Beatmaps.Count(b => !b.Filtered.Value)); public int CountDisplayed => beatmapSets.Where(s => !s.Filtered.Value).Sum(s => s.TotalItemsNotFiltered);
/// <summary> /// <summary>
/// The currently selected beatmap set. /// The currently selected beatmap set.
@@ -168,7 +168,10 @@ namespace osu.Game.Screens.Select
applyActiveCriteria(false); applyActiveCriteria(false);
if (loadedTestBeatmaps) if (loadedTestBeatmaps)
signalBeatmapsLoaded(); {
invalidateAfterChange();
BeatmapSetsLoaded = true;
}
// Restore selection // Restore selection
if (selectedBeatmapBefore != null && newRoot.BeatmapSetsByID.TryGetValue(selectedBeatmapBefore.BeatmapSet!.ID, out var newSelectionCandidates)) if (selectedBeatmapBefore != null && newRoot.BeatmapSetsByID.TryGetValue(selectedBeatmapBefore.BeatmapSet!.ID, out var newSelectionCandidates))
@@ -289,7 +292,7 @@ namespace osu.Game.Screens.Select
foreach (var id in realmSets) foreach (var id in realmSets)
{ {
if (!root.BeatmapSetsByID.ContainsKey(id)) if (!root.BeatmapSetsByID.ContainsKey(id))
UpdateBeatmapSet(realm.Realm.Find<BeatmapSetInfo>(id)!.Detach()); updateBeatmapSet(realm.Realm.Find<BeatmapSetInfo>(id)!.Detach());
} }
foreach (var id in root.BeatmapSetsByID.Keys) foreach (var id in root.BeatmapSetsByID.Keys)
@@ -298,15 +301,16 @@ namespace osu.Game.Screens.Select
removeBeatmapSet(id); removeBeatmapSet(id);
} }
signalBeatmapsLoaded(); invalidateAfterChange();
BeatmapSetsLoaded = true;
return; return;
} }
foreach (int i in changes.NewModifiedIndices) foreach (int i in changes.NewModifiedIndices)
UpdateBeatmapSet(sender[i].Detach()); updateBeatmapSet(sender[i].Detach());
foreach (int i in changes.InsertedIndices) foreach (int i in changes.InsertedIndices)
UpdateBeatmapSet(sender[i].Detach()); updateBeatmapSet(sender[i].Detach());
if (changes.DeletedIndices.Length > 0 && SelectedBeatmapInfo != null) if (changes.DeletedIndices.Length > 0 && SelectedBeatmapInfo != null)
{ {
@@ -347,6 +351,8 @@ namespace osu.Game.Screens.Select
SelectBeatmap(sender[modifiedAndInserted.First()].Beatmaps.First()); SelectBeatmap(sender[modifiedAndInserted.First()].Beatmaps.First());
} }
} }
invalidateAfterChange();
} }
private void beatmapsChanged(IRealmCollection<BeatmapInfo> sender, ChangeSet? changes) private void beatmapsChanged(IRealmCollection<BeatmapInfo> sender, ChangeSet? changes)
@@ -355,6 +361,8 @@ namespace osu.Game.Screens.Select
if (changes == null) if (changes == null)
return; return;
bool changed = false;
foreach (int i in changes.InsertedIndices) foreach (int i in changes.InsertedIndices)
{ {
var beatmapInfo = sender[i]; var beatmapInfo = sender[i];
@@ -367,17 +375,24 @@ namespace osu.Game.Screens.Select
if (root.BeatmapSetsByID.TryGetValue(beatmapSet.ID, out var existingSets) if (root.BeatmapSetsByID.TryGetValue(beatmapSet.ID, out var existingSets)
&& existingSets.SelectMany(s => s.Beatmaps).All(b => b.BeatmapInfo.ID != beatmapInfo.ID)) && existingSets.SelectMany(s => s.Beatmaps).All(b => b.BeatmapInfo.ID != beatmapInfo.ID))
{ {
UpdateBeatmapSet(beatmapSet.Detach()); updateBeatmapSet(beatmapSet.Detach());
changed = true;
} }
} }
if (changed)
invalidateAfterChange();
} }
private IQueryable<BeatmapSetInfo> getBeatmapSets(Realm realm) => realm.All<BeatmapSetInfo>().Where(s => !s.DeletePending && !s.Protected); private IQueryable<BeatmapSetInfo> getBeatmapSets(Realm realm) => realm.All<BeatmapSetInfo>().Where(s => !s.DeletePending && !s.Protected);
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
removeBeatmapSet(beatmapSet.ID); removeBeatmapSet(beatmapSet.ID);
invalidateAfterChange();
});
private void removeBeatmapSet(Guid beatmapSetID) => Schedule(() => private void removeBeatmapSet(Guid beatmapSetID)
{ {
if (!root.BeatmapSetsByID.TryGetValue(beatmapSetID, out var existingSets)) if (!root.BeatmapSetsByID.TryGetValue(beatmapSetID, out var existingSets))
return; return;
@@ -392,16 +407,15 @@ namespace osu.Game.Screens.Select
root.RemoveItem(set); root.RemoveItem(set);
} }
}
itemsCache.Invalidate();
if (!Scroll.UserScrolling)
ScrollToSelected(true);
BeatmapSetsChanged?.Invoke();
});
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
updateBeatmapSet(beatmapSet);
invalidateAfterChange();
});
private void updateBeatmapSet(BeatmapSetInfo beatmapSet)
{ {
Guid? previouslySelectedID = null; Guid? previouslySelectedID = null;
@@ -464,14 +478,7 @@ namespace osu.Game.Screens.Select
select((CarouselItem?)newSet.Beatmaps.FirstOrDefault(b => b.BeatmapInfo.ID == previouslySelectedID) ?? newSet); select((CarouselItem?)newSet.Beatmaps.FirstOrDefault(b => b.BeatmapInfo.ID == previouslySelectedID) ?? newSet);
} }
} }
}
itemsCache.Invalidate();
if (!Scroll.UserScrolling)
ScrollToSelected(true);
BeatmapSetsChanged?.Invoke();
});
/// <summary> /// <summary>
/// Selects a given beatmap on the carousel. /// Selects a given beatmap on the carousel.
@@ -748,15 +755,14 @@ namespace osu.Game.Screens.Select
} }
} }
private void signalBeatmapsLoaded() private void invalidateAfterChange()
{ {
if (!BeatmapSetsLoaded)
{
BeatmapSetsChanged?.Invoke();
BeatmapSetsLoaded = true;
}
itemsCache.Invalidate(); itemsCache.Invalidate();
if (!Scroll.UserScrolling)
ScrollToSelected(true);
BeatmapSetsChanged?.Invoke();
} }
private float? scrollTarget; private float? scrollTarget;
@@ -14,6 +14,8 @@ namespace osu.Game.Screens.Select.Carousel
public IReadOnlyList<CarouselItem> Items => items; public IReadOnlyList<CarouselItem> Items => items;
public int TotalItemsNotFiltered { get; private set; }
private readonly List<CarouselItem> items = new List<CarouselItem>(); private readonly List<CarouselItem> items = new List<CarouselItem>();
/// <summary> /// <summary>
@@ -31,6 +33,9 @@ namespace osu.Game.Screens.Select.Carousel
{ {
items.Remove(i); items.Remove(i);
if (!i.Filtered.Value)
TotalItemsNotFiltered--;
// it's important we do the deselection after removing, so any further actions based on // it's important we do the deselection after removing, so any further actions based on
// State.ValueChanged make decisions post-removal. // State.ValueChanged make decisions post-removal.
i.State.Value = CarouselItemState.Collapsed; i.State.Value = CarouselItemState.Collapsed;
@@ -55,6 +60,9 @@ namespace osu.Game.Screens.Select.Carousel
// criteria may be null for initial population. the filtering will be applied post-add. // criteria may be null for initial population. the filtering will be applied post-add.
items.Add(i); items.Add(i);
} }
if (!i.Filtered.Value)
TotalItemsNotFiltered++;
} }
public CarouselGroup(List<CarouselItem>? items = null) public CarouselGroup(List<CarouselItem>? items = null)
@@ -84,7 +92,14 @@ namespace osu.Game.Screens.Select.Carousel
{ {
base.Filter(criteria); base.Filter(criteria);
items.ForEach(c => c.Filter(criteria)); TotalItemsNotFiltered = 0;
foreach (var c in items)
{
c.Filter(criteria);
if (!c.Filtered.Value)
TotalItemsNotFiltered++;
}
// Sorting is expensive, so only perform if it's actually changed. // Sorting is expensive, so only perform if it's actually changed.
if (lastCriteria?.Sort != criteria.Sort) if (lastCriteria?.Sort != criteria.Sort)
+4 -3
View File
@@ -162,7 +162,7 @@ namespace osu.Game.Screens.Select
BleedBottom = Footer.HEIGHT, BleedBottom = Footer.HEIGHT,
SelectionChanged = updateSelectedBeatmap, SelectionChanged = updateSelectedBeatmap,
BeatmapSetsChanged = carouselBeatmapsLoaded, BeatmapSetsChanged = carouselBeatmapsLoaded,
FilterApplied = updateVisibleBeatmapCount, FilterApplied = () => Scheduler.AddOnce(updateVisibleBeatmapCount),
GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s),
}, c => carouselContainer.Child = c); }, c => carouselContainer.Child = c);
@@ -843,7 +843,7 @@ namespace osu.Game.Screens.Select
private void carouselBeatmapsLoaded() private void carouselBeatmapsLoaded()
{ {
bindBindables(); bindBindables();
updateVisibleBeatmapCount(); Scheduler.AddOnce(updateVisibleBeatmapCount);
Carousel.AllowSelection = true; Carousel.AllowSelection = true;
@@ -877,7 +877,8 @@ namespace osu.Game.Screens.Select
{ {
// Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918
// but also in this case we want support for formatting a number within a string). // but also in this case we want support for formatting a number within a string).
FilterControl.InformationalText = Carousel.CountDisplayed != 1 ? $"{Carousel.CountDisplayed:#,0} matches" : $"{Carousel.CountDisplayed:#,0} match"; int carouselCountDisplayed = Carousel.CountDisplayed;
FilterControl.InformationalText = carouselCountDisplayed != 1 ? $"{carouselCountDisplayed:#,0} matches" : $"{carouselCountDisplayed:#,0} match";
} }
private bool boundLocalBindables; private bool boundLocalBindables;