mirror of
https://github.com/ppy/osu.git
synced 2026-05-30 12:50:24 +08:00
95648a3d27
TL;DR the clock was being set too late, causing more transforms to be created than necessary. This solves the issue by way of a refactor (sorry). Overall this should simplify handling of things as more of the logic is shared with the known good-state `BeatmapBackgroundWithStoryboard`. I did try without a refactor (just delaying the creation until the clock arrives) but this version made more sense because background generally expect to do their main load in BDL to aid in smooth transitions. And we can't get the clock by there. (although arguably we could just use a similar method to `BeatmapBackgroundWithStoryboard` and forego using the editor clock). Of note, I removed the black background overdraw hack. There are edge cases where it will lead to weird transitions, but these are far and few between. Basically you need a storyboard which sets the flag to hide the beatmap background and has transparency in it. This is no longer as flagrantly bad as things used to be (which led to the inline fix) as far as I can tell, but feel free to prove me wrong. If this is a blocker I'll probably just add a permanent black box (which does fix this). Closes #36875.
125 lines
4.5 KiB
C#
125 lines
4.5 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.
|
|
|
|
using System.Threading;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Bindables;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Shapes;
|
|
using osu.Framework.Screens;
|
|
using osu.Game.Beatmaps;
|
|
using osu.Game.Configuration;
|
|
using osu.Game.Graphics;
|
|
using osu.Game.Graphics.Backgrounds;
|
|
using osu.Game.Screens.Edit;
|
|
using osuTK.Graphics;
|
|
|
|
namespace osu.Game.Screens.Backgrounds
|
|
{
|
|
public partial class EditorBackgroundScreen : BackgroundScreen
|
|
{
|
|
private readonly Container dimContainer;
|
|
|
|
private CancellationTokenSource? cancellationTokenSource;
|
|
private Bindable<float> dimLevel = null!;
|
|
private Bindable<bool> showStoryboard = null!;
|
|
|
|
private BeatmapBackgroundWithStoryboard? background;
|
|
|
|
private readonly Container content;
|
|
private readonly Box blackBox;
|
|
|
|
// We retrieve IBindable<WorkingBeatmap> from our dependency cache instead of passing WorkingBeatmap directly into EditorBackgroundScreen.
|
|
// Otherwise, DummyWorkingBeatmap will be erroneously passed in whenever creating a new beatmap (since the Schedule() in the Editor that populates
|
|
// a new WorkingBeatmap with correct values generally runs after EditorBackgroundScreen is created), which causes any background changes to not be displayed.
|
|
[Resolved]
|
|
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
|
|
|
|
public EditorBackgroundScreen(EditorBeatmap editorBeatmap)
|
|
{
|
|
InternalChild = dimContainer = new Container
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Children = new Drawable[]
|
|
{
|
|
// This adds overdraw but makes transitions not suck.
|
|
// There's probably a better way to do this, but it's high effort.
|
|
blackBox = new Box
|
|
{
|
|
Colour = Color4.Black,
|
|
RelativeSizeAxes = Axes.Both,
|
|
},
|
|
content = new EditorSkinProvidingContainer(editorBeatmap)
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load(OsuConfigManager config)
|
|
{
|
|
dimLevel = config.GetBindable<float>(OsuSetting.EditorDim);
|
|
showStoryboard = config.GetBindable<bool>(OsuSetting.EditorShowStoryboard);
|
|
|
|
content.Child = createContent();
|
|
updateState(withAnimation: false);
|
|
}
|
|
|
|
protected override void LoadComplete()
|
|
{
|
|
base.LoadComplete();
|
|
|
|
dimLevel.BindValueChanged(_ => dimContainer.FadeColour(OsuColour.Gray(1 - dimLevel.Value), 500, Easing.OutQuint), true);
|
|
showStoryboard.BindValueChanged(_ => updateState());
|
|
|
|
updateState(withAnimation: false);
|
|
}
|
|
|
|
public override void OnEntering(ScreenTransitionEvent e)
|
|
{
|
|
base.OnEntering(e);
|
|
blackBox.LifetimeEnd = LatestTransformEndTime;
|
|
}
|
|
|
|
public override bool OnExiting(ScreenExitEvent e)
|
|
{
|
|
// The storyboard will do weird things with clock time changing on exit, so let's just hide it instead.
|
|
background?.UnloadStoryboard();
|
|
|
|
return base.OnExiting(e);
|
|
}
|
|
|
|
public void RefreshBackgroundAsync()
|
|
{
|
|
cancellationTokenSource?.Cancel();
|
|
LoadComponentAsync(createContent(), loaded =>
|
|
{
|
|
content.Child = loaded;
|
|
updateState(withAnimation: false);
|
|
}, (cancellationTokenSource = new CancellationTokenSource()).Token);
|
|
}
|
|
|
|
private Drawable createContent() => background = new BeatmapBackgroundWithStoryboard(beatmap.Value)
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
StoryboardLoaded = () => updateState(withAnimation: false)
|
|
};
|
|
|
|
private void updateState(bool withAnimation = true)
|
|
{
|
|
background?.Storyboard.FadeTo(showStoryboard.Value ? 1 : 0, withAnimation ? 500 : 0, Easing.OutQuint);
|
|
}
|
|
|
|
public override bool Equals(BackgroundScreen? other)
|
|
{
|
|
if (other is not EditorBackgroundScreen otherBeatmapBackground)
|
|
return false;
|
|
|
|
return base.Equals(other) && beatmap == otherBeatmapBackground.beatmap;
|
|
}
|
|
}
|
|
}
|