diff --git a/PerformanceCalculatorGUI/Screens/SimulateScreen.cs b/PerformanceCalculatorGUI/Screens/SimulateScreen.cs index 6dbe06f863..d18e355deb 100644 --- a/PerformanceCalculatorGUI/Screens/SimulateScreen.cs +++ b/PerformanceCalculatorGUI/Screens/SimulateScreen.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; @@ -119,6 +120,8 @@ public partial class SimulateScreen : PerformanceCalculatorScreen [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + private CancellationTokenSource cancellationTokenSource; + public override bool ShouldShowConfirmationDialogOnSwitch => working != null; private const int file_selection_container_height = 40; @@ -531,14 +534,14 @@ private void load(OsuColour osuColour) { HotReloadCallbackReceiver.CompilationFinished += _ => Schedule(() => { - calculateDifficulty(); - calculatePerformance(); + calculateDifficultyAsync().ContinueWith(_ => calculatePerformance()); }); } } protected override void Dispose(bool isDisposing) { + cancellationTokenSource?.Cancel(); modSettingChangeTracker?.Dispose(); appliedMods.UnbindAll(); @@ -577,20 +580,22 @@ private void modsChanged(ValueChangedEvent> mods) { createCalculators(); updateMissesTextboxes(); - calculateDifficulty(); - calculatePerformance(); + calculateDifficultyAsync().ContinueWith(_ => calculatePerformance()); }, 300); }; - calculateDifficulty(); - updateCombo(false); - calculatePerformance(); + calculateDifficultyAsync().ContinueWith(_ => + { + updateCombo(false); + calculatePerformance(); + }); } private void resetBeatmap() { working = null; beatmapTitle.Clear(); + cancellationTokenSource?.Cancel(); resetMods(); beatmapDataContainer.Hide(); @@ -652,33 +657,40 @@ private void createCalculators() performanceCalculator = rulesetInstance.CreatePerformanceCalculator(); } - private void calculateDifficulty() + private Task calculateDifficultyAsync() { if (working == null || difficultyCalculator.Value == null) - return; + return Task.CompletedTask; - try - { - difficultyAttributes = difficultyCalculator.Value.Calculate(appliedMods.Value); - difficultyAttributesContainer.Attributes.Value = AttributeConversion.ToDictionary(difficultyAttributes); - } - catch (Exception e) - { - showError(e); - resetBeatmap(); - return; - } + cancellationTokenSource?.Cancel(); + cancellationTokenSource = new CancellationTokenSource(); - if (difficultyCalculator.Value is IExtendedDifficultyCalculator extendedDifficultyCalculator) + return Task.Run(() => { - // StrainSkill always skips the first object - if (working.Beatmap?.HitObjects.Count > 1) - strainVisualizer.TimeUntilFirstStrain.Value = (int)working.Beatmap.HitObjects[1].StartTime; + difficultyAttributes = difficultyCalculator.Value.Calculate(appliedMods.Value, cancellationTokenSource.Token); - strainVisualizer.Skills.Value = extendedDifficultyCalculator.GetSkills(); - } - else - strainVisualizer.Skills.Value = Array.Empty(); + if (cancellationTokenSource.IsCancellationRequested) + return; + + Schedule(() => + { + difficultyAttributesContainer.Attributes.Value = AttributeConversion.ToDictionary(difficultyAttributes); + + if (difficultyCalculator.Value is IExtendedDifficultyCalculator extendedDifficultyCalculator) + { + // StrainSkill always skips the first object + if (working.Beatmap?.HitObjects.Count > 1) + strainVisualizer.TimeUntilFirstStrain.Value = (int)working.Beatmap.HitObjects[1].StartTime; + + strainVisualizer.Skills.Value = extendedDifficultyCalculator.GetSkills(); + } + else + strainVisualizer.Skills.Value = Array.Empty(); + }); + }).ContinueWith(t => + { + Schedule(() => showError(t.Exception)); + }, TaskContinuationOptions.OnlyOnFaulted); } private void debouncedCalculatePerformance() @@ -689,7 +701,7 @@ private void debouncedCalculatePerformance() private void calculatePerformance() { - if (working == null || difficultyAttributes == null) + if (working == null || difficultyAttributes == null || cancellationTokenSource.IsCancellationRequested) return; int? countGood = null, countMeh = null; @@ -737,12 +749,11 @@ private void calculatePerformance() LegacyTotalScore = legacyTotalScore, }, difficultyAttributes); - performanceAttributesContainer.Attributes.Value = AttributeConversion.ToDictionary(ppAttributes); + Schedule(() => performanceAttributesContainer.Attributes.Value = AttributeConversion.ToDictionary(ppAttributes)); } catch (Exception e) { - showError(e); - resetBeatmap(); + Schedule(() => showError(e)); } } @@ -897,11 +908,10 @@ private void resetCalculations() createCalculators(); resetMods(); + populateScoreParams(); legacyTotalScore = null; - calculateDifficulty(); - calculatePerformance(); - populateScoreParams(); + calculateDifficultyAsync().ContinueWith(_ => calculatePerformance()); } // This is to make sure combo resets when classic mod is applied @@ -1070,10 +1080,7 @@ private void populateSettingsFromScore(long scoreId) sliderTailMissesTextBox.Text = sliderTailMisses.ToString(); } - calculateDifficulty(); - calculatePerformance(); - - scoreIdPopulateButton.State.Value = ButtonState.Done; + calculateDifficultyAsync().ContinueWith(_ => calculatePerformance()); }); }).ContinueWith(t => {