Skip to content

Commit 42520ee

Browse files
committed
Add scripts for drawing textures at runtime
1 parent 14ef406 commit 42520ee

File tree

4 files changed

+364
-0
lines changed

4 files changed

+364
-0
lines changed

Runtime/CheckerboardTextureDrawer.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using UnityEngine;
2+
3+
namespace Zigurous.Graphics
4+
{
5+
/// <summary>
6+
/// Draws a texture of a checkerboard pattern.
7+
/// </summary>
8+
[AddComponentMenu("Zigurous/Graphics/Checkerboard Texture Drawer")]
9+
public sealed class CheckerboardTextureDrawer : TextureDrawer
10+
{
11+
/// <summary>
12+
/// The checkerboard settings of a <see cref="CheckerboardTextureDrawer"/>.
13+
/// </summary>
14+
[System.Serializable]
15+
public struct CheckerboardSettings
16+
{
17+
/// <summary>
18+
/// The number of rows in the checkerboard.
19+
/// </summary>
20+
[Tooltip("The number of rows in the checkerboard.")]
21+
public int rows;
22+
23+
/// <summary>
24+
/// The number of columns in the checkerboard.
25+
/// </summary>
26+
[Tooltip("The number of columns in the checkerboard.")]
27+
public int columns;
28+
29+
/// <summary>
30+
/// The first color of the checkerboard.
31+
/// </summary>
32+
[Tooltip("The first color of the checkerboard.")]
33+
public Color colorA;
34+
35+
/// <summary>
36+
/// The second color of the checkerboard.
37+
/// </summary>
38+
[Tooltip("The second color of the checkerboard.")]
39+
public Color colorB;
40+
41+
/// <summary>
42+
/// Creates new checkerboard settings with the specified values.
43+
/// </summary>
44+
/// <param name="rows">The number of rows in the checkerboard.</param>
45+
/// <param name="columns">The number of columns in the checkerboard.</param>
46+
/// <param name="colorA">The first color of the checkerboard.</param>
47+
/// <param name="colorB">The second color of the checkerboard.</param>
48+
public CheckerboardSettings(int rows, int columns, Color colorA, Color colorB)
49+
{
50+
this.rows = rows;
51+
this.columns = columns;
52+
this.colorA = colorA;
53+
this.colorB = colorB;
54+
}
55+
56+
}
57+
58+
/// <summary>
59+
/// The checkerboard settings.
60+
/// </summary>
61+
[Tooltip("The checkerboard settings.")]
62+
public CheckerboardSettings checkerboard = new CheckerboardSettings(4, 4, Color.white, Color.black);
63+
64+
/// <inheritdoc />
65+
protected override void SetPixels(Texture2D texture)
66+
{
67+
int rectWidth = texture.width / this.checkerboard.columns;
68+
int rectHeight = texture.height / this.checkerboard.rows;
69+
70+
for (int row = 0; row < this.checkerboard.rows; row++)
71+
{
72+
for (int col = 0; col < this.checkerboard.columns; col++)
73+
{
74+
Color color = (row + col) % 2 == 0 ? this.checkerboard.colorA : this.checkerboard.colorB;
75+
76+
int positionX = col * rectWidth;
77+
int positionY = row * rectHeight;
78+
79+
for (int x = positionX; x < positionX + rectWidth; x++)
80+
{
81+
for (int y = positionY; y < positionY + rectHeight; y++)
82+
{
83+
texture.SetPixel(x, y, color);
84+
}
85+
}
86+
}
87+
}
88+
}
89+
90+
protected override void OnValidate()
91+
{
92+
base.OnValidate();
93+
94+
if (this.checkerboard.rows < 2) {
95+
this.checkerboard.rows = 2;
96+
}
97+
98+
if (this.checkerboard.columns < 2) {
99+
this.checkerboard.columns = 2;
100+
}
101+
}
102+
103+
}
104+
105+
}

Runtime/CheckerboardTextureDrawer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/TextureDrawer.cs

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
using UnityEngine;
2+
3+
namespace Zigurous.Graphics
4+
{
5+
/// <summary>
6+
/// Draws a custom texture at runtime.
7+
/// </summary>
8+
[ExecuteAlways]
9+
public abstract class TextureDrawer : MonoBehaviour
10+
{
11+
/// <summary>
12+
/// The texture settings of a <see cref="TextureDrawer"/>.
13+
/// </summary>
14+
[System.Serializable]
15+
public struct TextureSettings
16+
{
17+
/// <summary>
18+
/// The width and height of the texture.
19+
/// </summary>
20+
[Tooltip("The width and height of the texture.")]
21+
public Vector2Int size;
22+
23+
/// <summary>
24+
/// The filter mode of the texture.
25+
/// </summary>
26+
[Tooltip("The filter mode of the texture.")]
27+
public FilterMode filterMode;
28+
29+
/// <summary>
30+
/// The wrap mode of the texture.
31+
/// </summary>
32+
[Tooltip("The wrap mode of the texture.")]
33+
public TextureWrapMode wrapMode;
34+
35+
/// <summary>
36+
/// Creates new texture settings with specified values.
37+
/// </summary>
38+
/// <param name="size">The size of the texture.</param>
39+
/// <param name="filterMode">The filter mode of the texture.</param>
40+
/// <param name="wrapMode">The wrap mode of the texture.</param>
41+
public TextureSettings(Vector2Int size, FilterMode filterMode, TextureWrapMode wrapMode)
42+
{
43+
this.size = size;
44+
this.filterMode = filterMode;
45+
this.wrapMode = wrapMode;
46+
}
47+
48+
}
49+
50+
/// <summary>
51+
/// The render settings of a <see cref="TextureDrawer"/>.
52+
/// </summary>
53+
[System.Serializable]
54+
public struct RenderSettings
55+
{
56+
/// <summary>
57+
/// The shader property that holds the texture.
58+
/// </summary>
59+
[Tooltip("The shader property that holds the texture.")]
60+
public ShaderProperty shaderTextureName;
61+
62+
/// <summary>
63+
/// The amount of scaling to apply to the transform (as a multiplier).
64+
/// </summary>
65+
[Tooltip("The amount of scaling to apply to the transform (as a multiplier).")]
66+
public float scaleFactor;
67+
68+
/// <summary>
69+
/// Scales the transform of the object to match the texture size.
70+
/// </summary>
71+
[Tooltip("Scales the transform of the object to match the texture size.")]
72+
public bool scaleTransform;
73+
74+
#if UNITY_EDITOR
75+
/// <summary>
76+
/// Updates the texture while in the editor.
77+
/// </summary>
78+
[Tooltip("Updates the texture while in the editor.")]
79+
public bool updateInEditor;
80+
#endif
81+
82+
/// <summary>
83+
/// Creates new render settings with the specified values.
84+
/// </summary>
85+
/// <param name="shaderTextureName">The shader property that holds the texture.</param>
86+
/// <param name="scaleFactor">The amount of scaling to apply to the transform (as a multiplier).</param>
87+
/// <param name="scaleTransform">Scales the transform of the object to match the texture size.</param>
88+
public RenderSettings(ShaderProperty shaderTextureName, float scaleFactor = 1.0f, bool scaleTransform = false)
89+
{
90+
this.shaderTextureName = shaderTextureName;
91+
this.scaleFactor = scaleFactor;
92+
this.scaleTransform = scaleTransform;
93+
94+
#if UNITY_EDITOR
95+
this.updateInEditor = false;
96+
#endif
97+
}
98+
99+
}
100+
101+
/// <summary>
102+
/// The drawn texture.
103+
/// </summary>
104+
public Texture2D texture { get; private set; }
105+
106+
/// <summary>
107+
/// The texture settings.
108+
/// </summary>
109+
[Tooltip("The texture settings.")]
110+
public TextureSettings textureSettings = new TextureSettings(new Vector2Int(1024, 1024), FilterMode.Bilinear, TextureWrapMode.Clamp);
111+
112+
/// <summary>
113+
/// The renderer component that holds the material the texture is added to.
114+
/// </summary>
115+
public new Renderer renderer { get; private set; }
116+
117+
/// <summary>
118+
/// The render settings.
119+
/// </summary>
120+
[Tooltip("The render settings.")]
121+
public RenderSettings renderSettings = new RenderSettings("_MainTex", 1.0f, false);
122+
123+
/// <summary>
124+
/// Whether the settings have changed since the texture was last drawn.
125+
/// </summary>
126+
public bool invalidated { get; internal set; }
127+
128+
protected virtual void Awake()
129+
{
130+
this.renderer = GetComponent<Renderer>();
131+
}
132+
133+
protected virtual void OnValidate()
134+
{
135+
this.invalidated = true;
136+
137+
if (this.textureSettings.size.x < 1) {
138+
this.textureSettings.size.x = 1;
139+
}
140+
141+
if (this.textureSettings.size.y < 1) {
142+
this.textureSettings.size.y = 1;
143+
}
144+
145+
if (this.renderer == null) {
146+
this.renderer = GetComponent<Renderer>();
147+
}
148+
}
149+
150+
protected virtual void OnEnable()
151+
{
152+
if (Application.isPlaying) {
153+
Draw();
154+
}
155+
}
156+
157+
protected virtual void Update()
158+
{
159+
#if UNITY_EDITOR
160+
if (!(Application.isPlaying || this.renderSettings.updateInEditor)) {
161+
return;
162+
}
163+
#endif
164+
165+
if (this.invalidated) {
166+
Draw();
167+
}
168+
}
169+
170+
/// <summary>
171+
/// Draws the texture.
172+
/// </summary>
173+
/// <returns>The drawn texture.</returns>
174+
public Texture2D Draw()
175+
{
176+
if (this.texture == null || this.texture.width != this.textureSettings.size.x || this.texture.height != this.textureSettings.size.y) {
177+
this.texture = new Texture2D(this.textureSettings.size.x, this.textureSettings.size.y);
178+
}
179+
180+
this.texture.filterMode = this.textureSettings.filterMode;
181+
this.texture.wrapMode = this.textureSettings.wrapMode;
182+
this.invalidated = false;
183+
184+
SetPixels(this.texture);
185+
186+
this.texture.Apply();
187+
188+
ApplyTexture();
189+
SetTransformScale();
190+
191+
return this.texture;
192+
}
193+
194+
/// <summary>
195+
/// Sets the pixels of the texture.
196+
/// </summary>
197+
/// <param name="texture">The texture to set the pixels on.</param>
198+
protected abstract void SetPixels(Texture2D texture);
199+
200+
/// <summary>
201+
/// Applies the texture to the renderer material.
202+
/// </summary>
203+
private void ApplyTexture()
204+
{
205+
if (this.renderer == null) {
206+
return;
207+
}
208+
209+
if (Application.isPlaying) {
210+
this.renderer.material.SetTexture(this.renderSettings.shaderTextureName.id, this.texture);
211+
} else {
212+
this.renderer.sharedMaterial = new Material(this.renderer.sharedMaterial);
213+
this.renderer.sharedMaterial.SetTexture(this.renderSettings.shaderTextureName.id, this.texture);
214+
}
215+
}
216+
217+
/// <summary>
218+
/// Sets the scale of the transform based on the texture size.
219+
/// </summary>
220+
private void SetTransformScale()
221+
{
222+
if (this.texture == null || !this.renderSettings.scaleTransform) {
223+
return;
224+
}
225+
226+
Vector3 scale = new Vector2(this.texture.width, this.texture.height);
227+
scale *= this.renderSettings.scaleFactor;
228+
scale.z = 1.0f;
229+
230+
if (scale.x != Mathf.Infinity && scale.y != Mathf.Infinity) {
231+
this.transform.localScale = scale;
232+
}
233+
}
234+
235+
}
236+
237+
}

Runtime/TextureDrawer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)