mirror of
https://github.com/ppy/osu.git
synced 2025-03-28 01:47:33 +08:00
reafactor: use DrawNode to draw SegmenteddGraph
This commit is contained in:
parent
91eab7985b
commit
21073f3601
@ -5,20 +5,19 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Rendering;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Graphics.Shaders;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
public abstract partial class SegmentedGraph<T> : Container
|
public abstract partial class SegmentedGraph<T> : Drawable
|
||||||
where T : struct, IComparable<T>, IConvertible, IEquatable<T>
|
where T : struct, IComparable<T>, IConvertible, IEquatable<T>
|
||||||
{
|
{
|
||||||
private BufferedContainer? rectSegments;
|
|
||||||
private float previousDrawWidth;
|
|
||||||
private bool graphNeedsUpdate;
|
private bool graphNeedsUpdate;
|
||||||
|
|
||||||
private T[]? values;
|
private T[]? values;
|
||||||
@ -44,53 +43,33 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
values = value;
|
values = value;
|
||||||
recalculateTiers(values);
|
recalculateTiers(values);
|
||||||
graphNeedsUpdate = true;
|
graphNeedsUpdate = true;
|
||||||
|
Invalidate(Invalidation.DrawNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Colour4[] TierColours;
|
public readonly Colour4[] TierColours;
|
||||||
|
|
||||||
private CancellationTokenSource? cts;
|
private Texture texture = null!;
|
||||||
private ScheduledDelegate? scheduledCreate;
|
private IShader shader = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IRenderer renderer, ShaderManager shaders)
|
||||||
|
{
|
||||||
|
texture = renderer.WhitePixel;
|
||||||
|
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (graphNeedsUpdate || (values != null && DrawWidth != previousDrawWidth))
|
if (graphNeedsUpdate)
|
||||||
{
|
{
|
||||||
rectSegments?.FadeOut(150, Easing.OutQuint).Expire();
|
recalculateSegments();
|
||||||
|
Invalidate(Invalidation.DrawNode);
|
||||||
scheduledCreate?.Cancel();
|
|
||||||
scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 150);
|
|
||||||
|
|
||||||
previousDrawWidth = DrawWidth;
|
|
||||||
graphNeedsUpdate = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RecreateGraph()
|
|
||||||
{
|
|
||||||
var newSegments = new BufferedContainer(cachedFrameBuffer: true)
|
|
||||||
{
|
|
||||||
RedrawOnScale = false,
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
};
|
|
||||||
|
|
||||||
cts?.Cancel();
|
|
||||||
recalculateSegments();
|
|
||||||
redrawSegments(newSegments);
|
|
||||||
|
|
||||||
LoadComponentAsync(newSegments, s =>
|
|
||||||
{
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
rectSegments = s
|
|
||||||
};
|
|
||||||
|
|
||||||
s.FadeInFromZero(100);
|
|
||||||
}, (cts = new CancellationTokenSource()).Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recalculateTiers(T[]? arr)
|
private void recalculateTiers(T[]? arr)
|
||||||
{
|
{
|
||||||
if (arr == null || arr.Length == 0)
|
if (arr == null || arr.Length == 0)
|
||||||
@ -159,32 +138,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
private Colour4 tierToColour(int tier) => tier >= 0 ? TierColours[tier] : new Colour4(0, 0, 0, 0);
|
private Colour4 tierToColour(int tier) => tier >= 0 ? TierColours[tier] : new Colour4(0, 0, 0, 0);
|
||||||
|
|
||||||
// Base implementation, could be drawn with draw node if preferred
|
protected override DrawNode CreateDrawNode() => new SegmentedGraphDrawNode(this);
|
||||||
private void redrawSegments(BufferedContainer container)
|
|
||||||
{
|
|
||||||
if (segments.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (SegmentInfo segment in segments) // Lower tiers will be drawn first, putting them in the back
|
|
||||||
{
|
|
||||||
float width = segment.Length * DrawWidth;
|
|
||||||
|
|
||||||
// If the segment width exceeds the DrawWidth, just fill the rest
|
|
||||||
if (width >= DrawWidth)
|
|
||||||
width = DrawWidth;
|
|
||||||
|
|
||||||
container.Add(new Box
|
|
||||||
{
|
|
||||||
Name = $"Tier {segment.Tier} segment",
|
|
||||||
Origin = Anchor.BottomLeft,
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Position = new Vector2(segment.Start * DrawWidth, 0),
|
|
||||||
Width = width,
|
|
||||||
Colour = tierToColour(segment.Tier)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected struct SegmentInfo
|
protected struct SegmentInfo
|
||||||
{
|
{
|
||||||
@ -218,6 +172,58 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
public float Length => End - Start;
|
public float Length => End - Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SegmentedGraphDrawNode : DrawNode
|
||||||
|
{
|
||||||
|
public new SegmentedGraph<T> Source => (SegmentedGraph<T>)base.Source;
|
||||||
|
|
||||||
|
private Texture texture = null!;
|
||||||
|
private IShader shader = null!;
|
||||||
|
private readonly List<SegmentInfo> segments = new List<SegmentInfo>();
|
||||||
|
private Vector2 drawSize;
|
||||||
|
|
||||||
|
public SegmentedGraphDrawNode(SegmentedGraph<T> source)
|
||||||
|
: base(source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ApplyState()
|
||||||
|
{
|
||||||
|
base.ApplyState();
|
||||||
|
|
||||||
|
texture = Source.texture;
|
||||||
|
shader = Source.shader;
|
||||||
|
drawSize = Source.DrawSize;
|
||||||
|
segments.Clear();
|
||||||
|
segments.AddRange(Source.segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(IRenderer renderer)
|
||||||
|
{
|
||||||
|
base.Draw(renderer);
|
||||||
|
|
||||||
|
shader.Bind();
|
||||||
|
|
||||||
|
foreach (SegmentInfo segment in segments)
|
||||||
|
{
|
||||||
|
Vector2 topLeft = new Vector2(segment.Start * drawSize.X, 0);
|
||||||
|
Vector2 topRight = new Vector2(segment.End * drawSize.X, 0);
|
||||||
|
Vector2 bottomLeft = new Vector2(segment.Start * drawSize.X, drawSize.Y);
|
||||||
|
Vector2 bottomRight = new Vector2(segment.End * drawSize.X, drawSize.Y);
|
||||||
|
|
||||||
|
renderer.DrawQuad(
|
||||||
|
texture,
|
||||||
|
new Quad(
|
||||||
|
Vector2Extensions.Transform(topLeft, DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(topRight, DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(bottomLeft, DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(bottomRight, DrawInfo.Matrix)),
|
||||||
|
Source.tierToColour(segment.Tier));
|
||||||
|
}
|
||||||
|
|
||||||
|
shader.Unbind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected class SegmentManager : IEnumerable<SegmentInfo>
|
protected class SegmentManager : IEnumerable<SegmentInfo>
|
||||||
{
|
{
|
||||||
private readonly List<SegmentInfo> segments = new List<SegmentInfo>();
|
private readonly List<SegmentInfo> segments = new List<SegmentInfo>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user