Skip to content

Commit

Permalink
Merge pull request #59 from andy840119/fix-masking-issue
Browse files Browse the repository at this point in the history
Implement masking container.
  • Loading branch information
andy840119 authored Oct 3, 2021
2 parents 850909d + bce6006 commit ee9c7a0
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osuTK;
using osuTK.Graphics;

namespace osu.Framework.Font.Tests.Visual.Containers
{
public class MaskingContainerTestScene : BackgroundGridTestSample
{
private readonly MaskingContainer<Drawable> maskingContainer;

public MaskingContainerTestScene()
{
Child = maskingContainer = new MaskingContainer<Drawable>
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200),
Children = new Drawable[]
{
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(250),
Colour = Colour4.Red
},
new DraggableCircle
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = Color4.Blue,
Size = new Vector2(100)
}
}
};
}

[TestCase(Edges.None)]
[TestCase(Edges.Left)]
[TestCase(Edges.Right)]
[TestCase(Edges.Top)]
[TestCase(Edges.Bottom)]
[TestCase(Edges.Vertical)]
[TestCase(Edges.Horizontal)]
[TestCase(Edges.Left | Edges.Top)]
public void TestMasking(Edges edges)
{
AddStep("apply masking", () =>
{
maskingContainer.MaskingEdges = edges;
});
}
}
}
107 changes: 107 additions & 0 deletions osu.Framework.Font/Graphics/Containers/MaskingContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using osu.Framework.Graphics.OpenGL;
using osu.Framework.Graphics.OpenGL.Vertices;
using osu.Framework.Graphics.Primitives;

namespace osu.Framework.Graphics.Containers
{
/// <summary>
/// It's a container that only masking target direction.
/// </summary>
/// <typeparam name="T"></typeparam>
public class MaskingContainer<T> : Container<T> where T : Drawable
{
/// <summary>
/// If enabled, only the portion of children that falls within this <see cref="Container"/>'s
/// shape is drawn to the screen.
/// </summary>
public new bool Masking
{
get => throw new InvalidOperationException("Should not get masking in here.");
set => throw new InvalidOperationException("Should not assign masking in here.");
}

private Edges maskingEdges = Edges.None;

public Edges MaskingEdges
{
get => maskingEdges;
set
{
if (maskingEdges == value)
return;

maskingEdges = value;
Invalidate(Invalidation.DrawNode);
}
}

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

protected class MaskingCompositeDrawableDrawNode : CompositeDrawableDrawNode
{
protected new MaskingContainer<T> Source => (MaskingContainer<T>)base.Source;

/// <summary>
/// Information about how masking of children should be carried out.
/// </summary>
private MaskingInfo? maskingInfo;

public MaskingCompositeDrawableDrawNode(CompositeDrawable source)
: base(source)
{
}

public override void ApplyState()
{
base.ApplyState();

maskingInfo = Source.MaskingEdges == Edges.None
? (MaskingInfo?)null
: new MaskingInfo
{
ScreenSpaceAABB = generateMasking(Source.ScreenSpaceDrawQuad.AABB, Source.MaskingEdges),
};
}

private static RectangleI generateMasking(RectangleI source, Edges edges)
{
return source.Inflate(getExtendSize(Edges.Left), getExtendSize(Edges.Right), getExtendSize(Edges.Top), getExtendSize(Edges.Bottom));

int getExtendSize(Edges flag)
{
const int extend_size = 1000;
return edges.HasFlag(flag) ? 0 : extend_size;
}
}

public override void Draw(Action<TexturedVertex2D> vertexAction)
{
// will not working if not adding masking info into here.
if (maskingInfo != null)
GLWrapper.PushMaskingInfo(maskingInfo.Value);

base.Draw(vertexAction);

if (maskingInfo != null)
GLWrapper.PopMaskingInfo();
}

protected override void DrawChildrenOpaqueInteriors(DepthValue depthValue, Action<TexturedVertex2D> vertexAction)
{
// will have black border if not adding masking info into here.
if (maskingInfo != null)
GLWrapper.PushMaskingInfo(maskingInfo.Value);

base.DrawChildrenOpaqueInteriors(depthValue, vertexAction);

if (maskingInfo != null)
GLWrapper.PopMaskingInfo();
}
}
}
}
13 changes: 6 additions & 7 deletions osu.Framework.Font/Graphics/Sprites/KaraokeSpriteText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ public class KaraokeSpriteText : KaraokeSpriteText<LyricSpriteText>

public partial class KaraokeSpriteText<T> : CompositeDrawable, IMultiShaderBufferedDrawable, IHasRuby, IHasRomaji where T : LyricSpriteText, new()
{
private readonly Container frontLyricTextContainer;
private readonly MaskingContainer<T> frontLyricTextContainer;
private readonly T frontLyricText;

private readonly Container backLyricTextContainer;
private readonly MaskingContainer<T> backLyricTextContainer;
private readonly T backLyricText;

public IShader TextureShader { get; private set; }
Expand All @@ -34,23 +34,22 @@ public KaraokeSpriteText()
AutoSizeAxes = Axes.Both;
InternalChildren = new Drawable[]
{
backLyricTextContainer = new Container
backLyricTextContainer = new MaskingContainer<T>
{
AutoSizeAxes = Axes.Y,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Masking = true,
MaskingEdges = Edges.Left,
Child = backLyricText = new T
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
}
},
frontLyricTextContainer = new Container
frontLyricTextContainer = new MaskingContainer<T>
{
AutoSizeAxes = Axes.Y,

Masking = true,
MaskingEdges = Edges.Right,
Child = frontLyricText = new T(),
}
};
Expand Down

0 comments on commit ee9c7a0

Please sign in to comment.