1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 09:07:52 +08:00

Implement spinner glow

This commit is contained in:
Andrei Zavatski 2023-11-24 06:09:41 +03:00
parent 9541d3d452
commit c7f1fd23e7

View File

@ -2,10 +2,17 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Runtime.InteropServices;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Shaders.Types;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Utils;
using osu.Game.Rulesets.Objects.Drawables;
@ -19,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon
private const float arc_fill = 0.15f;
private const float arc_radius = 0.12f;
private CircularProgress fill = null!;
private ProgressFill fill = null!;
private DrawableSpinner spinner = null!;
@ -45,13 +52,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon
InnerRadius = arc_radius,
RoundedCaps = true,
},
fill = new CircularProgress
fill = new ProgressFill
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
InnerRadius = arc_radius,
RoundedCaps = true,
GlowColour = new Color4(171, 255, 255, 255)
}
};
}
@ -67,5 +75,115 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon
fill.Rotation = (float)(90 - fill.Current.Value * 180);
}
private partial class ProgressFill : CircularProgress
{
private Color4 glowColour = Color4.White;
public Color4 GlowColour
{
get => glowColour;
set
{
glowColour = value;
Invalidate(Invalidation.DrawNode);
}
}
private Texture glowTexture = null!;
private IShader glowShader = null!;
private float glowSize;
[BackgroundDependencyLoader]
private void load(TextureStore textures, ShaderManager shaders)
{
glowTexture = textures.Get("Gameplay/osu/spinner-glow");
glowShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "SpinnerGlow");
glowSize = Blur.KernelSize(50); // Half of the maximum blur sigma in the design (which is 100)
}
protected override DrawNode CreateDrawNode() => new ProgressFillDrawNode(this);
private class ProgressFillDrawNode : CircularProgressDrawNode
{
protected new ProgressFill Source => (ProgressFill)base.Source;
public ProgressFillDrawNode(CircularProgress source)
: base(source)
{
}
private Texture glowTexture = null!;
private IShader glowShader = null!;
private Quad glowQuad;
private float relativeGlowSize;
private Color4 glowColour;
public override void ApplyState()
{
base.ApplyState();
glowTexture = Source.glowTexture;
glowShader = Source.glowShader;
glowColour = Source.glowColour;
// Inflated draw quad by the size of the blur.
glowQuad = Source.ToScreenSpace(DrawRectangle.Inflate(Source.glowSize));
relativeGlowSize = Source.glowSize / Source.DrawSize.X;
}
public override void Draw(IRenderer renderer)
{
base.Draw(renderer);
drawGlow(renderer);
}
private void drawGlow(IRenderer renderer)
{
renderer.SetBlend(BlendingParameters.Additive);
glowShader.Bind();
bindGlowUniformResources(glowShader, renderer);
ColourInfo col = DrawColourInfo.Colour;
col.ApplyChild(glowColour);
renderer.DrawQuad(glowTexture, glowQuad, col);
glowShader.Unbind();
}
private IUniformBuffer<ProgressGlowParameters>? progressGlowParametersBuffer;
private void bindGlowUniformResources(IShader shader, IRenderer renderer)
{
progressGlowParametersBuffer ??= renderer.CreateUniformBuffer<ProgressGlowParameters>();
progressGlowParametersBuffer.Data = new ProgressGlowParameters
{
InnerRadius = InnerRadius,
Progress = Progress,
TexelSize = TexelSize,
GlowSize = relativeGlowSize
};
shader.BindUniformBlock("m_ProgressGlowParameters", progressGlowParametersBuffer);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
progressGlowParametersBuffer?.Dispose();
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private record struct ProgressGlowParameters
{
public UniformFloat InnerRadius;
public UniformFloat Progress;
public UniformFloat TexelSize;
public UniformFloat GlowSize;
}
}
}
}
}