From 7edc2b3cef5dfd284b19f5eeb7ecfe007ed59914 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 22 Feb 2024 16:37:53 +0900 Subject: [PATCH 01/10] Add back ctor --- .../Veldrid/Buffers/VeldridFrameBuffer.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs b/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs index 651505402..d99a368f0 100644 --- a/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs +++ b/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs @@ -22,8 +22,9 @@ namespace osu.Framework.Graphics.Veldrid.Buffers private readonly VeldridRenderer renderer; private readonly PixelFormat? depthFormat; - private readonly VeldridTexture colourTarget; + private readonly bool externalColourTarget; + private readonly int mipLevel; private Texture? depthTarget; private Vector2 size = Vector2.One; @@ -63,6 +64,18 @@ namespace osu.Framework.Graphics.Veldrid.Buffers recreateResources(); } + internal VeldridFrameBuffer(VeldridRenderer renderer, VeldridTexture colourTarget, int mipLevel) + { + this.renderer = renderer; + this.colourTarget = colourTarget; + this.mipLevel = mipLevel; + + Texture = renderer.CreateTexture(colourTarget); + externalColourTarget = true; + + recreateResources(); + } + [MemberNotNull(nameof(Framebuffer))] private void recreateResources() { @@ -77,7 +90,7 @@ namespace osu.Framework.Graphics.Veldrid.Buffers FramebufferDescription description = new FramebufferDescription { - ColorTargets = new[] { new FramebufferAttachmentDescription(colourTarget.GetResourceList().Single().Texture, 0) }, + ColorTargets = new[] { new FramebufferAttachmentDescription(colourTarget.GetResourceList().Single().Texture, 0, (uint)mipLevel) }, DepthTarget = depthTarget == null ? null : new FramebufferAttachmentDescription(depthTarget, 0) }; @@ -97,7 +110,7 @@ namespace osu.Framework.Graphics.Veldrid.Buffers /// Whether the texture should also be deleted. private void deleteResources(bool deleteTexture) { - if (deleteTexture) + if (deleteTexture && !externalColourTarget) colourTarget.Dispose(); if (Framebuffer.IsNotNull()) From b66df36026e70bb972a6febd7ba3554368323fd1 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 23 Feb 2024 02:52:20 +0900 Subject: [PATCH 02/10] Add common renderer DeleteFrameBuffer method --- osu.Framework/Graphics/OpenGL/GLRenderer.cs | 13 ++----------- osu.Framework/Graphics/Rendering/Renderer.cs | 14 ++++++++++++++ .../Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs | 10 +++------- osu.Framework/Graphics/Veldrid/VeldridRenderer.cs | 3 +++ 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/osu.Framework/Graphics/OpenGL/GLRenderer.cs b/osu.Framework/Graphics/OpenGL/GLRenderer.cs index 5819b430d..338cff27f 100644 --- a/osu.Framework/Graphics/OpenGL/GLRenderer.cs +++ b/osu.Framework/Graphics/OpenGL/GLRenderer.cs @@ -233,17 +233,8 @@ namespace osu.Framework.Graphics.OpenGL protected override void SetFrameBufferImplementation(IFrameBuffer? frameBuffer) => GL.BindFramebuffer(FramebufferTarget.Framebuffer, ((GLFrameBuffer?)frameBuffer)?.FrameBuffer ?? backbufferFramebuffer); - /// - /// Deletes a frame buffer. - /// - /// The frame buffer to delete. - public void DeleteFrameBuffer(IFrameBuffer frameBuffer) - { - while (FrameBuffer == frameBuffer) - UnbindFrameBuffer(frameBuffer); - - ScheduleDisposal(GL.DeleteFramebuffer, ((GLFrameBuffer)frameBuffer).FrameBuffer); - } + protected override void DeleteFrameBufferImplementation(IFrameBuffer frameBuffer) + => GL.DeleteFramebuffer(((GLFrameBuffer)frameBuffer).FrameBuffer); protected override void ClearImplementation(ClearInfo clearInfo) { diff --git a/osu.Framework/Graphics/Rendering/Renderer.cs b/osu.Framework/Graphics/Rendering/Renderer.cs index fb9b89a24..48b290955 100644 --- a/osu.Framework/Graphics/Rendering/Renderer.cs +++ b/osu.Framework/Graphics/Rendering/Renderer.cs @@ -966,6 +966,20 @@ namespace osu.Framework.Graphics.Rendering /// The framebuffer to use, or null to use the backbuffer (i.e. main framebuffer). protected abstract void SetFrameBufferImplementation(IFrameBuffer? frameBuffer); + /// + /// Deletes a frame buffer. + /// + /// The frame buffer to delete. + public void DeleteFrameBuffer(IFrameBuffer frameBuffer) + { + while (FrameBuffer == frameBuffer) + UnbindFrameBuffer(frameBuffer); + + ScheduleDisposal(DeleteFrameBufferImplementation, frameBuffer); + } + + protected abstract void DeleteFrameBufferImplementation(IFrameBuffer frameBuffer); + #endregion public void DrawVertices(PrimitiveTopology topology, int vertexStart, int verticesCount) diff --git a/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs b/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs index d99a368f0..41abbb668 100644 --- a/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs +++ b/osu.Framework/Graphics/Veldrid/Buffers/VeldridFrameBuffer.cs @@ -80,7 +80,7 @@ namespace osu.Framework.Graphics.Veldrid.Buffers private void recreateResources() { // The texture is created once and resized internally, so it should not be deleted. - deleteResources(false); + DeleteResources(false); if (depthFormat is PixelFormat depth) { @@ -108,7 +108,7 @@ namespace osu.Framework.Graphics.Veldrid.Buffers /// Deletes the resources of this frame buffer. /// /// Whether the texture should also be deleted. - private void deleteResources(bool deleteTexture) + public void DeleteResources(bool deleteTexture) { if (deleteTexture && !externalColourTarget) colourTarget.Dispose(); @@ -140,11 +140,7 @@ namespace osu.Framework.Graphics.Veldrid.Buffers if (isDisposed) return; - while (renderer.IsFrameBufferBound(this)) - Unbind(); - - deleteResources(true); - + renderer.DeleteFrameBuffer(this); isDisposed = true; } diff --git a/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs b/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs index 8ee6e362b..115087749 100644 --- a/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs +++ b/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs @@ -491,6 +491,9 @@ namespace osu.Framework.Graphics.Veldrid SetFramebuffer(framebuffer); } + protected override void DeleteFrameBufferImplementation(IFrameBuffer frameBuffer) + => ((VeldridFrameBuffer)frameBuffer).DeleteResources(true); + public override void DrawVerticesImplementation(PrimitiveTopology topology, int vertexStart, int verticesCount) { // normally we would flush/submit all texture upload commands at the end of the frame, since no actual rendering by the GPU will happen until then, From 3544d63a9462d0daf3b14550272d302dab783254 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 25 Feb 2024 13:20:51 +0300 Subject: [PATCH 03/10] Reduce allocations in PerformanceOverlay --- .../Performance/PerformanceOverlay.cs | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/osu.Framework/Graphics/Performance/PerformanceOverlay.cs b/osu.Framework/Graphics/Performance/PerformanceOverlay.cs index d63e1d0c2..772734cd4 100644 --- a/osu.Framework/Graphics/Performance/PerformanceOverlay.cs +++ b/osu.Framework/Graphics/Performance/PerformanceOverlay.cs @@ -77,22 +77,27 @@ namespace osu.Framework.Graphics.Performance // for some reason PerformanceOverlay has 0 width despite using AutoSizeAxes, and it doesn't look simple to fix. // let's just work around it and consider frame statistics display dimensions for receiving input events. - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Children.OfType().Any(d => d.ReceivePositionalInputAt(screenSpacePos)); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + foreach (var child in this) + { + if (child is FrameStatisticsDisplay display && display.ReceivePositionalInputAt(screenSpacePos)) + return true; + } + + return false; + } protected override bool OnKeyDown(KeyDownEvent e) { switch (e.Key) { case Key.ControlLeft: - foreach (var display in Children.OfType()) - display.Expanded = true; - + applyToDisplays(static d => d.Expanded = true); break; case Key.ShiftLeft: - foreach (var display in Children.OfType()) - display.Running = false; - + applyToDisplays(static d => d.Running = false); break; } @@ -104,15 +109,11 @@ namespace osu.Framework.Graphics.Performance switch (e.Key) { case Key.ControlLeft: - foreach (var display in Children.OfType()) - display.Expanded = false; - + applyToDisplays(static d => d.Expanded = false); break; case Key.ShiftLeft: - foreach (var display in Children.OfType()) - display.Running = true; - + applyToDisplays(static d => d.Running = true); break; } @@ -124,15 +125,11 @@ namespace osu.Framework.Graphics.Performance switch (e.Touch.Source) { case TouchSource.Touch1: - foreach (var display in Children.OfType()) - display.Expanded = true; - + applyToDisplays(static d => d.Expanded = true); break; case TouchSource.Touch2: - foreach (var display in Children.OfType()) - display.Running = false; - + applyToDisplays(static d => d.Running = false); break; } @@ -144,15 +141,11 @@ namespace osu.Framework.Graphics.Performance switch (e.Touch.Source) { case TouchSource.Touch1: - foreach (var display in Children.OfType()) - display.Expanded = false; - + applyToDisplays(static d => d.Expanded = false); break; case TouchSource.Touch2: - foreach (var display in Children.OfType()) - display.Running = true; - + applyToDisplays(static d => d.Running = true); break; } @@ -201,12 +194,24 @@ namespace osu.Framework.Graphics.Performance break; } - foreach (FrameStatisticsDisplay d in Children.OfType()) - d.State = state; + foreach (var child in this) + { + if (child is FrameStatisticsDisplay display) + display.State = state; + } StateChanged?.Invoke(State); } + private void applyToDisplays(Predicate predicate) + { + foreach (var child in this) + { + if (child is FrameStatisticsDisplay display) + predicate.Invoke(display); + } + } + private void updateInfoText() { if (infoText == null) From f14486d4f86d6ce4c868334f955e7ffd1b80e6f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 10:19:13 +0800 Subject: [PATCH 04/10] Store `FrameStatisticDisplay`s to a list to make addressing them easier --- .../Performance/PerformanceOverlay.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Framework/Graphics/Performance/PerformanceOverlay.cs b/osu.Framework/Graphics/Performance/PerformanceOverlay.cs index 772734cd4..cd535a8c3 100644 --- a/osu.Framework/Graphics/Performance/PerformanceOverlay.cs +++ b/osu.Framework/Graphics/Performance/PerformanceOverlay.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -39,6 +40,8 @@ namespace osu.Framework.Graphics.Performance private bool initialised; + private readonly List framedDisplays = new List(); + public FrameStatisticsMode State { get => state; @@ -79,9 +82,9 @@ namespace osu.Framework.Graphics.Performance // let's just work around it and consider frame statistics display dimensions for receiving input events. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) { - foreach (var child in this) + foreach (var display in framedDisplays) { - if (child is FrameStatisticsDisplay display && display.ReceivePositionalInputAt(screenSpacePos)) + if (display.ReceivePositionalInputAt(screenSpacePos)) return true; } @@ -181,12 +184,15 @@ namespace osu.Framework.Graphics.Performance foreach (GameThread t in host.Threads) { - Add(new FrameStatisticsDisplay(t, uploadPool) + var display = new FrameStatisticsDisplay(t, uploadPool) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, State = state - }); + }; + + Add(display); + framedDisplays.Add(display); } } @@ -194,22 +200,16 @@ namespace osu.Framework.Graphics.Performance break; } - foreach (var child in this) - { - if (child is FrameStatisticsDisplay display) - display.State = state; - } + foreach (var display in framedDisplays) + display.State = state; StateChanged?.Invoke(State); } private void applyToDisplays(Predicate predicate) { - foreach (var child in this) - { - if (child is FrameStatisticsDisplay display) - predicate.Invoke(display); - } + foreach (var display in framedDisplays) + predicate.Invoke(display); } private void updateInfoText() From c35d537ce43a94b6f7644804a88c311417880e88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 13:05:16 +0800 Subject: [PATCH 05/10] Fix typo in variable name --- .../Graphics/Performance/PerformanceOverlay.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Framework/Graphics/Performance/PerformanceOverlay.cs b/osu.Framework/Graphics/Performance/PerformanceOverlay.cs index cd535a8c3..1d0f58b06 100644 --- a/osu.Framework/Graphics/Performance/PerformanceOverlay.cs +++ b/osu.Framework/Graphics/Performance/PerformanceOverlay.cs @@ -40,7 +40,7 @@ namespace osu.Framework.Graphics.Performance private bool initialised; - private readonly List framedDisplays = new List(); + private readonly List frameDisplays = new List(); public FrameStatisticsMode State { @@ -82,7 +82,7 @@ namespace osu.Framework.Graphics.Performance // let's just work around it and consider frame statistics display dimensions for receiving input events. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) { - foreach (var display in framedDisplays) + foreach (var display in frameDisplays) { if (display.ReceivePositionalInputAt(screenSpacePos)) return true; @@ -192,7 +192,7 @@ namespace osu.Framework.Graphics.Performance }; Add(display); - framedDisplays.Add(display); + frameDisplays.Add(display); } } @@ -200,7 +200,7 @@ namespace osu.Framework.Graphics.Performance break; } - foreach (var display in framedDisplays) + foreach (var display in frameDisplays) display.State = state; StateChanged?.Invoke(State); @@ -208,7 +208,7 @@ namespace osu.Framework.Graphics.Performance private void applyToDisplays(Predicate predicate) { - foreach (var display in framedDisplays) + foreach (var display in frameDisplays) predicate.Invoke(display); } From 082f699aa5d62e027d4f10a3fe095012edc1fa62 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 26 Feb 2024 19:40:37 +0900 Subject: [PATCH 06/10] Improve benchmark --- .../BenchmarkAggregateBindable.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Framework.Benchmarks/BenchmarkAggregateBindable.cs b/osu.Framework.Benchmarks/BenchmarkAggregateBindable.cs index 3e01b96c6..bb6039a65 100644 --- a/osu.Framework.Benchmarks/BenchmarkAggregateBindable.cs +++ b/osu.Framework.Benchmarks/BenchmarkAggregateBindable.cs @@ -11,15 +11,27 @@ namespace osu.Framework.Benchmarks { private readonly BindableInt source1 = new BindableInt(); private readonly BindableInt source2 = new BindableInt(); + private readonly AggregateBindable boundAggregate = new AggregateBindable(((i, j) => i + j)); + private readonly AggregateBindable aggregate = new AggregateBindable(((i, j) => i + j)); + + [GlobalSetup] + public void GlobalSetup() + { + boundAggregate.AddSource(source1); + boundAggregate.AddSource(source2); + } [Benchmark] - public void AggregateRecalculation() + public void AddRemoveSource() { - var aggregate = new AggregateBindable(((i, j) => i + j)); - aggregate.AddSource(source1); aggregate.AddSource(source2); + aggregate.RemoveAllSources(); + } + [Benchmark] + public void SetValue() + { for (int i = 0; i < 100; i++) { source1.Value = i; From 840d401018f852ed0f2438d854d0baa650a019e6 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 26 Feb 2024 19:56:39 +0900 Subject: [PATCH 07/10] Reduce WeakReference allocs in AggregateBindable --- osu.Framework/Bindables/AggregateBindable.cs | 6 +++--- osu.Framework/Bindables/Bindable.cs | 2 ++ osu.Framework/Bindables/IBindable.cs | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Framework/Bindables/AggregateBindable.cs b/osu.Framework/Bindables/AggregateBindable.cs index 9e327752d..66afffe23 100644 --- a/osu.Framework/Bindables/AggregateBindable.cs +++ b/osu.Framework/Bindables/AggregateBindable.cs @@ -52,7 +52,7 @@ namespace osu.Framework.Bindables return; var boundCopy = bindable.GetBoundCopy(); - sourceMapping.Add(new WeakRefPair(new WeakReference>(bindable), boundCopy)); + sourceMapping.Add(new WeakRefPair(bindable.GetWeakReference(), boundCopy)); boundCopy.BindValueChanged(recalculateAggregate, true); } } @@ -114,10 +114,10 @@ namespace osu.Framework.Bindables private class WeakRefPair { - public readonly WeakReference> WeakReference; + public readonly WeakReference> WeakReference; public readonly IBindable BoundCopy; - public WeakRefPair(WeakReference> weakReference, IBindable boundCopy) + public WeakRefPair(WeakReference> weakReference, IBindable boundCopy) { WeakReference = weakReference; BoundCopy = boundCopy; diff --git a/osu.Framework/Bindables/Bindable.cs b/osu.Framework/Bindables/Bindable.cs index 5f4687ba3..f213d44fc 100644 --- a/osu.Framework/Bindables/Bindable.cs +++ b/osu.Framework/Bindables/Bindable.cs @@ -440,6 +440,8 @@ namespace osu.Framework.Bindables IBindable IBindable.GetBoundCopy() => GetBoundCopy(); + public WeakReference> GetWeakReference() => weakReference; + IBindable IBindable.GetBoundCopy() => GetBoundCopy(); /// diff --git a/osu.Framework/Bindables/IBindable.cs b/osu.Framework/Bindables/IBindable.cs index 74b4de3c1..dc64d96f0 100644 --- a/osu.Framework/Bindables/IBindable.cs +++ b/osu.Framework/Bindables/IBindable.cs @@ -111,5 +111,10 @@ namespace osu.Framework.Bindables /// IBindable GetBoundCopy(); + + /// + /// Retrieves a weak reference to this bindable. + /// + internal WeakReference> GetWeakReference(); } } From 7a33912086243c8c6844c887092e08c9a448bea8 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 26 Feb 2024 20:04:45 +0900 Subject: [PATCH 08/10] Further reduce allocs --- osu.Framework/Bindables/AggregateBindable.cs | 33 +++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/osu.Framework/Bindables/AggregateBindable.cs b/osu.Framework/Bindables/AggregateBindable.cs index 66afffe23..e65a66e95 100644 --- a/osu.Framework/Bindables/AggregateBindable.cs +++ b/osu.Framework/Bindables/AggregateBindable.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Linq; namespace osu.Framework.Bindables { @@ -65,20 +64,26 @@ namespace osu.Framework.Bindables { lock (sourceMapping) { - var weak = findExistingPair(bindable); - - if (weak != null) + if (findExistingPair(bindable) is WeakRefPair pair) { - weak.BoundCopy.UnbindAll(); - sourceMapping.Remove(weak); + pair.BoundCopy.UnbindAll(); + sourceMapping.Remove(pair); } recalculateAggregate(); } } - private WeakRefPair findExistingPair(IBindable bindable) => - sourceMapping.FirstOrDefault(p => p.WeakReference.TryGetTarget(out var target) && target == bindable); + private WeakRefPair? findExistingPair(IBindable bindable) + { + foreach (var p in sourceMapping) + { + if (p.WeakReference.TryGetTarget(out var target) && target == bindable) + return p; + } + + return null; + } private void recalculateAggregate(ValueChangedEvent obj = null) { @@ -112,16 +117,6 @@ namespace osu.Framework.Bindables } } - private class WeakRefPair - { - public readonly WeakReference> WeakReference; - public readonly IBindable BoundCopy; - - public WeakRefPair(WeakReference> weakReference, IBindable boundCopy) - { - WeakReference = weakReference; - BoundCopy = boundCopy; - } - } + private readonly record struct WeakRefPair(WeakReference> WeakReference, IBindable BoundCopy); } } From 0ad9d94fe57efc4015f5abf5ee69d866bf24612c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 26 Feb 2024 13:35:41 +0100 Subject: [PATCH 09/10] Do not expose `GetWeakReference()` as public on `Bindable` --- osu.Framework/Bindables/Bindable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Framework/Bindables/Bindable.cs b/osu.Framework/Bindables/Bindable.cs index f213d44fc..4447e2a15 100644 --- a/osu.Framework/Bindables/Bindable.cs +++ b/osu.Framework/Bindables/Bindable.cs @@ -440,7 +440,7 @@ namespace osu.Framework.Bindables IBindable IBindable.GetBoundCopy() => GetBoundCopy(); - public WeakReference> GetWeakReference() => weakReference; + WeakReference> IBindable.GetWeakReference() => weakReference; IBindable IBindable.GetBoundCopy() => GetBoundCopy(); From 6765cb7571b1c9a6ad4dd831643c9738e630bb75 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 26 Feb 2024 21:21:28 +0300 Subject: [PATCH 10/10] Remove bindable from CircularProgress --- .../Visual/Graphics/TestSceneStencil.cs | 4 +- .../TestSceneVertexUploadPerformance.cs | 2 +- .../TestSceneCircularProgress.cs | 18 +++---- .../Graphics/Cursor/CursorContainer.cs | 6 +-- .../UserInterface/CircularProgress.cs | 54 +++++++++---------- 5 files changed, 41 insertions(+), 43 deletions(-) diff --git a/osu.Framework.Tests/Visual/Graphics/TestSceneStencil.cs b/osu.Framework.Tests/Visual/Graphics/TestSceneStencil.cs index fe0882a55..e918640c3 100644 --- a/osu.Framework.Tests/Visual/Graphics/TestSceneStencil.cs +++ b/osu.Framework.Tests/Visual/Graphics/TestSceneStencil.cs @@ -82,7 +82,7 @@ namespace osu.Framework.Tests.Visual.Graphics Size = new Vector2(circle_radius), RelativePositionAxes = Axes.Both, Position = new Vector2(xPos, yPos), - Current = { Value = 1 } + Progress = 1 }); circlesContainerBuffered.Add(new CircularProgress @@ -91,7 +91,7 @@ namespace osu.Framework.Tests.Visual.Graphics Size = new Vector2(circle_radius), RelativePositionAxes = Axes.Both, Position = new Vector2(xPos, yPos), - Current = { Value = 1 } + Progress = 1 }); } } diff --git a/osu.Framework.Tests/Visual/Performance/TestSceneVertexUploadPerformance.cs b/osu.Framework.Tests/Visual/Performance/TestSceneVertexUploadPerformance.cs index b5c209ed6..ab642bda5 100644 --- a/osu.Framework.Tests/Visual/Performance/TestSceneVertexUploadPerformance.cs +++ b/osu.Framework.Tests/Visual/Performance/TestSceneVertexUploadPerformance.cs @@ -17,7 +17,7 @@ namespace osu.Framework.Tests.Visual.Performance base.Update(); foreach (var p in Flow.OfType()) - p.Current.Value = (p.Current.Value + (Time.Elapsed * RNG.NextSingle()) / 1000) % 1; + p.Progress = (p.Progress + (Time.Elapsed * RNG.NextSingle()) / 1000) % 1; } } } diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneCircularProgress.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneCircularProgress.cs index 522911abe..299b77fec 100644 --- a/osu.Framework.Tests/Visual/UserInterface/TestSceneCircularProgress.cs +++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneCircularProgress.cs @@ -145,23 +145,23 @@ namespace osu.Framework.Tests.Visual.UserInterface switch (rotateMode) { case 0: - clock.Current.Value = Time.Current % (period * 2) / period - 1; + clock.Progress = Time.Current % (period * 2) / period - 1; break; case 1: - clock.Current.Value = Time.Current % period / period; + clock.Progress = Time.Current % period / period; break; case 2: - clock.Current.Value = Time.Current % period / period - 1; + clock.Progress = Time.Current % period / period - 1; break; case 3: - clock.Current.Value = Time.Current % transition_period / transition_period / 5 - 0.1f; + clock.Progress = Time.Current % transition_period / transition_period / 5 - 0.1f; break; case 4: - clock.Current.Value = (Time.Current % transition_period / transition_period / 5 - 0.1f + 2) % 2 - 1; + clock.Progress = (Time.Current % transition_period / transition_period / 5 - 0.1f + 2) % 2 - 1; break; } } @@ -245,19 +245,19 @@ namespace osu.Framework.Tests.Visual.UserInterface switch (tf) { case 0: - clock.FillTo(0).Then().FillTo(1, 1000).Loop(); + clock.ProgressTo(0).Then().ProgressTo(1, 1000).Loop(); break; case 1: - clock.FillTo(1).Then().FillTo(0, 1000).Loop(); + clock.ProgressTo(1).Then().ProgressTo(0, 1000).Loop(); break; case 2: - clock.FillTo(0, 1000).Then().FillTo(1, 1000).Loop(); + clock.ProgressTo(0, 1000).Then().ProgressTo(1, 1000).Loop(); break; case 3: - clock.FillTo(0).Then().FillTo(1, 1000, Easing.InOutQuart).Loop(); + clock.ProgressTo(0).Then().ProgressTo(1, 1000, Easing.InOutQuart).Loop(); break; } } diff --git a/osu.Framework/Graphics/Cursor/CursorContainer.cs b/osu.Framework/Graphics/Cursor/CursorContainer.cs index 38e6cd142..47c5ee738 100644 --- a/osu.Framework/Graphics/Cursor/CursorContainer.cs +++ b/osu.Framework/Graphics/Cursor/CursorContainer.cs @@ -148,8 +148,8 @@ namespace osu.Framework.Graphics.Cursor progress.FadeColour(Color4.SkyBlue) .TransformTo(nameof(progress.InnerRadius), 0.2f) .TransformTo(nameof(progress.InnerRadius), 0.3f, 150, Easing.OutQuint) - .TransformBindableTo(progress.Current, 0) - .TransformBindableTo(progress.Current, 1, duration / 3 * 2); + .ProgressTo(0) + .ProgressTo(1, duration / 3 * 2); using (BeginDelayedSequence(duration / 3 * 2)) { @@ -165,7 +165,7 @@ namespace osu.Framework.Graphics.Cursor { this.FadeOut(400, Easing.OutQuint); - progress.TransformBindableTo(progress.Current, 0, 400, Easing.OutQuint) + progress.ProgressTo(0, 400, Easing.OutQuint) .TransformTo(nameof(progress.InnerRadius), 0.2f, 50, Easing.OutQuint); } } diff --git a/osu.Framework/Graphics/UserInterface/CircularProgress.cs b/osu.Framework/Graphics/UserInterface/CircularProgress.cs index e2a0b61f9..bca36fec4 100644 --- a/osu.Framework/Graphics/UserInterface/CircularProgress.cs +++ b/osu.Framework/Graphics/UserInterface/CircularProgress.cs @@ -6,7 +6,6 @@ using System; using System.Runtime.InteropServices; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Shaders.Types; @@ -15,14 +14,26 @@ using osu.Framework.Graphics.Transforms; namespace osu.Framework.Graphics.UserInterface { - public partial class CircularProgress : Sprite, IHasCurrentValue + public partial class CircularProgress : Sprite { - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private double progress; - public Bindable Current + public double Progress { - get => current.Current; - set => current.Current = value; + get => progress; + set + { + if (!double.IsFinite(value)) + throw new ArgumentException($"{nameof(Progress)} must be finite, but is {value}."); + + if (progress == value) + return; + + progress = value; + + if (IsLoaded) + Invalidate(Invalidation.DrawNode); + } } [BackgroundDependencyLoader] @@ -32,27 +43,14 @@ namespace osu.Framework.Graphics.UserInterface TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "CircularProgress"); } - protected override void LoadComplete() - { - base.LoadComplete(); - - Current.BindValueChanged(c => - { - if (!double.IsFinite(c.NewValue)) - throw new ArgumentException($"{nameof(Current)} must be finite, but is {c.NewValue}."); - - Invalidate(Invalidation.DrawNode); - }, true); - } - 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 ProgressTo(double newValue, double duration = 0, Easing easing = Easing.None) + => ProgressTo(newValue, duration, new DefaultEasingFunction(easing)); - public TransformSequence FillTo(double newValue, double duration, in TEasing easing) + public TransformSequence ProgressTo(double newValue, double duration, in TEasing easing) where TEasing : IEasingFunction - => this.TransformBindableTo(Current, newValue, duration, easing); + => this.TransformTo(nameof(Progress), newValue, duration, easing); private float innerRadius = 1; @@ -108,7 +106,7 @@ namespace osu.Framework.Graphics.UserInterface base.ApplyState(); InnerRadius = Source.innerRadius; - Progress = Math.Abs((float)Source.current.Value); + Progress = Math.Abs((float)Source.progress); RoundedCaps = Source.roundedCaps; // smoothstep looks too sharp with 1px, let's give it a bit more @@ -162,11 +160,11 @@ namespace osu.Framework.Graphics.UserInterface 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 ProgressTo(this TransformSequence t, double newValue, double duration = 0, Easing easing = Easing.None) + => t.ProgressTo(newValue, duration, new DefaultEasingFunction(easing)); - public static TransformSequence FillTo(this TransformSequence t, double newValue, double duration, TEasing easing) + public static TransformSequence ProgressTo(this TransformSequence t, double newValue, double duration, TEasing easing) where TEasing : IEasingFunction - => t.Append(cp => cp.FillTo(newValue, duration, easing)); + => t.Append(cp => cp.ProgressTo(newValue, duration, easing)); } }