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 osu.Framework.Allocation;
6using osu.Framework.Graphics;
7using osu.Framework.Graphics.Containers;
8using osu.Framework.Graphics.OpenGL.Vertices;
9using osu.Framework.Graphics.Sprites;
10using osu.Framework.Graphics.Textures;
11using osu.Framework.Testing;
12using osuTK.Graphics.ES30;
13using SixLabors.ImageSharp;
14using SixLabors.ImageSharp.PixelFormats;
15
16namespace osu.Framework.Tests.Visual.Sprites
17{
18 public class TestSceneTextureUnit : GridTestScene
19 {
20 public TestSceneTextureUnit()
21 : base(2, 2)
22 {
23 Cell(0, 0).Child = createTest(TextureUnit.Texture0, "white");
24 Cell(0, 1).Child = createTest(TextureUnit.Texture1, "red");
25 Cell(1, 0).Child = createTest(TextureUnit.Texture2, "green");
26 Cell(1, 1).Child = createTest(TextureUnit.Texture3, "blue");
27 }
28
29 private Drawable createTest(TextureUnit unit, string expectedColour) => new Container
30 {
31 RelativeSizeAxes = Axes.Both,
32 Children = new Drawable[]
33 {
34 new SpriteText
35 {
36 Anchor = Anchor.TopCentre,
37 Origin = Anchor.TopCentre,
38 Text = $"Unit {unit - TextureUnit.Texture0} ({expectedColour})"
39 },
40 new Container
41 {
42 RelativeSizeAxes = Axes.Both,
43 Padding = new MarginPadding { Top = 20 },
44 Child = new TestSprite(unit)
45 {
46 Anchor = Anchor.Centre,
47 Origin = Anchor.Centre,
48 RelativeSizeAxes = Axes.Both,
49 FillMode = FillMode.Fit
50 }
51 }
52 }
53 };
54
55 private class TestSprite : Sprite
56 {
57 private readonly TextureUnit unit;
58
59 private Texture redTex;
60 private Texture greenTex;
61 private Texture blueTex;
62
63 public TestSprite(TextureUnit unit)
64 {
65 this.unit = unit;
66 }
67
68 [BackgroundDependencyLoader]
69 private void load()
70 {
71 // 0 -> White, 1 -> Red, 2 -> Green, 3 -> Blue
72 Texture = createTexture(new Rgba32(255, 255, 255, 255));
73 redTex = createTexture(new Rgba32(255, 0, 0, 255));
74 greenTex = createTexture(new Rgba32(0, 255, 0, 255));
75 blueTex = createTexture(new Rgba32(0, 0, 255, 255));
76 }
77
78 private Texture createTexture(Rgba32 pixel)
79 {
80 var texData = new Image<Rgba32>(32, 32);
81
82 for (int x = 0; x < texData.Width; x++)
83 {
84 for (int y = 0; y < texData.Height; y++)
85 texData[x, y] = pixel;
86 }
87
88 var tex = new Texture(texData.Width, texData.Height, true);
89 tex.SetData(new TextureUpload(texData));
90
91 return tex;
92 }
93
94 protected override DrawNode CreateDrawNode() => new TestBoxDrawNode(this, unit);
95
96 private class TestBoxDrawNode : SpriteDrawNode
97 {
98 protected new TestSprite Source => (TestSprite)base.Source;
99
100 private readonly TextureUnit unit;
101
102 private Texture redTex;
103 private Texture greenTex;
104 private Texture blueTex;
105
106 public TestBoxDrawNode(TestSprite source, TextureUnit unit)
107 : base(source)
108 {
109 this.unit = unit;
110 }
111
112 public override void ApplyState()
113 {
114 base.ApplyState();
115
116 redTex = Source.redTex;
117 greenTex = Source.greenTex;
118 blueTex = Source.blueTex;
119 }
120
121 public override void Draw(Action<TexturedVertex2D> vertexAction)
122 {
123 redTex.TextureGL.Bind(TextureUnit.Texture1);
124 greenTex.TextureGL.Bind(TextureUnit.Texture2);
125 blueTex.TextureGL.Bind(TextureUnit.Texture3);
126
127 int unitId = unit - TextureUnit.Texture0;
128 Shader.GetUniform<int>("m_Sampler").UpdateValue(ref unitId);
129
130 base.Draw(vertexAction);
131
132 unitId = 0;
133 Shader.GetUniform<int>("m_Sampler").UpdateValue(ref unitId);
134 }
135
136 protected internal override bool CanDrawOpaqueInterior => false;
137 }
138 }
139 }
140}