diff --git a/Content.Client/UserInterface/CooldownGraphic.cs b/Content.Client/UserInterface/CooldownGraphic.cs index 4e1cd2f484..6bd8f3bade 100644 --- a/Content.Client/UserInterface/CooldownGraphic.cs +++ b/Content.Client/UserInterface/CooldownGraphic.cs @@ -3,11 +3,26 @@ using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.Graphics; using Robust.Shared.Maths; using System; +using Robust.Client.Graphics.Shaders; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; namespace Robust.Client.UserInterface.Controls { + public class CooldownGraphic : Control { + + [Dependency] private readonly IPrototypeManager _protoMan = default!; + + private ShaderInstance _shader; + + public CooldownGraphic() + { + IoCManager.InjectDependencies(this); + _shader = _protoMan.Index("CooldownAnimation").InstanceUnique(); + } + /// /// Progress of the cooldown animation. /// Possible values range from 1 to -1, where 1 to 0 is a depleting circle animation and 0 to -1 is a blink animation. @@ -16,41 +31,26 @@ namespace Robust.Client.UserInterface.Controls protected override void Draw(DrawingHandleScreen handle) { - const int maxSegments = 64; - const float segment = MathHelper.TwoPi / maxSegments; + Color color; - var effective_fraction = Progress >= 0f ? Progress : 1f; // we want the full circle for the blink - - var segments = (int)Math.Max(2, Math.Ceiling(maxSegments * effective_fraction) + 1); // ensure that we always have at least 3 vertices, we also need one more segment - var max = MathHelper.TwoPi * effective_fraction; - var outer_radius = (Math.Min(SizeBox.Height, SizeBox.Width) / 2) * 0.875f; // 28/32 = 0.875 - 2 pixels inwards from the edge - var inner_radius = (Math.Min(SizeBox.Height, SizeBox.Width) / 2) * 0.5625f; // 18/32 = 0.5625 - 5 pixels thick - - Span vertices = stackalloc Vector2[segments * 2]; - var center = PixelPosition + SizeBox.Center; - for (int i = 0; i < segments; i++) - { - var angle = MathHelper.Pi + Math.Min(max, segment * i); - vertices[2*i] = center + new Vector2((float) Math.Sin(angle) * outer_radius, (float) Math.Cos(angle) * outer_radius); - vertices[2*i + 1] = center + new Vector2((float) Math.Sin(angle) * inner_radius, (float) Math.Cos(angle) * inner_radius); - } - - Color draw_color; - - var fraction_lerp = 1f - Math.Abs(Progress); // for future bikeshedding purposes + var lerp = 1f - Math.Abs(Progress); // for future bikeshedding purposes if (Progress >= 0f) { - var hue = (5f / 18f) * fraction_lerp; - draw_color = Color.FromHsv((hue, 0.75f, 0.75f, 0.50f)); + var hue = (5f / 18f) * lerp; + color = Color.FromHsv((hue, 0.75f, 0.75f, 0.50f)); } else { - var alpha = Math.Clamp(0.5f * fraction_lerp, 0f, 0.5f); - draw_color = new Color(1f, 1f, 1f, alpha); + var alpha = Math.Clamp(0.5f * lerp, 0f, 0.5f); + color = new Color(1f, 1f, 1f, alpha); } - handle.DrawPrimitives(DrawPrimitiveTopology.TriangleStrip, vertices, draw_color); + _shader.SetParameter("progress", Progress); + handle.UseShader(_shader); + handle.DrawRect(PixelSizeBox, color); } + } + } diff --git a/Resources/Prototypes/Shaders/cooldown.yml b/Resources/Prototypes/Shaders/cooldown.yml new file mode 100644 index 0000000000..51da84e393 --- /dev/null +++ b/Resources/Prototypes/Shaders/cooldown.yml @@ -0,0 +1,6 @@ +- type: shader + id: CooldownAnimation + kind: source + path: "/Shaders/cooldown.swsl" + params: + progress: 0 diff --git a/Resources/Shaders/cooldown.swsl b/Resources/Shaders/cooldown.swsl new file mode 100644 index 0000000000..90b215a1c3 --- /dev/null +++ b/Resources/Shaders/cooldown.swsl @@ -0,0 +1,25 @@ +light_mode unshaded; + +const float PI = 3.14159265; + +uniform float progress = 0.0; + +void fragment() { + vec4 col = texture(TEXTURE, UV); + vec2 center = vec2(0.5,0.5); + vec2 delta = UV.xy - center; + + float angle = atan(delta.x, -delta.y) + PI; + + float dist = length(delta); + float dist_fwidth = fwidth(dist) * 0.67; + + float dist_alpha = smoothstep(0.1-dist_fwidth, 0.1, abs(dist-0.35)); + + float angle_delta = (progress * PI * 2) - angle; + float arc_length = angle_delta * dist; + + float angle_alpha = progress > 0 ? smoothstep(dist_fwidth, 0.0, arc_length) : 0.0; + + COLOR = vec4(col.xyz, 1-max(dist_alpha, angle_alpha)); +} \ No newline at end of file