mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 21:23:04 +08:00
Merge branch 'master' into hide-no-spin-bonus
This commit is contained in:
commit
c0f65d83b3
@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Height = 0.82f,
|
Height = 0.82f,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
@ -54,6 +56,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = ArgonNotePiece.CORNER_RADIUS * 2,
|
Height = ArgonNotePiece.CORNER_RADIUS * 2,
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -32,6 +33,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
AddStep("values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Select(i => (float)i));
|
AddStep("values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Select(i => (float)i));
|
||||||
AddStep("values from 1-100", () => graph.Values = Enumerable.Range(1, 100).Select(i => (float)i));
|
AddStep("values from 1-100", () => graph.Values = Enumerable.Range(1, 100).Select(i => (float)i));
|
||||||
AddStep("reversed values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Reverse().Select(i => (float)i));
|
AddStep("reversed values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Reverse().Select(i => (float)i));
|
||||||
|
AddStep("empty values", () => graph.Values = Array.Empty<float>());
|
||||||
AddStep("Bottom to top", () => graph.Direction = BarDirection.BottomToTop);
|
AddStep("Bottom to top", () => graph.Direction = BarDirection.BottomToTop);
|
||||||
AddStep("Top to bottom", () => graph.Direction = BarDirection.TopToBottom);
|
AddStep("Top to bottom", () => graph.Direction = BarDirection.TopToBottom);
|
||||||
AddStep("Left to right", () => graph.Direction = BarDirection.LeftToRight);
|
AddStep("Left to right", () => graph.Direction = BarDirection.LeftToRight);
|
||||||
|
@ -136,7 +136,9 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
private static readonly string[] always_bundled_beatmaps =
|
private static readonly string[] always_bundled_beatmaps =
|
||||||
{
|
{
|
||||||
// This thing is 40mb, I'm not sure we want it here...
|
// This thing is 40mb, I'm not sure we want it here...
|
||||||
@"1388906 Raphlesia & BilliumMoto - My Love.osz"
|
@"1388906 Raphlesia & BilliumMoto - My Love.osz",
|
||||||
|
// Winner of Triangles mapping competition: https://osu.ppy.sh/home/news/2022-10-06-results-triangles
|
||||||
|
@"1841885 cYsmix - triangles.osz",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly string[] bundled_osu =
|
private static readonly string[] bundled_osu =
|
||||||
|
@ -109,15 +109,11 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum BarDirection
|
public enum BarDirection
|
||||||
{
|
{
|
||||||
LeftToRight = 1,
|
LeftToRight,
|
||||||
RightToLeft = 1 << 1,
|
RightToLeft,
|
||||||
TopToBottom = 1 << 2,
|
TopToBottom,
|
||||||
BottomToTop = 1 << 3,
|
BottomToTop
|
||||||
|
|
||||||
Vertical = TopToBottom | BottomToTop,
|
|
||||||
Horizontal = LeftToRight | RightToLeft,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,23 @@
|
|||||||
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Extensions.EnumExtensions;
|
using osu.Framework.Graphics.Rendering;
|
||||||
|
using osu.Framework.Graphics.Shaders;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
public class BarGraph : FillFlowContainer<Bar>
|
public class BarGraph : Drawable
|
||||||
{
|
{
|
||||||
|
private const int resize_duration = 250;
|
||||||
|
private const Easing easing = Easing.InOutCubic;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Manually sets the max value, if null <see cref="Enumerable.Max(IEnumerable{float})"/> is instead used
|
/// Manually sets the max value, if null <see cref="Enumerable.Max(IEnumerable{float})"/> is instead used
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -21,22 +29,21 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
private BarDirection direction = BarDirection.BottomToTop;
|
private BarDirection direction = BarDirection.BottomToTop;
|
||||||
|
|
||||||
public new BarDirection Direction
|
public BarDirection Direction
|
||||||
{
|
{
|
||||||
get => direction;
|
get => direction;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
direction = value;
|
if (direction == value)
|
||||||
base.Direction = direction.HasFlagFast(BarDirection.Horizontal) ? FillDirection.Vertical : FillDirection.Horizontal;
|
return;
|
||||||
|
|
||||||
foreach (var bar in Children)
|
direction = value;
|
||||||
{
|
Invalidate(Invalidation.DrawNode);
|
||||||
bar.Size = direction.HasFlagFast(BarDirection.Horizontal) ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1);
|
|
||||||
bar.Direction = direction;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly BarsInfo bars = new BarsInfo();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of floats that defines the length of each <see cref="Bar"/>
|
/// A list of floats that defines the length of each <see cref="Bar"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,37 +51,199 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
List<Bar> bars = Children.ToList();
|
if (!value.Any())
|
||||||
|
|
||||||
foreach (var bar in value.Select((length, index) => new { Value = length, Bar = bars.Count > index ? bars[index] : null }))
|
|
||||||
{
|
{
|
||||||
float length = MaxValue ?? value.Max();
|
bars.Clear();
|
||||||
if (length != 0)
|
Invalidate(Invalidation.DrawNode);
|
||||||
length = bar.Value / length;
|
return;
|
||||||
|
|
||||||
float size = value.Count();
|
|
||||||
if (size != 0)
|
|
||||||
size = 1.0f / size;
|
|
||||||
|
|
||||||
if (bar.Bar != null)
|
|
||||||
{
|
|
||||||
bar.Bar.Length = length;
|
|
||||||
bar.Bar.Size = direction.HasFlagFast(BarDirection.Horizontal) ? new Vector2(1, size) : new Vector2(size, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Add(new Bar
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = direction.HasFlagFast(BarDirection.Horizontal) ? new Vector2(1, size) : new Vector2(size, 1),
|
|
||||||
Length = length,
|
|
||||||
Direction = Direction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//I'm using ToList() here because Where() returns an Enumerable which can change it's elements afterwards
|
float maxLength = MaxValue ?? value.Max();
|
||||||
RemoveRange(Children.Where((_, index) => index >= value.Count()).ToList(), true);
|
|
||||||
|
bars.SetLengths(value.Select(v => maxLength == 0 ? 0 : Math.Max(0f, v / maxLength)).ToArray());
|
||||||
|
|
||||||
|
animationStartTime = Clock.CurrentTime;
|
||||||
|
animationComplete = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double animationStartTime;
|
||||||
|
private bool animationComplete;
|
||||||
|
|
||||||
|
private IShader shader = null!;
|
||||||
|
private Texture texture = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IRenderer renderer, ShaderManager shaders)
|
||||||
|
{
|
||||||
|
texture = renderer.WhitePixel;
|
||||||
|
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (!bars.Any)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double currentTime = Clock.CurrentTime;
|
||||||
|
|
||||||
|
if (currentTime < animationStartTime + resize_duration)
|
||||||
|
{
|
||||||
|
bars.Animate(animationStartTime, currentTime);
|
||||||
|
Invalidate(Invalidation.DrawNode);
|
||||||
|
}
|
||||||
|
else if (!animationComplete)
|
||||||
|
{
|
||||||
|
bars.FinishAnimation();
|
||||||
|
Invalidate(Invalidation.DrawNode);
|
||||||
|
|
||||||
|
animationComplete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DrawNode CreateDrawNode() => new BarGraphDrawNode(this);
|
||||||
|
|
||||||
|
private class BarGraphDrawNode : DrawNode
|
||||||
|
{
|
||||||
|
public new BarGraph Source => (BarGraph)base.Source;
|
||||||
|
|
||||||
|
public BarGraphDrawNode(BarGraph source)
|
||||||
|
: base(source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private IShader shader = null!;
|
||||||
|
private Texture texture = null!;
|
||||||
|
private Vector2 drawSize;
|
||||||
|
private BarDirection direction;
|
||||||
|
private float barBreadth;
|
||||||
|
|
||||||
|
private readonly List<float> lengths = new List<float>();
|
||||||
|
|
||||||
|
public override void ApplyState()
|
||||||
|
{
|
||||||
|
base.ApplyState();
|
||||||
|
|
||||||
|
shader = Source.shader;
|
||||||
|
texture = Source.texture;
|
||||||
|
drawSize = Source.DrawSize;
|
||||||
|
direction = Source.direction;
|
||||||
|
barBreadth = Source.bars.Breadth;
|
||||||
|
|
||||||
|
lengths.Clear();
|
||||||
|
lengths.AddRange(Source.bars.InstantaneousLengths);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(IRenderer renderer)
|
||||||
|
{
|
||||||
|
base.Draw(renderer);
|
||||||
|
|
||||||
|
shader.Bind();
|
||||||
|
|
||||||
|
for (int i = 0; i < lengths.Count; i++)
|
||||||
|
{
|
||||||
|
float barHeight = drawSize.Y * ((direction == BarDirection.TopToBottom || direction == BarDirection.BottomToTop) ? lengths[i] : barBreadth);
|
||||||
|
float barWidth = drawSize.X * ((direction == BarDirection.LeftToRight || direction == BarDirection.RightToLeft) ? lengths[i] : barBreadth);
|
||||||
|
|
||||||
|
Vector2 topLeft;
|
||||||
|
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case BarDirection.LeftToRight:
|
||||||
|
topLeft = new Vector2(0, i * barHeight);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BarDirection.RightToLeft:
|
||||||
|
topLeft = new Vector2(drawSize.X - barWidth, i * barHeight);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BarDirection.TopToBottom:
|
||||||
|
topLeft = new Vector2(i * barWidth, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BarDirection.BottomToTop:
|
||||||
|
topLeft = new Vector2(i * barWidth, drawSize.Y - barHeight);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.DrawQuad(
|
||||||
|
texture,
|
||||||
|
new Quad(
|
||||||
|
Vector2Extensions.Transform(topLeft, DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(topLeft + new Vector2(barWidth, 0), DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(topLeft + new Vector2(0, barHeight), DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(topLeft + new Vector2(barWidth, barHeight), DrawInfo.Matrix)
|
||||||
|
),
|
||||||
|
DrawColourInfo.Colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
shader.Unbind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarsInfo
|
||||||
|
{
|
||||||
|
public bool Any => Count > 0;
|
||||||
|
|
||||||
|
public int Count { get; private set; }
|
||||||
|
|
||||||
|
public float Breadth { get; private set; }
|
||||||
|
|
||||||
|
public List<float> InstantaneousLengths { get; } = new List<float>();
|
||||||
|
|
||||||
|
private readonly List<float> initialLengths = new List<float>();
|
||||||
|
private readonly List<float> finalLengths = new List<float>();
|
||||||
|
|
||||||
|
public void Clear() => SetLengths(Array.Empty<float>());
|
||||||
|
|
||||||
|
public void SetLengths(float[] newLengths)
|
||||||
|
{
|
||||||
|
int newCount = newLengths.Length;
|
||||||
|
|
||||||
|
for (int i = 0; i < newCount; i++)
|
||||||
|
{
|
||||||
|
// If we have an old bar at this index - change it's length
|
||||||
|
if (i < Count)
|
||||||
|
{
|
||||||
|
initialLengths[i] = finalLengths[i];
|
||||||
|
finalLengths[i] = newLengths[i];
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If exceeded old bars count - add new one
|
||||||
|
initialLengths.Add(0);
|
||||||
|
finalLengths.Add(newLengths[i]);
|
||||||
|
InstantaneousLengths.Add(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove excessive bars
|
||||||
|
if (Count > newCount)
|
||||||
|
{
|
||||||
|
int barsToRemove = Count - newCount;
|
||||||
|
|
||||||
|
initialLengths.RemoveRange(newCount, barsToRemove);
|
||||||
|
finalLengths.RemoveRange(newCount, barsToRemove);
|
||||||
|
InstantaneousLengths.RemoveRange(newCount, barsToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
Count = newCount;
|
||||||
|
Breadth = Count == 0 ? 0 : (1f / Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Animate(double animationStartTime, double currentTime)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
InstantaneousLengths[i] = Interpolation.ValueAt(currentTime, initialLengths[i], finalLengths[i], animationStartTime, animationStartTime + resize_duration, easing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FinishAnimation()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
InstantaneousLengths[i] = finalLengths[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,11 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
|||||||
// the dropdown. BASS does not give us a simple mechanism to select
|
// the dropdown. BASS does not give us a simple mechanism to select
|
||||||
// specific audio devices in such a case anyways. Such
|
// specific audio devices in such a case anyways. Such
|
||||||
// functionality would require involved OS-specific code.
|
// functionality would require involved OS-specific code.
|
||||||
dropdown.Items = deviceItems.Distinct().ToList();
|
dropdown.Items = deviceItems
|
||||||
|
// Dropdown doesn't like null items. Somehow we are seeing some arrive here (see https://github.com/ppy/osu/issues/21271)
|
||||||
|
.Where(i => i != null)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
Loading…
Reference in New Issue
Block a user