Skip to content

Commit

Permalink
Merge pull request #594 from LumpBloom7/NoteShader
Browse files Browse the repository at this point in the history
Use custom shader for LanedNotes
  • Loading branch information
LumpBloom7 authored Jul 14, 2024
2 parents 09d02a4 + 9eb5917 commit eaa6723
Show file tree
Hide file tree
Showing 16 changed files with 420 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public partial class TestSceneBreakNote : OsuTestScene
private readonly Container content;
protected override Container<Drawable> Content => content;

protected override Ruleset CreateRuleset() => new SentakkiRuleset();
private int depthIndex;

public TestSceneBreakNote()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public partial class TestSceneHoldNote : OsuTestScene
{
private readonly Container content;
protected override Container<Drawable> Content => content;
protected override Ruleset CreateRuleset() => new SentakkiRuleset();

private int depthIndex;

Expand Down
2 changes: 2 additions & 0 deletions osu.Game.Rulesets.Sentakki.Tests/Objects/TestSceneTapNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public partial class TestSceneTapNote : OsuTestScene
private readonly Container content;
protected override Container<Drawable> Content => content;

protected override Ruleset CreateRuleset() => new SentakkiRuleset();

private int depthIndex;

public TestSceneTapNote()
Expand Down
14 changes: 7 additions & 7 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/DotPiece.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces
{
public partial class DotPiece : CompositeDrawable
{
public DotPiece(float outlineThickness = 2, bool squared = false)
: this(new Vector2(SentakkiPlayfield.DOTSIZE), outlineThickness, squared)
public DotPiece(float outlineThickness = 2)
: this(new Vector2(SentakkiPlayfield.DOTSIZE), outlineThickness)
{
}

public DotPiece(Vector2 size, float outlineThickness = 2, bool squared = false)
public DotPiece(Vector2 size, float outlineThickness = 2)
{
Size = size;
Vector2 innerDotSize = size - new Vector2(outlineThickness * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Masking = true;
CornerExponent = squared ? 2.5f : 2f;
CornerRadius = Math.Min(size.X, size.Y) / (squared ? 4 : 2);
CornerExponent = 2f;
CornerRadius = Math.Min(size.X, size.Y) / 2;
InternalChildren = new Drawable[]
{
new Box
Expand All @@ -33,8 +33,8 @@ public DotPiece(Vector2 size, float outlineThickness = 2, bool squared = false)
},
new Container
{
CornerExponent = squared ? 2.5f : 2f,
CornerRadius = Math.Min(innerDotSize.X, innerDotSize.Y) / (squared ? 4 : 2),
CornerExponent = 2f,
CornerRadius = Math.Min(innerDotSize.X, innerDotSize.Y) / 2,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = innerDotSize,
Expand Down
17 changes: 6 additions & 11 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/HoldBody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,12 @@ public HoldBody()
Origin = Anchor.TopCentre;
InternalChildren = new Drawable[]
{
new NoteRingPiece(),
new DotPiece(squared: true)
{
Rotation = 45,
Anchor = Anchor.BottomCentre,
},
new DotPiece(squared: true)
{
Rotation = 45,
Anchor = Anchor.TopCentre,
},
new Container{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Child = new NoteRingPiece(true)
}
};
}

Expand Down
157 changes: 157 additions & 0 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/LaneNoteVisual.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System.Runtime.InteropServices;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Shaders.Types;
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK;

namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces;

public enum NoteShape
{
Ring,
Hex,
Star
}

public partial class LaneNoteVisual : Sprite, ITexturedShaderDrawable
{
public NoteShape Shape { get; init; } = NoteShape.Ring;
private float thickness = 0.25f;
public float Thickness
{
get => thickness;
set
{
if (thickness == value)
return;
thickness = value;
Invalidate(Invalidation.DrawNode);
}
}

private float shadowRadius = 15f / 105f;
public float ShadowRadius
{
get => shadowRadius;
set
{
if (shadowRadius == value)
return;
shadowRadius = value;
Invalidate(Invalidation.DrawNode);
}
}

private bool glow;
public bool Glow
{
get => glow;
set
{
if (glow == value)
return;
glow = value;
Invalidate(Invalidation.DrawNode);
}
}

public new IShader TextureShader { get; private set; } = null!;

protected override DrawNode CreateDrawNode() => new LaneNoteVisualDrawNode(this);

private BindableBool exBindable = new BindableBool();

private string fragmentShaderFor(NoteShape shape)
{
switch (shape)
{
case NoteShape.Ring:
default:
return "ringNote";
case NoteShape.Hex:
return "hexNote";
case NoteShape.Star:
return "starNote";
}
}

[BackgroundDependencyLoader]
private void load(ShaderManager shaders, IRenderer renderer, DrawableHitObject? hitObject)
{
TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, fragmentShaderFor(Shape));
Texture = renderer.WhitePixel;

if (hitObject is null)
return;

// Bind exnote
exBindable.BindTo(((DrawableSentakkiHitObject)hitObject).ExBindable);
exBindable.BindValueChanged(b => Glow = b.NewValue, true);
}

private partial class LaneNoteVisualDrawNode : SpriteDrawNode
{
protected new LaneNoteVisual Source => (LaneNoteVisual)base.Source;
protected override bool CanDrawOpaqueInterior => false;
private IUniformBuffer<ShapeParameters>? shapeParameters;

private float thickness;
private Vector2 size;
private bool glow;
private float shadowRadius;

public LaneNoteVisualDrawNode(LaneNoteVisual source)
: base(source)
{
}

public override void ApplyState()
{
base.ApplyState();
thickness = Source.Thickness;
size = Source.DrawSize;
shadowRadius = Source.shadowRadius;
glow = Source.Glow;
}

protected override void BindUniformResources(IShader shader, IRenderer renderer)
{
base.BindUniformResources(shader, renderer);

shapeParameters ??= renderer.CreateUniformBuffer<ShapeParameters>();

shapeParameters.Data = shapeParameters.Data with
{
Thickness = thickness,
Size = size,
ShadowRadius = shadowRadius,
Glow = glow,
};

shader.BindUniformBlock("m_shapeParameters", shapeParameters);
}

protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
shapeParameters?.Dispose();
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
private record struct ShapeParameters
{
public UniformFloat Thickness;
public UniformPadding4 _;
public UniformVector2 Size;
public UniformFloat ShadowRadius;
public UniformBool Glow;

public UniformPadding8 __;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@ namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces
public partial class NoteRingPiece : CompositeDrawable
{
private const float base_circle_size = 75;
private const float drawable_size = base_circle_size + 30; // 30 units for shadow

public NoteRingPiece()
public NoteRingPiece(bool hex = false)
{
Padding = new MarginPadding(-base_circle_size / 2);
Padding = new MarginPadding(-drawable_size / 2);
RelativeSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
InternalChildren = new Drawable[]
{
new ShadowPiece(),
new RingPiece(),
new LaneNoteVisual(){
RelativeSizeAxes = Axes.Both,
Shape = hex ? NoteShape.Hex : NoteShape.Ring,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
};
}
}
Expand Down
67 changes: 0 additions & 67 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/Pieces/ShadowPiece.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,51 +1,32 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK.Graphics;

namespace osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces.Slides
{
public partial class StarPiece : CompositeDrawable
{
private Sprite glowTexture = null!;

private Bindable<bool> ExBindable = new Bindable<bool>();

private const float base_circle_size = 75;
private const float drawable_size = base_circle_size + 30; // 30 units for shadow
public StarPiece()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Padding = new MarginPadding(-drawable_size / 2);
}

[BackgroundDependencyLoader]
private void load(TextureStore textures, DrawableHitObject? hitObject)
private void load()
{
AddRangeInternal(new Drawable[]{
glowTexture = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = textures.Get("starGlow"),
Colour = Color4.Black
},
new Sprite
{
new LaneNoteVisual{
RelativeSizeAxes = Axes.Both,

Shape = NoteShape.Star,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = textures.Get("star"),
}
});

if (hitObject is null)
return;

// Bind exnote
ExBindable.BindTo(((DrawableSentakkiHitObject)hitObject).ExBindable);
ExBindable.BindValueChanged(v => glowTexture.Colour = v.NewValue ? Color4.White : Color4.Black, true);
}
}
}
Loading

0 comments on commit eaa6723

Please sign in to comment.