설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MaterialSlot.cs 15KB

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