A game about forced loneliness, made by TACStudios
at master 249 lines 8.2 kB view raw
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}