1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-26 03:49:56 +08:00
Files
osu-lazer/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs
T
Dean Herbert 34119aab8e Adjust song select beatmap background transition to better support transparent backgrounds
The new background now briefly fades in. The reason we didn't do this to
date is that there could be a perceived decrease in brightness as the old
and new background transition through opacity.

But a quick fade in, it doesn't seem to cause any visual artifacting.

I've also added a scale effect because it felt quite nice. Willing to
pull that if anyone has an issue with it, but it's a step in the
direction of "adding more motion to song select", which is still an area
I see lacking greatly – even compared to stable.
2025-05-07 14:59:29 +09:00

209 lines
7.2 KiB
C#

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;
using osu.Game.Screens.Play;
using osuTK;
namespace osu.Game.Screens.Backgrounds
{
public partial class BackgroundScreenBeatmap : BackgroundScreen
{
/// <summary>
/// The amount of blur to apply when full user blur is requested.
/// </summary>
public const float USER_BLUR_FACTOR = 25;
protected Background Background;
private WorkingBeatmap beatmap;
/// <summary>
/// Whether or not user-configured settings relating to brightness of elements should be ignored.
/// </summary>
/// <remarks>
/// Beatmap background screens should not apply user settings by default.
/// </remarks>
public readonly Bindable<bool> IgnoreUserSettings = new Bindable<bool>(true);
/// <summary>
/// Whether or not the storyboard loaded should completely hide the background behind it.
/// </summary>
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
/// <summary>
/// The amount of blur to be applied in addition to user-specified blur.
/// </summary>
public readonly Bindable<float> BlurAmount = new BindableFloat();
/// <summary>
/// The amount of dim to be used when <see cref="IgnoreUserSettings"/> is <c>true</c>.
/// </summary>
public readonly Bindable<float> DimWhenUserSettingsIgnored = new Bindable<float>();
internal readonly Bindable<bool> IsBreakTime = new Bindable<bool>();
private readonly DimmableBackground dimmable;
protected virtual DimmableBackground CreateFadeContainer() => new DimmableBackground { RelativeSizeAxes = Axes.Both };
public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null)
{
Beatmap = beatmap;
InternalChild = dimmable = CreateFadeContainer();
dimmable.StoryboardReplacesBackground.BindTo(StoryboardReplacesBackground);
dimmable.IgnoreUserSettings.BindTo(IgnoreUserSettings);
dimmable.IsBreakTime.BindTo(IsBreakTime);
dimmable.BlurAmount.BindTo(BlurAmount);
dimmable.DimWhenUserSettingsIgnored.BindTo(DimWhenUserSettingsIgnored);
}
[BackgroundDependencyLoader]
private void load()
{
var background = new BeatmapBackground(beatmap);
LoadComponent(background);
switchBackground(background);
}
private CancellationTokenSource cancellationSource;
public WorkingBeatmap Beatmap
{
get => beatmap;
set
{
if (beatmap == value && beatmap != null)
return;
beatmap = value;
Schedule(() =>
{
if ((Background as BeatmapBackground)?.Beatmap.BeatmapInfo.BackgroundEquals(beatmap?.BeatmapInfo) ?? false)
return;
cancellationSource?.Cancel();
LoadComponentAsync(new BeatmapBackground(beatmap), switchBackground, (cancellationSource = new CancellationTokenSource()).Token);
});
}
}
private void switchBackground(BeatmapBackground b)
{
float newDepth = 0;
if (Background != null)
{
newDepth = Background.Depth + 1;
Background.FadeOut(250);
Background.Expire();
}
b.Depth = newDepth;
b.Anchor = b.Origin = Anchor.Centre;
b.FadeInFromZero(500, Easing.OutQuint);
b.ScaleTo(1.02f).ScaleTo(1, 3500, Easing.OutQuint);
dimmable.Background = Background = b;
}
public override bool Equals(BackgroundScreen other)
{
if (!(other is BackgroundScreenBeatmap otherBeatmapBackground)) return false;
return base.Equals(other) && beatmap == otherBeatmapBackground.Beatmap;
}
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>
public readonly Bindable<float> BlurAmount = new BindableFloat();
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
public Background Background
{
get => background;
set
{
background?.Expire();
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)
{
ArgumentNullException.ThrowIfNull(drawable);
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>
private Vector2 blurTarget => !IgnoreUserSettings.Value
? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * USER_BLUR_FACTOR)
: new Vector2(BlurAmount.Value);
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
userBlurLevel = config.GetBindable<double>(OsuSetting.BlurLevel);
}
protected override void LoadComplete()
{
base.LoadComplete();
userBlurLevel.ValueChanged += _ => UpdateVisuals();
BlurAmount.ValueChanged += _ => UpdateVisuals();
StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals();
}
protected override float DimLevel
{
get
{
if ((IgnoreUserSettings.Value || ShowStoryboard.Value) && StoryboardReplacesBackground.Value)
return 1;
return base.DimLevel;
}
}
protected override void UpdateVisuals()
{
base.UpdateVisuals();
Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint);
}
}
}
}