// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; namespace osu.Game.Beatmaps.Drawables { /// /// A component solely responsible for calculating difficulty in the background. /// Intended for use with to only run processing when usage is on-screen. /// public class DifficultyRetriever : Component { /// /// The bindable star difficulty. /// public IBindable StarDifficulty => starDifficulty; private readonly Bindable starDifficulty = new Bindable(); private readonly IBeatmapInfo beatmapInfo; private readonly IRulesetInfo? ruleset; private readonly IReadOnlyList? mods; private readonly CancellationTokenSource difficultyCancellation = new CancellationTokenSource(); [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } = null!; /// /// Construct a difficulty retriever that tracks the current ruleset / mod selection. /// /// The beatmap to use for calculation. public DifficultyRetriever(IBeatmapInfo beatmapInfo) { this.beatmapInfo = beatmapInfo; } /// /// Construct a difficulty retriever that is calculated only once for the specified ruleset / mod combination. /// This will not track global ruleset and mod changes. /// /// The beatmap to use for calculation. /// The ruleset to use for calculation. /// The mods to use for calculation. public DifficultyRetriever(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, IReadOnlyList mods) { this.beatmapInfo = beatmapInfo; this.ruleset = ruleset; this.mods = mods; } private IBindable localStarDifficulty = null!; [BackgroundDependencyLoader] private void load() { localStarDifficulty = ruleset != null ? difficultyCache.GetBindableDifficulty(beatmapInfo, ruleset, mods, difficultyCancellation.Token) : difficultyCache.GetBindableDifficulty(beatmapInfo, difficultyCancellation.Token); localStarDifficulty.BindValueChanged(d => { if (d.NewValue is StarDifficulty diff) starDifficulty.Value = diff; }); } protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); difficultyCancellation.Cancel(); } } }