Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draw slide chevrons using SDF shader #639

Merged
merged 13 commits into from
Nov 15, 2024
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Sentakki.Objects;
using osu.Game.Rulesets.Sentakki.Objects.Drawables;
using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides;
using osu.Game.Tests.Visual;
using osuTK;
using osuTK.Graphics;

namespace osu.Game.Rulesets.Sentakki.Tests.Graphics
{
[TestFixture]
public partial class TestSceneChevronVisual : OsuGridTestScene
{
protected override Ruleset CreateRuleset() => new SentakkiRuleset();
public TestSceneChevronVisual() : base(1, 2)
{
Cell(0).Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White
});
Cell(1).Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White
});
Cell(0).Add(new SlideChevron());
Cell(1).Add(new DrawableChevron()
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(80, 62.5f),
Thickness = 7
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Pooling;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Sentakki.Objects;
using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides;
using osu.Game.Rulesets.Sentakki.UI;
using osu.Game.Rulesets.Sentakki.UI.Components;
using osu.Game.Tests.Visual;
using osuTK;
using osuTK.Graphics;

namespace osu.Game.Rulesets.Sentakki.Tests.Graphics
{
[TestFixture]
public partial class TestSceneFanChevronVisual : OsuGridTestScene
{
protected override Ruleset CreateRuleset() => new SentakkiRuleset();
private readonly SlideVisual slide;

private readonly Container fanChevContainer;

[Cached]
private readonly DrawablePool<SlideChevron> chevronPool;
public TestSceneFanChevronVisual() : base(1, 2)
{
Cell(0).Add(chevronPool = new DrawablePool<SlideChevron>(62));
Cell(0).Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White
});
Cell(0).Add(new SentakkiRing
{
RelativeSizeAxes = Axes.None,
Size = new Vector2(SentakkiPlayfield.RINGSIZE)
});
Cell(0).Add(slide = new SlideVisual());
Cell(0).Add(new SentakkiRing
{
RelativeSizeAxes = Axes.None,
Size = new Vector2(SentakkiPlayfield.RINGSIZE)
});
Cell(1).Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White
});
Cell(1).Add(new SentakkiRing
{
RelativeSizeAxes = Axes.None,
Size = new Vector2(SentakkiPlayfield.RINGSIZE)
});
float rot = SentakkiExtensions.GetRotationForLane(4);
Cell(1).Add(fanChevContainer = new Container()
{
RelativeSizeAxes = Axes.None,
Size = new Vector2(600),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Rotation = rot,
});

Vector2 lineStart = SentakkiExtensions.GetPositionAlongLane(SentakkiPlayfield.INTERSECTDISTANCE, 0);
Vector2 middleLineEnd = SentakkiExtensions.GetPositionAlongLane(SentakkiPlayfield.INTERSECTDISTANCE, 4);
Vector2 middleLineDelta = middleLineEnd - lineStart;

for (int i = 0; i < 11; ++i)
{
float progress = (i + 2f) / 12f;

float scale = progress - (2f / 12);
var middlePosition = lineStart + (middleLineDelta * progress);

float t = 6.5f + (2.5f * scale);

float chevWidth = MathF.Abs(lineStart.X - middlePosition.X);

(float sin, float cos) = MathF.SinCos((-135 + 90f) / 180f * MathF.PI);

Vector2 secondPoint = new Vector2(sin, -cos) * chevWidth;
Vector2 one = new Vector2(chevWidth, 0);

var middle = (one + secondPoint) * 0.5f;
float h = (middle - Vector2.Zero).Length + (t * 3);

float w = (secondPoint - one).Length;

const float safe_space_ratio = (570 / 600f) * 600;

float y = safe_space_ratio * scale;

var fanChev = new DrawableChevron()
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = w + 30,
Height = h + 30,
Thickness = t,
Y = -y + 300 - 50,
FanChevron = true,
};

fanChevContainer.Add(fanChev);
}
}

protected override void LoadComplete()
{
base.LoadComplete();
slide.Path = SlidePaths.CreateSlidePath(new SlideBodyPart(SlidePaths.PathShapes.Fan, 4, false));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,9 @@ public partial class TestSceneAllSlides : OsuTestScene
[Cached]
private readonly DrawablePool<SlideChevron> chevronPool;

[Cached]
private readonly SlideFanChevrons fanChevrons;

public TestSceneAllSlides()
{
Add(chevronPool = new DrawablePool<SlideChevron>(62));
Add(fanChevrons = new SlideFanChevrons());

Add(new SentakkiRing
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,9 @@ public partial class TestSceneCircleChaining : OsuTestScene
[Cached]
private readonly DrawablePool<SlideChevron> chevronPool = null!;

[Cached]
private readonly SlideFanChevrons fanChevrons = null!;

public TestSceneCircleChaining()
{
Add(chevronPool = new DrawablePool<SlideChevron>(62));
Add(fanChevrons = new SlideFanChevrons());

Add(new SentakkiRing
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Pooling;
using osu.Game.Rulesets.Sentakki.Objects;
using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides;
using osu.Game.Rulesets.Sentakki.UI;
Expand All @@ -19,13 +20,14 @@ public partial class TestSceneFanSlide : OsuTestScene
protected int EndPath;

[Cached]
private readonly SlideFanChevrons fanChevrons;
private readonly DrawablePool<SlideChevron> chevronPool = null!;


private readonly SlideVisual slide;

public TestSceneFanSlide()
{
Add(fanChevrons = new SlideFanChevrons());
Add(chevronPool = new DrawablePool<SlideChevron>(62));

Add(new SentakkiRing
{
Expand All @@ -38,6 +40,7 @@ public TestSceneFanSlide()
AddSliderStep("Progress", 0.0f, 1.0f, 0.0f, p =>
{
slide.Progress = p;
slide.UpdateChevronVisibility();
});

AddSliderStep("Rotation", 0.0f, 360f, 22.5f, p =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,9 @@ public abstract partial class TestSceneSlide : OsuTestScene
[Cached]
private readonly DrawablePool<SlideChevron> chevronPool;

[Cached]
private readonly SlideFanChevrons fanChevrons;

protected TestSceneSlide()
{
Add(chevronPool = new DrawablePool<SlideChevron>(62));
Add(fanChevrons = new SlideFanChevrons());

Add(new SentakkiRing
{
Expand All @@ -62,6 +58,7 @@ protected TestSceneSlide()
AddSliderStep("Progress", 0.0f, 1.0f, 0.0f, p =>
{
slide.Progress = p;
slide.UpdateChevronVisibility();
});

AddToggleStep("Mirrored", b =>
Expand Down
5 changes: 3 additions & 2 deletions osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneSlideFan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Pooling;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Sentakki.Objects;
Expand All @@ -27,7 +28,7 @@ public partial class TestSceneSlideFan : OsuTestScene
private int depthIndex;

[Cached]
private readonly SlideFanChevrons fanChevrons;
private readonly DrawablePool<SlideChevron> chevronPool = null!;

public TestSceneSlideFan()
{
Expand All @@ -39,7 +40,7 @@ public TestSceneSlideFan()
Rotation = -22.5f
});

Add(fanChevrons = new SlideFanChevrons());
Add(chevronPool = new DrawablePool<SlideChevron>(62));

AddStep("Miss Single", () => testSingle(2000));
AddStep("Hit Single", () => testSingle(2000, true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ public partial class TestSceneSlideNote : OsuTestScene
[Cached]
private readonly DrawablePool<SlideChevron> chevronPool;

[Cached]
private readonly SlideFanChevrons fanChevrons;

public TestSceneSlideNote()
{
base.Content.Add(content = new SentakkiInputManager(new SentakkiRuleset().RulesetInfo));
Expand All @@ -44,7 +41,6 @@ public TestSceneSlideNote()
});

Add(chevronPool = new DrawablePool<SlideChevron>(62));
Add(fanChevrons = new SlideFanChevrons());

AddStep("Miss Single", () => testSingle(2000));
AddStep("Hit Single", () => testSingle(2000, true));
Expand Down
Loading
Loading