A game framework written with osu! in mind.
at master 106 lines 3.8 kB view raw
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 osuTK; 5using System; 6using osu.Framework.Graphics.OpenGL.Vertices; 7using osu.Framework.Graphics.Primitives; 8using osu.Framework.Graphics.Textures; 9using osu.Framework.Graphics.OpenGL; 10using osu.Framework.Graphics.OpenGL.Textures; 11 12namespace osu.Framework.Graphics.Sprites 13{ 14 /// <summary> 15 /// Draw node containing all necessary information to draw a <see cref="Sprite"/>. 16 /// </summary> 17 public class SpriteDrawNode : TexturedShaderDrawNode 18 { 19 protected Texture Texture { get; private set; } 20 protected Quad ScreenSpaceDrawQuad { get; private set; } 21 22 protected RectangleF DrawRectangle { get; private set; } 23 protected Vector2 InflationAmount { get; private set; } 24 25 protected RectangleF TextureCoords { get; private set; } 26 27 protected new Sprite Source => (Sprite)base.Source; 28 29 protected Quad ConservativeScreenSpaceDrawQuad; 30 31 private bool hasOpaqueInterior; 32 33 public SpriteDrawNode(Sprite source) 34 : base(source) 35 { 36 } 37 38 public override void ApplyState() 39 { 40 base.ApplyState(); 41 42 Texture = Source.Texture; 43 ScreenSpaceDrawQuad = Source.ScreenSpaceDrawQuad; 44 DrawRectangle = Source.DrawRectangle; 45 InflationAmount = Source.InflationAmount; 46 47 TextureCoords = Source.DrawRectangle.RelativeIn(Source.DrawTextureRectangle); 48 if (Texture != null) 49 TextureCoords *= new Vector2(Texture.DisplayWidth, Texture.DisplayHeight); 50 51 hasOpaqueInterior = DrawColourInfo.Colour.MinAlpha == 1 52 && DrawColourInfo.Blending == BlendingParameters.Mixture 53 && DrawColourInfo.Colour.HasSingleColour; 54 55 if (CanDrawOpaqueInterior) 56 ConservativeScreenSpaceDrawQuad = Source.ConservativeScreenSpaceDrawQuad; 57 } 58 59 protected virtual void Blit(Action<TexturedVertex2D> vertexAction) 60 { 61 DrawQuad(Texture, ScreenSpaceDrawQuad, DrawColourInfo.Colour, null, vertexAction, 62 new Vector2(InflationAmount.X / DrawRectangle.Width, InflationAmount.Y / DrawRectangle.Height), 63 null, TextureCoords); 64 } 65 66 protected virtual void BlitOpaqueInterior(Action<TexturedVertex2D> vertexAction) 67 { 68 if (GLWrapper.IsMaskingActive) 69 DrawClipped(ref ConservativeScreenSpaceDrawQuad, Texture, DrawColourInfo.Colour, vertexAction: vertexAction); 70 else 71 DrawQuad(Texture, ConservativeScreenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction, textureCoords: TextureCoords); 72 } 73 74 public override void Draw(Action<TexturedVertex2D> vertexAction) 75 { 76 base.Draw(vertexAction); 77 78 if (Texture?.Available != true) 79 return; 80 81 Shader.Bind(); 82 83 Blit(vertexAction); 84 85 Shader.Unbind(); 86 } 87 88 protected override bool RequiresRoundedShader => base.RequiresRoundedShader || InflationAmount != Vector2.Zero; 89 90 protected override void DrawOpaqueInterior(Action<TexturedVertex2D> vertexAction) 91 { 92 base.DrawOpaqueInterior(vertexAction); 93 94 if (Texture?.Available != true) 95 return; 96 97 TextureShader.Bind(); 98 99 BlitOpaqueInterior(vertexAction); 100 101 TextureShader.Unbind(); 102 } 103 104 protected internal override bool CanDrawOpaqueInterior => Texture?.Available == true && Texture.Opacity == Opacity.Opaque && hasOpaqueInterior; 105 } 106}