// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transforms; namespace osu.Framework.Graphics.UserInterface { public class CircularProgress : Drawable, ITexturedShaderDrawable, IHasCurrentValue { private readonly BindableWithCurrent current = new BindableWithCurrent(); public Bindable Current { get => current.Current; set => current.Current = value; } public CircularProgress() { Current.ValueChanged += newValue => Invalidate(Invalidation.DrawNode); } public IShader RoundedTextureShader { get; private set; } public IShader TextureShader { get; private set; } #region Disposal protected override void Dispose(bool isDisposing) { texture?.Dispose(); texture = null; base.Dispose(isDisposing); } #endregion protected override DrawNode CreateDrawNode() => new CircularProgressDrawNode(this); public TransformSequence FillTo(double newValue, double duration = 0, Easing easing = Easing.None) => FillTo(newValue, duration, new DefaultEasingFunction(easing)); public TransformSequence FillTo(double newValue, double duration, in TEasing easing) where TEasing : IEasingFunction => this.TransformBindableTo(Current, newValue, duration, easing); [BackgroundDependencyLoader] private void load(ShaderManager shaders) { RoundedTextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED); TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE); } private Texture texture = Texture.WhitePixel; public Texture Texture { get => texture; set { if (value == texture) return; texture?.Dispose(); texture = value; Invalidate(Invalidation.DrawNode); } } private float innerRadius = 1; /// /// The inner fill radius, relative to the of the . /// The value range is 0 to 1 where 0 is invisible and 1 is completely filled. /// The entire texture still fills the disk without cropping it. /// public float InnerRadius { get => innerRadius; set { innerRadius = Math.Clamp(value, 0, 1); Invalidate(Invalidation.DrawNode); } } } public static class CircularProgressTransformSequenceExtensions { public static TransformSequence FillTo(this TransformSequence t, double newValue, double duration = 0, Easing easing = Easing.None) => t.FillTo(newValue, duration, new DefaultEasingFunction(easing)); public static TransformSequence FillTo(this TransformSequence t, double newValue, double duration, TEasing easing) where TEasing : IEasingFunction => t.Append(cp => cp.FillTo(newValue, duration, easing)); } }