A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEngine; 5using UnityEditor.Graphing; 6using UnityEditor.ShaderGraph.Internal; 7using UnityEditor.ShaderGraph.Serialization; 8using UnityEditor.ShaderGraph.Drawing.Slots; 9using UnityEngine.UIElements; 10 11namespace UnityEditor.ShaderGraph 12{ 13 [Serializable] 14 abstract class MaterialSlot : JsonObject, IDisposable 15 { 16 const string k_NotInit = "Not Initialized"; 17 18 [SerializeField] 19 int m_Id; 20 21 [SerializeField] 22 string m_DisplayName = k_NotInit; 23 24 [SerializeField] 25 SlotType m_SlotType = SlotType.Input; 26 27 [SerializeField] 28 bool m_Hidden; 29 30 [SerializeField] 31 string m_ShaderOutputName; 32 33 [SerializeField] 34 ShaderStageCapability m_StageCapability; 35 36 bool m_HasError; 37 38 protected MaterialSlot() { } 39 40 protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) 41 { 42 m_Id = slotId; 43 m_DisplayName = displayName; 44 m_SlotType = slotType; 45 m_Hidden = hidden; 46 m_ShaderOutputName = shaderOutputName; 47 this.stageCapability = stageCapability; 48 } 49 50 internal void SetInternalData(SlotType slotType, string shaderOutputName) 51 { 52 this.m_SlotType = slotType; 53 this.shaderOutputName = shaderOutputName; 54 } 55 56 public bool IsConnectionTestable() 57 { 58 if (owner is SubGraphNode sgNode) 59 { 60 var property = sgNode.GetShaderProperty(id); 61 if (property != null) 62 { 63 return property.isConnectionTestable; 64 } 65 } 66 else if (owner is PropertyNode propertyNode) 67 { 68 return propertyNode.property.isConnectionTestable; 69 } 70 return false; 71 } 72 73 public VisualElement InstantiateCustomControl() 74 { 75 if (!isConnected && IsConnectionTestable()) 76 { 77 var sgNode = owner as SubGraphNode; 78 var property = sgNode.GetShaderProperty(id); 79 return new LabelSlotControlView(property.customSlotLabel); 80 } 81 return null; 82 } 83 84 public virtual VisualElement InstantiateControl() 85 { 86 return null; 87 } 88 89 static string ConcreteSlotValueTypeAsString(ConcreteSlotValueType type) 90 { 91 switch (type) 92 { 93 case ConcreteSlotValueType.Vector1: 94 return "(1)"; 95 case ConcreteSlotValueType.Vector2: 96 return "(2)"; 97 case ConcreteSlotValueType.Vector3: 98 return "(3)"; 99 case ConcreteSlotValueType.Vector4: 100 return "(4)"; 101 case ConcreteSlotValueType.Boolean: 102 return "(B)"; 103 case ConcreteSlotValueType.Matrix2: 104 return "(2x2)"; 105 case ConcreteSlotValueType.Matrix3: 106 return "(3x3)"; 107 case ConcreteSlotValueType.Matrix4: 108 return "(4x4)"; 109 case ConcreteSlotValueType.SamplerState: 110 return "(SS)"; 111 case ConcreteSlotValueType.Texture2D: 112 return "(T2)"; 113 case ConcreteSlotValueType.Texture2DArray: 114 return "(T2A)"; 115 case ConcreteSlotValueType.Texture3D: 116 return "(T3)"; 117 case ConcreteSlotValueType.Cubemap: 118 return "(C)"; 119 case ConcreteSlotValueType.Gradient: 120 return "(G)"; 121 case ConcreteSlotValueType.VirtualTexture: 122 return "(VT)"; 123 case ConcreteSlotValueType.PropertyConnectionState: 124 return "(P)"; 125 default: 126 return "(E)"; 127 } 128 } 129 130 public virtual string displayName 131 { 132 get { return m_DisplayName + ConcreteSlotValueTypeAsString(concreteValueType); } 133 set { m_DisplayName = value; } 134 } 135 136 public string RawDisplayName() 137 { 138 return m_DisplayName; 139 } 140 141 public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStageCapability shaderStageCapability = ShaderStageCapability.All, bool hidden = false) 142 { 143 switch (type) 144 { 145 case SlotValueType.SamplerState: 146 return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 147 case SlotValueType.DynamicMatrix: 148 return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 149 case SlotValueType.Matrix4: 150 return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 151 case SlotValueType.Matrix3: 152 return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 153 case SlotValueType.Matrix2: 154 return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 155 case SlotValueType.Texture2D: 156 return slotType == SlotType.Input 157 ? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) 158 : new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 159 case SlotValueType.Texture2DArray: 160 return slotType == SlotType.Input 161 ? new Texture2DArrayInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) 162 : new Texture2DArrayMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 163 case SlotValueType.Texture3D: 164 return slotType == SlotType.Input 165 ? new Texture3DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) 166 : new Texture3DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 167 case SlotValueType.Cubemap: 168 return slotType == SlotType.Input 169 ? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) 170 : new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 171 case SlotValueType.VirtualTexture: 172 return slotType == SlotType.Input 173 ? new VirtualTextureInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) 174 : new VirtualTextureMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 175 case SlotValueType.Gradient: 176 return slotType == SlotType.Input 177 ? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) 178 : new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 179 case SlotValueType.DynamicVector: 180 return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden); 181 case SlotValueType.Vector4: 182 return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden); 183 case SlotValueType.Vector3: 184 return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden); 185 case SlotValueType.Vector2: 186 return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden); 187 case SlotValueType.Vector1: 188 return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStageCapability, hidden: hidden); 189 case SlotValueType.Dynamic: 190 return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStageCapability, hidden); 191 case SlotValueType.Boolean: 192 return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStageCapability, hidden); 193 case SlotValueType.PropertyConnectionState: 194 return new PropertyConnectionStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden); 195 } 196 197 throw new ArgumentOutOfRangeException("type", type, null); 198 } 199 200 public SlotReference slotReference 201 { 202 get { return new SlotReference(owner, m_Id); } 203 } 204 205 public AbstractMaterialNode owner { get; set; } 206 207 // if hidden, the slot does not create a port in the UI 208 public bool hidden 209 { 210 get { return m_Hidden; } 211 set { m_Hidden = value; } 212 } 213 214 public int id 215 { 216 get { return m_Id; } 217 } 218 219 public bool isInputSlot 220 { 221 get { return m_SlotType == SlotType.Input; } 222 } 223 224 public bool isOutputSlot 225 { 226 get { return m_SlotType == SlotType.Output; } 227 } 228 229 public SlotType slotType 230 { 231 get { return m_SlotType; } 232 } 233 234 public bool isConnected 235 { 236 get 237 { 238 // node and graph respectivly 239 if (owner == null || owner.owner == null) 240 return false; 241 242 var graph = owner.owner; 243 var edges = graph.GetEdges(slotReference); 244 return edges.Any(); 245 } 246 } 247 248 public abstract bool isDefaultValue { get; } 249 250 public abstract SlotValueType valueType { get; } 251 252 public abstract ConcreteSlotValueType concreteValueType { get; } 253 254 public string shaderOutputName 255 { 256 get { return m_ShaderOutputName; } 257 private set { m_ShaderOutputName = value; } 258 } 259 260 public ShaderStageCapability stageCapability 261 { 262 get { return m_StageCapability; } 263 set { m_StageCapability = value; } 264 } 265 266 public bool hasError 267 { 268 get { return m_HasError; } 269 set { m_HasError = value; } 270 } 271 272 public bool IsUsingDefaultValue() 273 { 274 if (!isConnected && isDefaultValue) 275 return true; 276 else 277 return false; 278 } 279 280 public bool IsCompatibleWith(MaterialSlot otherSlot) 281 { 282 return otherSlot != null 283 && otherSlot.owner != owner 284 && otherSlot.isInputSlot != isInputSlot 285 && !hidden 286 && !otherSlot.hidden 287 && ((isInputSlot 288 ? SlotValueHelper.AreCompatible(valueType, otherSlot.concreteValueType, otherSlot.IsConnectionTestable()) 289 : SlotValueHelper.AreCompatible(otherSlot.valueType, concreteValueType, IsConnectionTestable()))); 290 } 291 292 public bool IsCompatibleStageWith(MaterialSlot otherSlot) 293 { 294 var startStage = otherSlot.stageCapability; 295 if (startStage == ShaderStageCapability.All || otherSlot.owner is SubGraphNode) 296 startStage = NodeUtils.GetEffectiveShaderStageCapability(otherSlot, true) 297 & NodeUtils.GetEffectiveShaderStageCapability(otherSlot, false); 298 return IsCompatibleStageWith(startStage); 299 } 300 301 internal bool IsCompatibleStageWith(ShaderStageCapability capability) 302 { 303 return capability == ShaderStageCapability.All || stageCapability == ShaderStageCapability.All || stageCapability == capability; 304 } 305 306 public string GetDefaultValue(GenerationMode generationMode, ConcretePrecision concretePrecision) 307 { 308 string defaultValue = GetDefaultValue(generationMode); 309 return defaultValue.Replace(PrecisionUtil.Token, concretePrecision.ToShaderString()); 310 } 311 312 public virtual string GetDefaultValue(GenerationMode generationMode) 313 { 314 var matOwner = owner as AbstractMaterialNode; 315 if (matOwner == null) 316 throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode))); 317 318 if (generationMode.IsPreview() && matOwner.isActive) 319 return matOwner.GetVariableNameForSlot(id); 320 321 return ConcreteSlotValueAsVariable(); 322 } 323 324 protected virtual string ConcreteSlotValueAsVariable() 325 { 326 return "error"; 327 } 328 329 public abstract void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode); 330 331 public virtual void GetPreviewProperties(List<PreviewProperty> properties, string name) 332 { 333 properties.Add(default(PreviewProperty)); 334 } 335 336 public virtual void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName) 337 { 338 sb.Append(concreteValueType.ToShaderString()); 339 sb.Append(" "); 340 sb.Append(paramName); 341 } 342 343 public abstract void CopyValuesFrom(MaterialSlot foundSlot); 344 345 public bool Equals(MaterialSlot other) 346 { 347 return m_Id == other.m_Id && owner == other.owner; 348 } 349 350 public override bool Equals(object obj) 351 { 352 if (ReferenceEquals(null, obj)) return false; 353 if (ReferenceEquals(this, obj)) return true; 354 if (obj.GetType() != this.GetType()) return false; 355 return Equals((MaterialSlot)obj); 356 } 357 358 public override int GetHashCode() 359 { 360 unchecked 361 { 362 return (m_Id * 397) ^ (owner != null ? owner.GetHashCode() : 0); 363 } 364 } 365 366 public void Dispose() 367 { 368 owner = null; 369 } 370 371 // this tracks old CustomFunctionNode slots that are expecting the old bare resource inputs 372 // rather than the new structure-based inputs 373 internal virtual bool bareResource { get { return false; } set { } } 374 375 public virtual void CopyDefaultValue(MaterialSlot other) 376 { 377 m_Id = other.m_Id; 378 m_DisplayName = other.m_DisplayName; 379 m_SlotType = other.m_SlotType; 380 m_Hidden = other.m_Hidden; 381 m_ShaderOutputName = other.m_ShaderOutputName; 382 m_StageCapability = other.m_StageCapability; 383 } 384 } 385}