mirror of
https://github.com/ppy/osu.git
synced 2026-06-02 20:20:23 +08:00
fa4c72887f
Again, I don't know why the new implementation didn't just draw from the old which was known to work. This mostly matches what was there in v1.
171 lines
5.9 KiB
C#
171 lines
5.9 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;
|
|
using System.Threading;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Extensions.Color4Extensions;
|
|
using osu.Framework.Extensions.PolygonExtensions;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Colour;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Primitives;
|
|
using osu.Framework.Graphics.Shapes;
|
|
using osu.Framework.Graphics.Sprites;
|
|
using osu.Game.Beatmaps;
|
|
using osuTK;
|
|
using osuTK.Graphics;
|
|
|
|
namespace osu.Game.Screens.SelectV2
|
|
{
|
|
public partial class PanelSetBackground : BufferedContainer
|
|
{
|
|
[Resolved]
|
|
private BeatmapCarousel? beatmapCarousel { get; set; }
|
|
|
|
private Sprite? sprite;
|
|
|
|
private WorkingBeatmap? working;
|
|
|
|
private CancellationTokenSource? loadCancellation;
|
|
|
|
private double timeSinceUnpool;
|
|
|
|
public WorkingBeatmap? Beatmap
|
|
{
|
|
get => working;
|
|
set
|
|
{
|
|
if (value == working)
|
|
return;
|
|
|
|
working = value;
|
|
|
|
loadCancellation?.Cancel();
|
|
loadCancellation = null;
|
|
|
|
sprite?.Expire();
|
|
sprite = null;
|
|
|
|
timeSinceUnpool = 0;
|
|
}
|
|
}
|
|
|
|
public PanelSetBackground()
|
|
// TODO: for performance reasons we probably want this to be true
|
|
// for it to work we will need to move transforms accordingly.
|
|
: base(cachedFrameBuffer: false)
|
|
{
|
|
RelativeSizeAxes = Axes.Both;
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
loadContentIfRequired();
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
InternalChildren = new Drawable[]
|
|
{
|
|
new FillFlowContainer
|
|
{
|
|
Depth = -1,
|
|
RelativeSizeAxes = Axes.Both,
|
|
Direction = FillDirection.Horizontal,
|
|
// This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle
|
|
Shear = new Vector2(0.8f, 0),
|
|
Children = new[]
|
|
{
|
|
// The left half with no gradient applied
|
|
new Box
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Colour = Color4.Black.Opacity(0.5f),
|
|
Width = 0.4f,
|
|
},
|
|
new Box
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Colour = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0.3f)),
|
|
Width = 0.2f,
|
|
},
|
|
new Box
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Colour = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.3f), Color4.Black.Opacity(0.2f)),
|
|
// Slightly more than 1.0 in total to account for shear.
|
|
Width = 0.45f,
|
|
},
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
private void loadContentIfRequired()
|
|
{
|
|
// A load is already in progress if the cancellation token is non-null.
|
|
if (loadCancellation != null || working == null)
|
|
return;
|
|
|
|
if (beatmapCarousel != null)
|
|
{
|
|
Quad containingSsdq = beatmapCarousel.ScreenSpaceDrawQuad;
|
|
|
|
// Using DelayedLoadWrappers would only allow us to load content when on screen, but we want to preload while off-screen
|
|
// to provide a better user experience.
|
|
|
|
// This is tracking time that this drawable is updating since the last pool.
|
|
// This is intended to provide a debounce so very fast scrolls (from one end to the other of the carousel)
|
|
// don't cause huge overheads.
|
|
//
|
|
// We increase the delay based on distance from centre, so the beatmaps the user is currently looking at load first.
|
|
float timeUpdatingBeforeLoad = 50 + Math.Abs(containingSsdq.Centre.Y - ScreenSpaceDrawQuad.Centre.Y) / containingSsdq.Height * 100;
|
|
|
|
timeSinceUnpool += Time.Elapsed;
|
|
|
|
// We only trigger a load after this set has been in an updating state for a set amount of time.
|
|
if (timeSinceUnpool <= timeUpdatingBeforeLoad)
|
|
return;
|
|
}
|
|
|
|
loadCancellation = new CancellationTokenSource();
|
|
|
|
LoadComponentAsync(new PanelBeatmapBackground(working)
|
|
{
|
|
Depth = float.MaxValue,
|
|
RelativeSizeAxes = Axes.Both,
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
FillMode = FillMode.Fill,
|
|
}, s =>
|
|
{
|
|
AddInternal(sprite = s);
|
|
bool spriteOnScreen = beatmapCarousel?.ScreenSpaceDrawQuad.Intersects(sprite.ScreenSpaceDrawQuad) != false;
|
|
sprite.FadeInFromZero(spriteOnScreen ? 400 : 0, Easing.OutQuint);
|
|
}, loadCancellation.Token);
|
|
}
|
|
|
|
public partial class PanelBeatmapBackground : Sprite
|
|
{
|
|
private readonly IWorkingBeatmap working;
|
|
|
|
public PanelBeatmapBackground(IWorkingBeatmap working)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(working);
|
|
|
|
this.working = working;
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
Texture = working.GetPanelBackground();
|
|
}
|
|
}
|
|
}
|
|
}
|