A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using UnityEditor.Graphing;
5using UnityEditor.ShaderGraph.Serialization;
6using UnityEngine;
7using TextureDimension = UnityEngine.Rendering.TextureDimension;
8
9namespace UnityEditor.ShaderGraph.Internal
10{
11 [Serializable]
12 public struct TextureInfo
13 {
14 public TextureInfo(string name, Texture texture, TextureDimension dimension)
15 {
16 this.name = name;
17 this.texture = texture;
18 this.dimension = dimension;
19 Debug.Assert(texture == null || texture.dimension == dimension);
20 }
21
22 public string name;
23 public Texture texture;
24 public TextureDimension dimension;
25
26 public int instanceID => texture != null ? texture.GetInstanceID() : 0;
27 }
28
29 public sealed class ShaderGraphVfxAsset : ScriptableObject, ISerializationCallbackReceiver
30 {
31 private class ShaderGraphVfxAssetData : JsonObject
32 {
33 public List<JsonData<ShaderInput>> m_Properties = new();
34 }
35
36 public const int BaseColorSlotId = 1;
37 public const int MetallicSlotId = 2;
38 public const int SmoothnessSlotId = 3;
39 public const int NormalSlotId = 8;
40 public const int AlphaSlotId = 4;
41 public const int EmissiveSlotId = 5;
42 public const int ColorSlotId = 6;
43 public const int AlphaThresholdSlotId = 7;
44
45 [SerializeField]
46 public bool generatesWithShaderGraph;
47
48 [SerializeField]
49 public bool lit;
50
51 [SerializeField]
52 public bool alphaClipping;
53
54 [SerializeField]
55 internal ShaderStageCapability[] m_PropertiesStages;
56
57 [SerializeField]
58 internal GraphCompilationResult compilationResult;
59
60 [SerializeField]
61 internal ShaderGraphRequirements[] portRequirements;
62
63 [SerializeField]
64 string m_EvaluationFunctionName;
65
66 [SerializeField]
67 string m_InputStructName;
68
69 [SerializeField]
70 string m_OutputStructName;
71
72 [SerializeField]
73 ConcretePrecision m_ConcretePrecision = ConcretePrecision.Single;
74
75 ShaderGraphVfxAssetData m_Data = new ShaderGraphVfxAssetData();
76
77 [HideInInspector]
78 [SerializeField]
79 private SerializationHelper.JSONSerializedElement m_SerializedVfxAssetData;
80
81 [SerializeField]
82 internal IntArray[] outputPropertyIndices;
83
84 internal ConcretePrecision concretePrecision
85 {
86 get => m_ConcretePrecision;
87 set => m_ConcretePrecision = value;
88 }
89
90 [SerializeField]
91 OutputMetadata[] m_Outputs;
92
93 [SerializeField]
94 TextureInfo[] m_TextureInfos;
95
96 public IEnumerable<TextureInfo> textureInfos { get => m_TextureInfos; }
97
98 internal void SetTextureInfos(IList<PropertyCollector.TextureInfo> textures)
99 {
100 m_TextureInfos = textures.Select(t => new TextureInfo(t.name, EditorUtility.InstanceIDToObject(t.textureId) as Texture, t.dimension)).ToArray();
101 }
102
103 internal void SetOutputs(OutputMetadata[] outputs)
104 {
105 m_Outputs = outputs;
106 }
107
108 public OutputMetadata GetOutput(int id)
109 {
110 return m_Outputs.FirstOrDefault(t => t.id == id);
111 }
112
113 public bool HasOutput(int id)
114 {
115 return m_Outputs.Any(t => t.id == id);
116 }
117
118 public string evaluationFunctionName
119 {
120 get { return m_EvaluationFunctionName; }
121 internal set { m_EvaluationFunctionName = value; }
122 }
123
124 public string inputStructName
125 {
126 get { return m_InputStructName; }
127 internal set { m_InputStructName = value; }
128 }
129
130 public string outputStructName
131 {
132 get { return m_OutputStructName; }
133 internal set { m_OutputStructName = value; }
134 }
135
136 public List<ShaderInput> properties
137 {
138 get
139 {
140 EnsureProperties();
141 return m_Data.m_Properties.SelectValue().ToList();
142 }
143 }
144
145 public List<AbstractShaderProperty> fragmentProperties
146 {
147 get
148 {
149 EnsureProperties();
150 var allProperties = m_Data.m_Properties.SelectValue().ToList();
151 var fragProperties = new List<AbstractShaderProperty>();
152 for (var i = 0; i < allProperties.Count(); i++)
153 {
154 if (allProperties[i] is AbstractShaderProperty property
155 && (m_PropertiesStages[i] & ShaderStageCapability.Fragment) != 0)
156 fragProperties.Add(property);
157 }
158 return fragProperties;
159 }
160 }
161
162 public List<AbstractShaderProperty> vertexProperties
163 {
164 get
165 {
166 EnsureProperties();
167 var allProperties = m_Data.m_Properties.SelectValue().ToList();
168 var vertexProperties = new List<AbstractShaderProperty>();
169 for (var i = 0; i < allProperties.Count(); i++)
170 {
171 if (allProperties[i] is AbstractShaderProperty property
172 && (m_PropertiesStages[i] & ShaderStageCapability.Vertex) != 0)
173 vertexProperties.Add(property);
174 }
175 return vertexProperties;
176 }
177 }
178
179 internal void SetProperties(List<ShaderInput> propertiesList)
180 {
181 m_Data.m_Properties.Clear();
182 foreach (var property in propertiesList)
183 {
184 m_Data.m_Properties.Add(property);
185 }
186
187 var json = MultiJson.Serialize(m_Data);
188 m_SerializedVfxAssetData = new SerializationHelper.JSONSerializedElement() { JSONnodeData = json };
189 m_Data = null;
190 }
191
192 void EnsureProperties()
193 {
194 if ((m_Data == null || m_Data.m_Properties == null || !m_Data.m_Properties.Any()) && !String.IsNullOrEmpty(m_SerializedVfxAssetData.JSONnodeData))
195 {
196 m_Data = new ShaderGraphVfxAssetData();
197 MultiJson.Deserialize(m_Data, m_SerializedVfxAssetData.JSONnodeData);
198 }
199
200 foreach (var property in m_Data.m_Properties.SelectValue())
201 {
202 if (property is AbstractShaderProperty shaderProperty)
203 shaderProperty.SetupConcretePrecision(m_ConcretePrecision);
204 }
205 }
206
207 void ISerializationCallbackReceiver.OnAfterDeserialize()
208 {
209 m_Data = null;
210 }
211
212 void ISerializationCallbackReceiver.OnBeforeSerialize() { }
213
214 public GraphCode GetCode(OutputMetadata[] outputs)
215 {
216 var graphCode = new GraphCode();
217
218 graphCode.requirements = ShaderGraphRequirements.none;
219 var outputIndices = new int[outputs.Length];
220 for (var i = 0; i < outputs.Length; i++)
221 {
222 if (!outputs[i].isValid)
223 {
224 throw new ArgumentException($"Invalid {nameof(OutputMetadata)} at index {i}.", nameof(outputs));
225 }
226
227 outputIndices[i] = outputs[i].index;
228 graphCode.requirements = graphCode.requirements.Union(portRequirements[outputs[i].index]);
229 }
230
231 graphCode.code = compilationResult.GenerateCode(outputIndices);
232
233 var propertyIndexSet = new HashSet<int>();
234 foreach (var outputIndex in outputIndices)
235 {
236 foreach (var propertyIndex in outputPropertyIndices[outputIndex].array)
237 {
238 propertyIndexSet.Add(propertyIndex);
239 }
240 }
241 var propertyIndices = propertyIndexSet.ToArray();
242 Array.Sort(propertyIndices);
243 var filteredProperties = propertyIndices.Select(i => properties[i]).OfType<AbstractShaderProperty>().ToArray();
244 graphCode.properties = filteredProperties;
245
246 return graphCode;
247 }
248 }
249}