2019-07-15 10:48:33 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2019-01-24 16:43:03 +08:00
// See the LICENCE file in the repository root for full licence text.
2018-04-13 17:19:50 +08:00
2022-06-17 15:37:17 +08:00
#nullable disable
2019-07-12 10:50:06 +08:00
using System ;
2019-03-12 16:32:40 +08:00
using System.Threading ;
2016-11-22 20:22:12 +08:00
using osu.Framework.Allocation ;
2019-02-22 19:44:02 +08:00
using osu.Framework.Bindables ;
2017-03-28 20:26:20 +08:00
using osu.Framework.Graphics ;
2016-11-20 00:39:43 +08:00
using osu.Game.Beatmaps ;
2019-07-12 10:50:06 +08:00
using osu.Game.Configuration ;
2016-11-23 10:59:50 +08:00
using osu.Game.Graphics.Backgrounds ;
2019-02-20 15:53:57 +08:00
using osu.Game.Graphics.Containers ;
2019-07-12 10:50:06 +08:00
using osu.Game.Screens.Play ;
using osuTK ;
2018-04-13 17:19:50 +08:00
2016-11-20 00:39:43 +08:00
namespace osu.Game.Screens.Backgrounds
{
2019-03-14 15:09:17 +08:00
public partial class BackgroundScreenBeatmap : BackgroundScreen
2016-11-20 00:39:43 +08:00
{
2019-07-12 12:44:43 +08:00
/// <summary>
/// The amount of blur to apply when full user blur is requested.
/// </summary>
public const float USER_BLUR_FACTOR = 25 ;
2019-03-20 13:17:35 +08:00
protected Background Background ;
2019-02-15 15:57:53 +08:00
private WorkingBeatmap beatmap ;
2019-02-24 19:03:24 +08:00
/// <summary>
2021-04-15 13:04:03 +08:00
/// Whether or not user-configured settings relating to brightness of elements should be ignored.
2019-02-24 19:03:24 +08:00
/// </summary>
2021-04-15 13:04:03 +08:00
/// <remarks>
/// Beatmap background screens should not apply user settings by default.
/// </remarks>
public readonly Bindable < bool > IgnoreUserSettings = new Bindable < bool > ( true ) ;
2019-02-24 19:03:24 +08:00
2023-08-02 14:07:06 +08:00
/// <summary>
/// Whether or not the storyboard loaded should completely hide the background behind it.
/// </summary>
2019-02-28 17:25:58 +08:00
public readonly Bindable < bool > StoryboardReplacesBackground = new Bindable < bool > ( ) ;
2019-02-15 15:17:01 +08:00
2019-03-20 13:17:35 +08:00
/// <summary>
/// The amount of blur to be applied in addition to user-specified blur.
/// </summary>
2020-02-02 05:50:29 +08:00
public readonly Bindable < float > BlurAmount = new BindableFloat ( ) ;
2019-03-14 13:02:46 +08:00
2022-11-02 14:11:49 +08:00
/// <summary>
2022-11-02 16:49:52 +08:00
/// The amount of dim to be used when <see cref="IgnoreUserSettings"/> is <c>true</c>.
2022-11-02 14:11:49 +08:00
/// </summary>
2022-11-02 16:49:52 +08:00
public readonly Bindable < float > DimWhenUserSettingsIgnored = new Bindable < float > ( ) ;
2022-10-25 12:00:53 +08:00
2019-12-10 20:13:44 +08:00
internal readonly IBindable < bool > IsBreakTime = new Bindable < bool > ( ) ;
2019-07-12 10:50:06 +08:00
private readonly DimmableBackground dimmable ;
2019-02-24 19:03:24 +08:00
2019-07-12 10:50:06 +08:00
protected virtual DimmableBackground CreateFadeContainer ( ) = > new DimmableBackground { RelativeSizeAxes = Axes . Both } ;
2019-02-15 15:17:01 +08:00
2019-03-12 11:56:01 +08:00
public BackgroundScreenBeatmap ( WorkingBeatmap beatmap = null )
{
Beatmap = beatmap ;
2019-07-12 10:50:06 +08:00
InternalChild = dimmable = CreateFadeContainer ( ) ;
2020-01-09 12:43:57 +08:00
2023-08-02 14:07:06 +08:00
dimmable . StoryboardReplacesBackground . BindTo ( StoryboardReplacesBackground ) ;
2021-04-15 13:02:12 +08:00
dimmable . IgnoreUserSettings . BindTo ( IgnoreUserSettings ) ;
2019-12-10 20:13:44 +08:00
dimmable . IsBreakTime . BindTo ( IsBreakTime ) ;
2019-07-12 10:50:06 +08:00
dimmable . BlurAmount . BindTo ( BlurAmount ) ;
2022-11-02 16:49:52 +08:00
dimmable . DimWhenUserSettingsIgnored . BindTo ( DimWhenUserSettingsIgnored ) ;
2019-03-12 11:56:01 +08:00
}
[BackgroundDependencyLoader]
private void load ( )
{
2019-03-12 16:32:40 +08:00
var background = new BeatmapBackground ( beatmap ) ;
LoadComponent ( background ) ;
switchBackground ( background ) ;
2019-03-12 11:56:01 +08:00
}
2019-03-12 16:32:40 +08:00
private CancellationTokenSource cancellationSource ;
2019-03-12 13:01:27 +08:00
public WorkingBeatmap Beatmap
2016-11-20 00:39:43 +08:00
{
2019-02-28 12:58:19 +08:00
get = > beatmap ;
2016-11-20 00:39:43 +08:00
set
{
2017-01-30 22:44:02 +08:00
if ( beatmap = = value & & beatmap ! = null )
2016-11-20 00:39:43 +08:00
return ;
2018-04-13 17:19:50 +08:00
2016-11-20 00:39:43 +08:00
beatmap = value ;
2018-04-13 17:19:50 +08:00
2016-11-22 20:22:12 +08:00
Schedule ( ( ) = >
{
2019-11-25 17:28:43 +08:00
if ( ( Background as BeatmapBackground ) ? . Beatmap . BeatmapInfo . BackgroundEquals ( beatmap ? . BeatmapInfo ) ? ? false )
2019-03-12 16:32:40 +08:00
return ;
2019-03-12 11:55:54 +08:00
2019-03-12 16:32:40 +08:00
cancellationSource ? . Cancel ( ) ;
LoadComponentAsync ( new BeatmapBackground ( beatmap ) , switchBackground , ( cancellationSource = new CancellationTokenSource ( ) ) . Token ) ;
2016-11-22 20:22:12 +08:00
} ) ;
2016-11-20 00:39:43 +08:00
}
}
2018-04-13 17:19:50 +08:00
2023-01-07 00:26:30 +08:00
/// <summary>
/// Reloads beatmap's background.
/// </summary>
public void RefreshBackground ( )
{
Schedule ( ( ) = >
{
cancellationSource ? . Cancel ( ) ;
LoadComponentAsync ( new BeatmapBackground ( beatmap ) , switchBackground , ( cancellationSource = new CancellationTokenSource ( ) ) . Token ) ;
} ) ;
}
2019-03-12 16:32:40 +08:00
private void switchBackground ( BeatmapBackground b )
2016-11-20 00:39:43 +08:00
{
2019-03-11 23:05:05 +08:00
float newDepth = 0 ;
2019-04-01 11:16:05 +08:00
2019-03-11 23:05:05 +08:00
if ( Background ! = null )
{
newDepth = Background . Depth + 1 ;
Background . FinishTransforms ( ) ;
Background . FadeOut ( 250 ) ;
Background . Expire ( ) ;
}
b . Depth = newDepth ;
2019-07-12 10:50:06 +08:00
dimmable . Background = Background = b ;
2019-02-15 15:17:01 +08:00
}
2017-02-17 17:59:30 +08:00
public override bool Equals ( BackgroundScreen other )
2016-11-20 00:39:43 +08:00
{
2019-03-12 16:32:40 +08:00
if ( ! ( other is BackgroundScreenBeatmap otherBeatmapBackground ) ) return false ;
2018-04-13 17:19:50 +08:00
2017-03-07 09:59:19 +08:00
return base . Equals ( other ) & & beatmap = = otherBeatmapBackground . Beatmap ;
2016-11-20 00:39:43 +08:00
}
2018-04-13 17:19:50 +08:00
2019-07-12 10:50:06 +08:00
public partial class DimmableBackground : UserDimContainer
{
/// <summary>
/// The amount of blur to be applied to the background in addition to user-specified blur.
/// </summary>
/// <remarks>
/// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in <see cref="PlayerLoader"/>
/// </remarks>
2020-02-02 05:50:29 +08:00
public readonly Bindable < float > BlurAmount = new BindableFloat ( ) ;
2019-07-12 10:50:06 +08:00
2023-08-02 14:07:06 +08:00
public readonly Bindable < bool > StoryboardReplacesBackground = new Bindable < bool > ( ) ;
2019-07-12 10:50:06 +08:00
public Background Background
{
get = > background ;
set
{
2019-07-12 12:45:34 +08:00
background ? . Expire ( ) ;
2019-07-12 10:50:06 +08:00
base . Add ( background = value ) ;
background . BlurTo ( blurTarget , 0 , Easing . OutQuint ) ;
}
}
private Bindable < double > userBlurLevel { get ; set ; }
private Background background ;
public override void Add ( Drawable drawable )
{
2023-10-30 14:10:10 +08:00
ArgumentNullException . ThrowIfNull ( drawable ) ;
2019-07-12 10:50:06 +08:00
if ( drawable is Background )
throw new InvalidOperationException ( $"Use {nameof(Background)} to set a background." ) ;
base . Add ( drawable ) ;
}
/// <summary>
/// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs.
/// </summary>
2021-04-15 13:02:12 +08:00
private Vector2 blurTarget = > ! IgnoreUserSettings . Value
2019-07-12 12:44:43 +08:00
? new Vector2 ( BlurAmount . Value + ( float ) userBlurLevel . Value * USER_BLUR_FACTOR )
2019-07-12 10:50:06 +08:00
: new Vector2 ( BlurAmount . Value ) ;
[BackgroundDependencyLoader]
private void load ( OsuConfigManager config )
{
userBlurLevel = config . GetBindable < double > ( OsuSetting . BlurLevel ) ;
2019-07-15 10:48:33 +08:00
}
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
2019-07-12 10:50:06 +08:00
userBlurLevel . ValueChanged + = _ = > UpdateVisuals ( ) ;
BlurAmount . ValueChanged + = _ = > UpdateVisuals ( ) ;
2023-08-02 14:07:06 +08:00
StoryboardReplacesBackground . ValueChanged + = _ = > UpdateVisuals ( ) ;
2019-07-12 10:50:06 +08:00
}
2023-08-02 14:50:15 +08:00
protected override float DimLevel
{
get
{
if ( ( IgnoreUserSettings . Value | | ShowStoryboard . Value ) & & StoryboardReplacesBackground . Value )
return 1 ;
return base . DimLevel ;
}
}
2019-07-12 10:50:06 +08:00
protected override void UpdateVisuals ( )
{
base . UpdateVisuals ( ) ;
Background ? . BlurTo ( blurTarget , BACKGROUND_FADE_DURATION , Easing . OutQuint ) ;
}
}
2016-11-20 00:39:43 +08:00
}
}