PropertyNode.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using System;
  2. using System.Linq;
  3. using UnityEngine;
  4. using UnityEditor.Graphing;
  5. using UnityEditor.ShaderGraph.Internal;
  6. namespace UnityEditor.ShaderGraph
  7. {
  8. [Title("Input", "Property")]
  9. class PropertyNode : AbstractMaterialNode, IGeneratesBodyCode, IOnAssetEnabled
  10. {
  11. public PropertyNode()
  12. {
  13. name = "Property";
  14. UpdateNodeAfterDeserialization();
  15. }
  16. [SerializeField]
  17. string m_PropertyGuidSerialized;
  18. Guid m_PropertyGuid;
  19. public Guid propertyGuid
  20. {
  21. get { return m_PropertyGuid; }
  22. set
  23. {
  24. if (m_PropertyGuid == value)
  25. return;
  26. m_PropertyGuid = value;
  27. var property = owner.properties.FirstOrDefault(x => x.guid == value);
  28. if (property == null)
  29. return;
  30. AddOutputSlot(property);
  31. Dirty(ModificationScope.Topological);
  32. }
  33. }
  34. public override bool canSetPrecision => false;
  35. public void OnEnable()
  36. {
  37. var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid);
  38. if (property == null)
  39. return;
  40. AddOutputSlot(property);
  41. }
  42. public const int OutputSlotId = 0;
  43. void AddOutputSlot(AbstractShaderProperty property)
  44. {
  45. switch(property.concreteShaderValueType)
  46. {
  47. case ConcreteSlotValueType.Boolean:
  48. AddSlot(new BooleanMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, false));
  49. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  50. break;
  51. case ConcreteSlotValueType.Vector1:
  52. AddSlot(new Vector1MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, 0));
  53. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  54. break;
  55. case ConcreteSlotValueType.Vector2:
  56. AddSlot(new Vector2MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero));
  57. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  58. break;
  59. case ConcreteSlotValueType.Vector3:
  60. AddSlot(new Vector3MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero));
  61. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  62. break;
  63. case ConcreteSlotValueType.Vector4:
  64. AddSlot(new Vector4MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero));
  65. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  66. break;
  67. case ConcreteSlotValueType.Matrix2:
  68. AddSlot(new Matrix2MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  69. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  70. break;
  71. case ConcreteSlotValueType.Matrix3:
  72. AddSlot(new Matrix3MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  73. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  74. break;
  75. case ConcreteSlotValueType.Matrix4:
  76. AddSlot(new Matrix4MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  77. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  78. break;
  79. case ConcreteSlotValueType.Texture2D:
  80. AddSlot(new Texture2DMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  81. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  82. break;
  83. case ConcreteSlotValueType.Texture2DArray:
  84. AddSlot(new Texture2DArrayMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  85. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  86. break;
  87. case ConcreteSlotValueType.Texture3D:
  88. AddSlot(new Texture3DMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  89. RemoveSlotsNameNotMatching(new[] {OutputSlotId});
  90. break;
  91. case ConcreteSlotValueType.Cubemap:
  92. AddSlot(new CubemapMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  93. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  94. break;
  95. case ConcreteSlotValueType.SamplerState:
  96. AddSlot(new SamplerStateMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  97. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  98. break;
  99. case ConcreteSlotValueType.Gradient:
  100. AddSlot(new GradientMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output));
  101. RemoveSlotsNameNotMatching(new[] { OutputSlotId });
  102. break;
  103. default:
  104. throw new ArgumentOutOfRangeException();
  105. }
  106. }
  107. public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
  108. {
  109. var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid);
  110. if (property == null)
  111. return;
  112. switch(property.propertyType)
  113. {
  114. case PropertyType.Boolean:
  115. sb.AppendLine($"$precision {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  116. break;
  117. case PropertyType.Vector1:
  118. sb.AppendLine($"$precision {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  119. break;
  120. case PropertyType.Vector2:
  121. sb.AppendLine($"$precision2 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  122. break;
  123. case PropertyType.Vector3:
  124. sb.AppendLine($"$precision3 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  125. break;
  126. case PropertyType.Vector4:
  127. sb.AppendLine($"$precision4 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  128. break;
  129. case PropertyType.Color:
  130. sb.AppendLine($"$precision4 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  131. break;
  132. case PropertyType.Matrix2:
  133. sb.AppendLine($"$precision2x2 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  134. break;
  135. case PropertyType.Matrix3:
  136. sb.AppendLine($"$precision3x3 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  137. break;
  138. case PropertyType.Matrix4:
  139. sb.AppendLine($"$precision4x4 {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  140. break;
  141. case PropertyType.SamplerState:
  142. sb.AppendLine($"SamplerState {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  143. break;
  144. case PropertyType.Gradient:
  145. if(generationMode == GenerationMode.Preview)
  146. sb.AppendLine($"Gradient {GetVariableNameForSlot(OutputSlotId)} = {GradientUtil.GetGradientForPreview(property.referenceName)};");
  147. else
  148. sb.AppendLine($"Gradient {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};");
  149. break;
  150. }
  151. }
  152. public override string GetVariableNameForSlot(int slotId)
  153. {
  154. var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid);
  155. if (property == null)
  156. throw new NullReferenceException();
  157. if (!(property is Texture2DShaderProperty) &&
  158. !(property is Texture2DArrayShaderProperty) &&
  159. !(property is Texture3DShaderProperty) &&
  160. !(property is CubemapShaderProperty))
  161. return base.GetVariableNameForSlot(slotId);
  162. return property.referenceName;
  163. }
  164. protected override bool CalculateNodeHasError(ref string errorMessage)
  165. {
  166. if (!propertyGuid.Equals(Guid.Empty) && !owner.properties.Any(x => x.guid == propertyGuid))
  167. {
  168. errorMessage = "Property Node has no associated Blackboard property.";
  169. return true;
  170. }
  171. return false;
  172. }
  173. public override bool ValidateConcretePrecision(ref string errorMessage)
  174. {
  175. // Get precision from Property
  176. var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid);
  177. if (property == null)
  178. return true;
  179. // If Property has a precision override use that
  180. precision = property.precision;
  181. if (precision != Precision.Inherit)
  182. concretePrecision = precision.ToConcrete();
  183. else
  184. concretePrecision = owner.concretePrecision;
  185. return false;
  186. }
  187. public override void OnBeforeSerialize()
  188. {
  189. base.OnBeforeSerialize();
  190. m_PropertyGuidSerialized = m_PropertyGuid.ToString();
  191. }
  192. public override void OnAfterDeserialize()
  193. {
  194. base.OnAfterDeserialize();
  195. if (!string.IsNullOrEmpty(m_PropertyGuidSerialized))
  196. m_PropertyGuid = new Guid(m_PropertyGuidSerialized);
  197. }
  198. }
  199. }