A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Collections.Generic;
6using osu.Framework.Graphics.Colour;
7using osu.Framework.Graphics.OpenGL.Vertices;
8using osu.Framework.Graphics.Primitives;
9using osu.Framework.Graphics.Textures;
10using osuTK;
11using osuTK.Graphics;
12
13namespace osu.Framework.Graphics.Sprites
14{
15 public partial class SpriteText
16 {
17 internal class SpriteTextDrawNode : TexturedShaderDrawNode
18 {
19 protected new SpriteText Source => (SpriteText)base.Source;
20
21 private bool shadow;
22 private ColourInfo shadowColour;
23 private Vector2 shadowOffset;
24
25 private readonly List<ScreenSpaceCharacterPart> parts = new List<ScreenSpaceCharacterPart>();
26
27 public SpriteTextDrawNode(SpriteText source)
28 : base(source)
29 {
30 }
31
32 public override void ApplyState()
33 {
34 base.ApplyState();
35
36 parts.Clear();
37 parts.AddRange(Source.screenSpaceCharacters);
38 shadow = Source.Shadow;
39
40 if (shadow)
41 {
42 shadowColour = Source.ShadowColour;
43 shadowOffset = Source.premultipliedShadowOffset;
44 }
45 }
46
47 public override void Draw(Action<TexturedVertex2D> vertexAction)
48 {
49 base.Draw(vertexAction);
50
51 Shader.Bind();
52
53 var avgColour = (Color4)DrawColourInfo.Colour.AverageColour;
54 float shadowAlpha = MathF.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2);
55
56 //adjust shadow alpha based on highest component intensity to avoid muddy display of darker text.
57 //squared result for quadratic fall-off seems to give the best result.
58 var finalShadowColour = DrawColourInfo.Colour;
59 finalShadowColour.ApplyChild(shadowColour.MultiplyAlpha(shadowAlpha));
60
61 for (int i = 0; i < parts.Count; i++)
62 {
63 if (shadow)
64 {
65 var shadowQuad = parts[i].DrawQuad;
66
67 DrawQuad(parts[i].Texture,
68 new Quad(
69 shadowQuad.TopLeft + shadowOffset,
70 shadowQuad.TopRight + shadowOffset,
71 shadowQuad.BottomLeft + shadowOffset,
72 shadowQuad.BottomRight + shadowOffset),
73 finalShadowColour, vertexAction: vertexAction, inflationPercentage: parts[i].InflationPercentage);
74 }
75
76 DrawQuad(parts[i].Texture, parts[i].DrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction, inflationPercentage: parts[i].InflationPercentage);
77 }
78
79 Shader.Unbind();
80 }
81 }
82
83 /// <summary>
84 /// A character of a <see cref="SpriteText"/> provided with screen space draw coordinates.
85 /// </summary>
86 internal struct ScreenSpaceCharacterPart
87 {
88 /// <summary>
89 /// The screen-space quad for the character to be drawn in.
90 /// </summary>
91 public Quad DrawQuad;
92
93 /// <summary>
94 /// Extra padding for the character's texture.
95 /// </summary>
96 public Vector2 InflationPercentage;
97
98 /// <summary>
99 /// The texture to draw the character with.
100 /// </summary>
101 public Texture Texture;
102 }
103 }
104}