A game about forced loneliness, made by TACStudios
1using System;
2using UnityEngine;
3using UnityEngine.Rendering.LookDev;
4using IDataProvider = UnityEngine.Rendering.LookDev.IDataProvider;
5
6namespace UnityEditor.Rendering.LookDev
7{
8 /// <summary>Data container to be used with Renderer class</summary>
9 class RenderingData : IDisposable
10 {
11 /// <summary>
12 /// Internally set to true when the given RenderTexture <see cref="output"/> was not the good size regarding <see cref="viewPort"/> and needed to be recreated
13 /// </summary>
14 public bool sizeMissmatched;
15 /// <summary>The stage that possess every object in your view</summary>
16 public Stage stage;
17 /// <summary>Callback to update the Camera position. Only done in First phase.</summary>
18 public ICameraUpdater updater;
19 /// <summary>Viewport size</summary>
20 public Rect viewPort;
21 /// <summary>Render texture handling captured image</summary>
22 public RenderTexture output;
23
24 private bool disposed = false;
25
26 /// <summary>Dispose pattern</summary>
27 public void Dispose()
28 {
29 if (disposed)
30 return;
31 disposed = true;
32
33 stage = null;
34 updater = null;
35 output?.Release();
36 output = null;
37 }
38 }
39
40 /// <summary>Basic renderer to draw scene in texture</summary>
41 class Renderer
42 {
43 /// <summary>Use pixel perfect</summary>
44 public bool pixelPerfect { get; set; }
45
46 /// <summary>Constructor</summary>
47 /// <param name="pixelPerfect">[Optional] Use pixel perfect</param>
48 public Renderer(bool pixelPerfect = false)
49 => this.pixelPerfect = pixelPerfect;
50
51 /// <summary>Init for rendering</summary>
52 /// <param name="data">The data to use</param>
53 public void BeginRendering(RenderingData data, IDataProvider dataProvider)
54 {
55 data.stage.OnBeginRendering(dataProvider);
56 data.updater?.UpdateCamera(data.stage.camera);
57 data.stage.camera.enabled = true;
58 }
59
60 /// <summary>Finish to render</summary>
61 /// <param name="data">The data to use</param>
62 public void EndRendering(RenderingData data, IDataProvider dataProvider)
63 {
64 data.stage.camera.enabled = false;
65 data.stage.OnEndRendering(dataProvider);
66 }
67
68 bool CheckWrongSizeOutput(RenderingData data)
69 {
70 if (data.viewPort.IsNullOrInverted()
71 || data.viewPort.width != data.output.width
72 || data.viewPort.height != data.viewPort.height)
73 {
74 data.output = null;
75 data.sizeMissmatched = true;
76 return true;
77 }
78
79 data.sizeMissmatched = false;
80 return false;
81 }
82
83 /// <summary>
84 /// Capture image of the scene.
85 /// </summary>
86 /// <param name="data">Datas required to compute the capture</param>
87 /// [Optional] When drawing several time the scene, you can remove First and/or Last to not initialize objects.
88 /// Be careful though to always start your frame with a First and always end with a Last.
89 /// </param>
90 public void Acquire(RenderingData data)
91 {
92 if (CheckWrongSizeOutput(data))
93 return;
94
95 data.stage.camera.targetTexture = data.output;
96 data.stage.camera.Render();
97 }
98
99 internal static void DrawFullScreenQuad(Rect rect)
100 {
101 GL.PushMatrix();
102 GL.LoadOrtho();
103 GL.Viewport(rect);
104
105 GL.Begin(GL.QUADS);
106 GL.TexCoord2(0, 0);
107 GL.Vertex3(0f, 0f, 0);
108 GL.TexCoord2(0, 1);
109 GL.Vertex3(0f, 1f, 0);
110 GL.TexCoord2(1, 1);
111 GL.Vertex3(1f, 1f, 0);
112 GL.TexCoord2(1, 0);
113 GL.Vertex3(1f, 0f, 0);
114 GL.End();
115 GL.PopMatrix();
116 }
117 }
118
119 /// <summary>Rect extension</summary>
120 public static partial class RectExtension
121 {
122 /// <summary>Return true if the <see cref="Rect"/> is null sized or inverted.</summary>
123 /// <param name="r">The rect</param>
124 /// <returns>True: null or inverted area</returns>
125 public static bool IsNullOrInverted(this Rect r)
126 => r.width <= 0f || r.height <= 0f
127 || float.IsNaN(r.width) || float.IsNaN(r.height);
128 }
129}