A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3#if UNITY_2020_2_OR_NEWER 4using UnityEditor.AssetImporters; 5#else 6using UnityEditor.Experimental.AssetImporters; 7#endif 8using UnityEditor.Graphing; 9using UnityEditor.ShaderGraph.Internal; 10using UnityEditor.ShaderGraph.Serialization; 11using UnityEngine; 12 13namespace UnityEditor.ShaderGraph 14{ 15 [Serializable] 16 struct FunctionPair 17 { 18 public string key; // aka function name 19 public string value; // aka function code 20 public int graphPrecisionFlags; // Flags<GraphPrecision> indicating which precision variants are requested by the subgraph 21 22 public FunctionPair(string key, string value, int graphPrecisionFlags) 23 { 24 this.key = key; 25 this.value = value; 26 this.graphPrecisionFlags = graphPrecisionFlags; 27 } 28 } 29 30 [Serializable] 31 class SlotCapability 32 { 33 public string slotName; 34 public ShaderStageCapability capabilities = ShaderStageCapability.All; 35 } 36 37 [Serializable] 38 class SlotDependencyPair 39 { 40 public string inputSlotName; 41 public string outputSlotName; 42 } 43 44 /// Cached run-time information for slot dependency tracking within a sub-graph 45 class SlotDependencyInfo 46 { 47 internal string slotName; 48 internal ShaderStageCapability capabilities = ShaderStageCapability.All; 49 internal HashSet<string> dependencies = new HashSet<string>(); 50 51 internal void AddDepencencySlotName(string slotName) 52 { 53 dependencies.Add(slotName); 54 } 55 56 internal bool ContainsSlot(MaterialSlot slot) 57 { 58 return dependencies.Contains(slot.RawDisplayName()); 59 } 60 } 61 62 class SubGraphData : JsonObject 63 { 64 public List<JsonData<AbstractShaderProperty>> inputs = new List<JsonData<AbstractShaderProperty>>(); 65 public List<JsonData<ShaderKeyword>> keywords = new List<JsonData<ShaderKeyword>>(); 66 public List<JsonData<ShaderDropdown>> dropdowns = new List<JsonData<ShaderDropdown>>(); 67 public List<JsonData<AbstractShaderProperty>> nodeProperties = new List<JsonData<AbstractShaderProperty>>(); 68 public List<JsonData<MaterialSlot>> outputs = new List<JsonData<MaterialSlot>>(); 69 public List<JsonData<Target>> unsupportedTargets = new List<JsonData<Target>>(); 70 } 71 72 class SubGraphAsset : ScriptableObject, ISerializationCallbackReceiver 73 { 74 public bool isValid; 75 76 public long processedAt; 77 78 public string functionName; 79 80 public string inputStructName; 81 82 public string hlslName; 83 84 public string assetGuid; 85 86 public ShaderGraphRequirements requirements; 87 88 public string path; 89 90 public List<FunctionPair> functions = new List<FunctionPair>(); 91 92 public IncludeCollection includes; 93 94 public List<string> vtFeedbackVariables = new List<string>(); 95 96 private SubGraphData m_SubGraphData; 97 98 [HideInInspector] 99 [SerializeField] 100 private SerializationHelper.JSONSerializedElement m_SerializedSubGraphData; 101 102 public DataValueEnumerable<AbstractShaderProperty> inputs => m_SubGraphData.inputs.SelectValue(); 103 104 public DataValueEnumerable<ShaderKeyword> keywords => m_SubGraphData.keywords.SelectValue(); 105 106 public DataValueEnumerable<ShaderDropdown> dropdowns => m_SubGraphData.dropdowns.SelectValue(); 107 108 public DataValueEnumerable<AbstractShaderProperty> nodeProperties => m_SubGraphData.nodeProperties.SelectValue(); 109 110 public DataValueEnumerable<MaterialSlot> outputs => m_SubGraphData.outputs.SelectValue(); 111 112 public DataValueEnumerable<Target> unsupportedTargets => m_SubGraphData.unsupportedTargets.SelectValue(); 113 114 public List<string> children = new List<string>(); // guids of direct USED SUBGRAPH file dependencies 115 116 public List<string> descendents = new List<string>(); // guids of ALL file dependencies at any level, SHOULD LIST EVEN MISSING DESCENDENTS 117 118 public List<SlotCapability> inputCapabilities = new List<SlotCapability>(); 119 public List<SlotCapability> outputCapabilities = new List<SlotCapability>(); 120 // Every unique input/output dependency pair 121 public List<SlotDependencyPair> slotDependencies = new List<SlotDependencyPair>(); 122 123 Dictionary<string, SlotDependencyInfo> m_InputDependencies = new Dictionary<string, SlotDependencyInfo>(); 124 Dictionary<string, SlotDependencyInfo> m_OutputDependencies = new Dictionary<string, SlotDependencyInfo>(); 125 126 127 public SlotDependencyInfo GetInputDependencies(string slotName) 128 { 129 m_InputDependencies.TryGetValue(slotName, out SlotDependencyInfo result); 130 return result; 131 } 132 133 public SlotDependencyInfo GetOutputDependencies(string slotName) 134 { 135 m_OutputDependencies.TryGetValue(slotName, out SlotDependencyInfo result); 136 return result; 137 } 138 139 // this is the precision that the entire subgraph is set to (indicates whether the graph is hard-coded or switchable) 140 public GraphPrecision subGraphGraphPrecision; 141 142 // this is the precision of the subgraph outputs 143 // NOTE: this may not be the same as subGraphGraphPrecision 144 // for example, a graph could allow switching precisions for internal calculations, 145 // but the output of the graph is always full float 146 // NOTE: we don't currently have a way to select the graph precision for EACH output 147 // there's a single shared precision for all of them 148 public GraphPrecision outputGraphPrecision; 149 150 public PreviewMode previewMode; 151 152 public void WriteData(IEnumerable<AbstractShaderProperty> inputs, IEnumerable<ShaderKeyword> keywords, IEnumerable<ShaderDropdown> dropdowns, IEnumerable<AbstractShaderProperty> nodeProperties, IEnumerable<MaterialSlot> outputs, IEnumerable<Target> unsupportedTargets) 153 { 154 if (m_SubGraphData == null) 155 { 156 m_SubGraphData = new SubGraphData(); 157 m_SubGraphData.OverrideObjectId(assetGuid, "_subGraphData"); 158 } 159 160 m_SubGraphData.inputs.Clear(); 161 m_SubGraphData.keywords.Clear(); 162 m_SubGraphData.dropdowns.Clear(); 163 m_SubGraphData.nodeProperties.Clear(); 164 m_SubGraphData.outputs.Clear(); 165 m_SubGraphData.unsupportedTargets.Clear(); 166 167 foreach (var input in inputs) 168 { 169 m_SubGraphData.inputs.Add(input); 170 } 171 172 foreach (var keyword in keywords) 173 { 174 m_SubGraphData.keywords.Add(keyword); 175 } 176 177 foreach (var dropdown in dropdowns) 178 { 179 m_SubGraphData.dropdowns.Add(dropdown); 180 } 181 182 foreach (var nodeProperty in nodeProperties) 183 { 184 m_SubGraphData.nodeProperties.Add(nodeProperty); 185 } 186 187 foreach (var output in outputs) 188 { 189 m_SubGraphData.outputs.Add(output); 190 } 191 192 foreach (var unsupportedTarget in unsupportedTargets) 193 { 194 m_SubGraphData.unsupportedTargets.Add(unsupportedTarget); 195 } 196 var json = MultiJson.Serialize(m_SubGraphData); 197 m_SerializedSubGraphData = new SerializationHelper.JSONSerializedElement() { JSONnodeData = json }; 198 m_SubGraphData = null; 199 } 200 201 public void OnBeforeSerialize() 202 { 203 } 204 205 public void OnAfterDeserialize() 206 { 207 } 208 209 public void LoadGraphData() 210 { 211 m_SubGraphData = new SubGraphData(); 212 if (!String.IsNullOrEmpty(m_SerializedSubGraphData.JSONnodeData)) 213 { 214 MultiJson.Deserialize(m_SubGraphData, m_SerializedSubGraphData.JSONnodeData); 215 } 216 } 217 218 internal void LoadDependencyData() 219 { 220 m_InputDependencies.Clear(); 221 m_OutputDependencies.Clear(); 222 223 foreach (var capabilityInfo in inputCapabilities) 224 { 225 var dependencyInfo = new SlotDependencyInfo(); 226 dependencyInfo.slotName = capabilityInfo.slotName; 227 dependencyInfo.capabilities = capabilityInfo.capabilities; 228 if (m_InputDependencies.ContainsKey(dependencyInfo.slotName)) 229 { 230 Debug.LogWarning($"SubGraph '{hlslName}' has multiple input slots named '{dependencyInfo.slotName}', which is unsupported. Please assign the input slots unique names."); 231 continue; 232 } 233 m_InputDependencies.Add(dependencyInfo.slotName, dependencyInfo); 234 } 235 foreach (var capabilityInfo in outputCapabilities) 236 { 237 var dependencyInfo = new SlotDependencyInfo(); 238 dependencyInfo.slotName = capabilityInfo.slotName; 239 dependencyInfo.capabilities = capabilityInfo.capabilities; 240 if (m_OutputDependencies.ContainsKey(dependencyInfo.slotName)) 241 { 242 Debug.LogWarning($"SubGraph '{hlslName}' has multiple output slots named '{dependencyInfo.slotName}', which is unsupported. Please assign the output slots unique names."); 243 continue; 244 } 245 m_OutputDependencies.Add(dependencyInfo.slotName, dependencyInfo); 246 } 247 foreach (var slotDependency in slotDependencies) 248 { 249 // This shouldn't fail since every input/output must be in the above lists... 250 if (m_InputDependencies.ContainsKey(slotDependency.inputSlotName)) 251 m_InputDependencies[slotDependency.inputSlotName].AddDepencencySlotName(slotDependency.outputSlotName); 252 if (m_OutputDependencies.ContainsKey(slotDependency.outputSlotName)) 253 m_OutputDependencies[slotDependency.outputSlotName].AddDepencencySlotName(slotDependency.inputSlotName); 254 } 255 } 256 } 257}