// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; using osuTK; using osuTK.Graphics; namespace osu.Game.Graphics.Containers { /// /// A container that applies user-configured visual settings to its contents. /// This container specifies behavior that applies to both Storyboards and Backgrounds. /// public class UserDimContainer : Container { private const float background_fade_duration = 800; /// /// Whether or not user-configured dim levels should be applied to the container. /// public readonly Bindable EnableUserDim = new Bindable(); /// /// Whether or not the storyboard loaded should completely hide the background behind it. /// public readonly Bindable StoryboardReplacesBackground = new Bindable(); /// /// The amount of blur to be applied to the background in addition to user-specified blur. /// /// /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in /// public readonly Bindable BlurAmount = new Bindable(); private Bindable userDimLevel { get; set; } private Bindable userBlurLevel { get; set; } private Bindable showStoryboard { get; set; } protected Container DimContainer { get; } protected override Container Content => DimContainer; private readonly bool isStoryboard; private Vector2 blurTarget => EnableUserDim.Value ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) : new Vector2(BlurAmount.Value); private Background background; /// /// Creates a new . /// /// Whether or not this instance contains a storyboard. /// /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. /// /// public UserDimContainer(bool isStoryboard = false) { this.isStoryboard = isStoryboard; AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both }); } public override void Add(Drawable drawable) { // Make sure we're already at the correct blur target when a background is added to the container. if (drawable is Background b) { background = b; background.BlurTo(blurTarget, 0, Easing.OutQuint); } base.Add(drawable); } [BackgroundDependencyLoader] private void load(OsuConfigManager config) { userDimLevel = config.GetBindable(OsuSetting.DimLevel); userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); EnableUserDim.ValueChanged += _ => updateVisuals(); userDimLevel.ValueChanged += _ => updateVisuals(); userBlurLevel.ValueChanged += _ => updateVisuals(); showStoryboard.ValueChanged += _ => updateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => updateVisuals(); BlurAmount.ValueChanged += _ => updateVisuals(); } protected override void LoadComplete() { base.LoadComplete(); updateVisuals(); } private void updateVisuals() { if (isStoryboard) { DimContainer.FadeTo(!showStoryboard.Value || userDimLevel.Value == 1 ? 0 : 1, background_fade_duration, Easing.OutQuint); } else { // The background needs to be hidden in the case of it being replaced by the storyboard DimContainer.FadeTo(showStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, background_fade_duration, Easing.OutQuint); // This only works if the background is a direct child of DimContainer. // We can't blur the container like we did with the dim because buffered containers add considerable draw overhead. // As a result, this blurs the background directly via the direct children of DimContainer. background?.BlurTo(blurTarget, background_fade_duration, Easing.OutQuint); } DimContainer.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)userDimLevel.Value) : Color4.White, background_fade_duration, Easing.OutQuint); } } }