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.

279 lines
12 KiB

  1. using System;
  2. using UnityEngine;
  3. using UnityEditor;
  4. namespace AmplifyShaderEditor
  5. {
  6. [Serializable]
  7. public class StencilBufferOpHelper
  8. {
  9. public static readonly string[] StencilComparisonValues =
  10. {
  11. "<Default>",
  12. "Greater" ,
  13. "GEqual" ,
  14. "Less" ,
  15. "LEqual" ,
  16. "Equal" ,
  17. "NotEqual" ,
  18. "Always" ,
  19. "Never"
  20. };
  21. public static readonly string[] StencilComparisonLabels =
  22. {
  23. "<Default>",
  24. "Greater" ,
  25. "Greater or Equal" ,
  26. "Less" ,
  27. "Less or Equal" ,
  28. "Equal" ,
  29. "Not Equal" ,
  30. "Always" ,
  31. "Never"
  32. };
  33. public static readonly string[] StencilOpsValues =
  34. {
  35. "<Default>",
  36. "Keep",
  37. "Zero",
  38. "Replace",
  39. "IncrSat",
  40. "DecrSat",
  41. "Invert",
  42. "IncrWrap",
  43. "DecrWrap"
  44. };
  45. public static readonly string[] StencilOpsLabels =
  46. {
  47. "<Default>",
  48. "Keep",
  49. "Zero",
  50. "Replace",
  51. "IncrSat",
  52. "DecrSat",
  53. "Invert",
  54. "IncrWrap",
  55. "DecrWrap"
  56. };
  57. private const string FoldoutLabelStr = " Stencil Buffer";
  58. private GUIContent ReferenceValueContent = new GUIContent( "Reference", "The value to be compared against (if Comparison is anything else than always) and/or the value to be written to the buffer (if either Pass, Fail or ZFail is set to replace)" );
  59. private GUIContent ReadMaskContent = new GUIContent( "Read Mask", "An 8 bit mask as an 0-255 integer, used when comparing the reference value with the contents of the buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask)" );
  60. private GUIContent WriteMaskContent = new GUIContent( "Write Mask", "An 8 bit mask as an 0-255 integer, used when writing to the buffer" );
  61. private const string ComparisonStr = "Comparison";
  62. private const string PassStr = "Pass";
  63. private const string FailStr = "Fail";
  64. private const string ZFailStr = "ZFail";
  65. private const string ComparisonFrontStr = "Comp. Front";
  66. private const string PassFrontStr = "Pass Front";
  67. private const string FailFrontStr = "Fail Front";
  68. private const string ZFailFrontStr = "ZFail Front";
  69. private const string ComparisonBackStr = "Comp. Back";
  70. private const string PassBackStr = "Pass Back";
  71. private const string FailBackStr = "Fail Back";
  72. private const string ZFailBackStr = "ZFail Back";
  73. private const int ReadMaskDefaultValue = 255;
  74. private const int WriteMaskDefaultValue = 255;
  75. private const int ComparisonDefaultValue = 0;
  76. private const int PassStencilOpDefaultValue = 0;
  77. private const int FailStencilOpDefaultValue = 0;
  78. private const int ZFailStencilOpDefaultValue = 0;
  79. [SerializeField]
  80. private bool m_active;
  81. [SerializeField]
  82. private InlineProperty m_refValue = new InlineProperty();
  83. [SerializeField]
  84. private InlineProperty m_readMask = new InlineProperty( ReadMaskDefaultValue );
  85. [SerializeField]
  86. private InlineProperty m_writeMask = new InlineProperty( WriteMaskDefaultValue );
  87. //Comparison Function
  88. [SerializeField]
  89. private InlineProperty m_comparisonFunctionIdx = new InlineProperty( ComparisonDefaultValue );
  90. [SerializeField]
  91. private InlineProperty m_comparisonFunctionBackIdx = new InlineProperty( ComparisonDefaultValue );
  92. //Pass Stencil Op
  93. [SerializeField]
  94. private InlineProperty m_passStencilOpIdx = new InlineProperty( PassStencilOpDefaultValue );
  95. [SerializeField]
  96. private InlineProperty m_passStencilOpBackIdx = new InlineProperty( PassStencilOpDefaultValue );
  97. //Fail Stencil Op
  98. [SerializeField]
  99. private InlineProperty m_failStencilOpIdx = new InlineProperty( FailStencilOpDefaultValue );
  100. [SerializeField]
  101. private InlineProperty m_failStencilOpBackIdx = new InlineProperty( FailStencilOpDefaultValue );
  102. //ZFail Stencil Op
  103. [SerializeField]
  104. private InlineProperty m_zFailStencilOpIdx = new InlineProperty( ZFailStencilOpDefaultValue );
  105. [SerializeField]
  106. private InlineProperty m_zFailStencilOpBackIdx = new InlineProperty( ZFailStencilOpDefaultValue );
  107. public string CreateStencilOp( UndoParentNode owner )
  108. {
  109. string result = "\t\tStencil\n\t\t{\n";
  110. result += string.Format( "\t\t\tRef {0}\n", m_refValue.GetValueOrProperty() );
  111. if( m_readMask.Active || m_readMask.IntValue != ReadMaskDefaultValue )
  112. {
  113. result += string.Format( "\t\t\tReadMask {0}\n", m_readMask.GetValueOrProperty() );
  114. }
  115. if( m_writeMask.Active || m_writeMask.IntValue != WriteMaskDefaultValue )
  116. {
  117. result += string.Format( "\t\t\tWriteMask {0}\n", m_writeMask.GetValueOrProperty() );
  118. }
  119. if( ( owner as StandardSurfaceOutputNode ).CurrentCullMode == CullMode.Off )
  120. {
  121. if( m_comparisonFunctionIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionIdx.Active )
  122. result += string.Format( "\t\t\tCompFront {0}\n", m_comparisonFunctionIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionIdx.IntValue ] ) );
  123. if( m_passStencilOpIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpIdx.Active )
  124. result += string.Format( "\t\t\tPassFront {0}\n", m_passStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpIdx.IntValue ] ) );
  125. if( m_failStencilOpIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpIdx.Active )
  126. result += string.Format( "\t\t\tFailFront {0}\n", m_failStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpIdx.IntValue ] ) );
  127. if( m_zFailStencilOpIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpIdx.Active )
  128. result += string.Format( "\t\t\tZFailFront {0}\n", m_zFailStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpIdx.IntValue ] ) );
  129. if( m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionBackIdx.Active )
  130. result += string.Format( "\t\t\tCompBack {0}\n", m_comparisonFunctionBackIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionBackIdx.IntValue ] ) );
  131. if( m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpBackIdx.Active )
  132. result += string.Format( "\t\t\tPassBack {0}\n", m_passStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpBackIdx.IntValue ] ) );
  133. if( m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpBackIdx.Active )
  134. result += string.Format( "\t\t\tFailBack {0}\n", m_failStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpBackIdx.IntValue ] ) );
  135. if( m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpBackIdx.Active )
  136. result += string.Format( "\t\t\tZFailBack {0}\n", m_zFailStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpBackIdx.IntValue ] ) );
  137. }
  138. else
  139. {
  140. if( m_comparisonFunctionIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionIdx.Active )
  141. result += string.Format( "\t\t\tComp {0}\n", m_comparisonFunctionIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionIdx.IntValue ] ) );
  142. if( m_passStencilOpIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpIdx.Active )
  143. result += string.Format( "\t\t\tPass {0}\n", m_passStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpIdx.IntValue ] ) );
  144. if( m_failStencilOpIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpIdx.Active )
  145. result += string.Format( "\t\t\tFail {0}\n", m_failStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpIdx.IntValue ] ) );
  146. if( m_zFailStencilOpIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpIdx.Active )
  147. result += string.Format( "\t\t\tZFail {0}\n", m_zFailStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpIdx.IntValue ] ) );
  148. }
  149. result += "\t\t}\n";
  150. return result;
  151. }
  152. public void Draw( UndoParentNode owner )
  153. {
  154. bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions;
  155. NodeUtils.DrawPropertyGroup( owner, ref foldoutValue, ref m_active, FoldoutLabelStr, () =>
  156. {
  157. float cache = EditorGUIUtility.labelWidth;
  158. float cache2 = EditorGUIUtility.fieldWidth;
  159. EditorGUIUtility.labelWidth = 110;
  160. EditorGUIUtility.fieldWidth = 30;
  161. m_refValue.IntSlider( ref owner, ReferenceValueContent, 0, 255 );
  162. m_readMask.IntSlider( ref owner, ReadMaskContent, 0, 255 );
  163. m_writeMask.IntSlider( ref owner, WriteMaskContent, 0, 255 );
  164. //EditorGUIUtility.labelWidth = cache;
  165. EditorGUIUtility.fieldWidth = cache2;
  166. if( ( owner as StandardSurfaceOutputNode ).CurrentCullMode == CullMode.Off )
  167. {
  168. m_comparisonFunctionIdx.EnumTypePopup( ref owner, ComparisonFrontStr, StencilComparisonLabels );
  169. m_passStencilOpIdx.EnumTypePopup( ref owner, PassFrontStr, StencilOpsLabels );
  170. m_failStencilOpIdx.EnumTypePopup( ref owner, FailFrontStr, StencilOpsLabels );
  171. m_zFailStencilOpIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilOpsLabels );
  172. EditorGUILayout.Separator();
  173. m_comparisonFunctionBackIdx.EnumTypePopup( ref owner, ComparisonBackStr, StencilComparisonLabels );
  174. m_passStencilOpBackIdx.EnumTypePopup( ref owner, PassBackStr, StencilOpsLabels );
  175. m_failStencilOpBackIdx.EnumTypePopup( ref owner, FailBackStr, StencilOpsLabels );
  176. m_zFailStencilOpBackIdx.EnumTypePopup( ref owner, ZFailBackStr, StencilOpsLabels );
  177. }
  178. else
  179. {
  180. m_comparisonFunctionIdx.EnumTypePopup( ref owner, ComparisonStr, StencilComparisonLabels );
  181. m_passStencilOpIdx.EnumTypePopup( ref owner, PassFrontStr, StencilOpsLabels );
  182. m_failStencilOpIdx.EnumTypePopup( ref owner, FailFrontStr, StencilOpsLabels );
  183. m_zFailStencilOpIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilOpsLabels );
  184. }
  185. EditorGUIUtility.labelWidth = cache;
  186. } );
  187. owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldoutValue;
  188. }
  189. public void ReadFromString( ref uint index, ref string[] nodeParams )
  190. {
  191. m_active = Convert.ToBoolean( nodeParams[ index++ ] );
  192. if( UIUtils.CurrentShaderVersion() > 14501 )
  193. {
  194. m_refValue.ReadFromString( ref index, ref nodeParams );
  195. m_readMask.ReadFromString( ref index, ref nodeParams );
  196. m_writeMask.ReadFromString( ref index, ref nodeParams );
  197. m_comparisonFunctionIdx.ReadFromString( ref index, ref nodeParams );
  198. m_passStencilOpIdx.ReadFromString( ref index, ref nodeParams );
  199. m_failStencilOpIdx.ReadFromString( ref index, ref nodeParams );
  200. m_zFailStencilOpIdx.ReadFromString( ref index, ref nodeParams );
  201. }
  202. else
  203. {
  204. m_refValue.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  205. m_readMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  206. m_writeMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  207. m_comparisonFunctionIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  208. m_passStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  209. m_failStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  210. m_zFailStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  211. }
  212. if( UIUtils.CurrentShaderVersion() > 13203 )
  213. {
  214. if( UIUtils.CurrentShaderVersion() > 14501 )
  215. {
  216. m_comparisonFunctionBackIdx.ReadFromString( ref index, ref nodeParams );
  217. m_passStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
  218. m_failStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
  219. m_zFailStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
  220. }
  221. else
  222. {
  223. m_comparisonFunctionBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  224. m_passStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  225. m_failStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  226. m_zFailStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  227. }
  228. }
  229. }
  230. public void WriteToString( ref string nodeInfo )
  231. {
  232. IOUtils.AddFieldValueToString( ref nodeInfo, m_active );
  233. m_refValue.WriteToString( ref nodeInfo );
  234. m_readMask.WriteToString( ref nodeInfo );
  235. m_writeMask.WriteToString( ref nodeInfo );
  236. m_comparisonFunctionIdx.WriteToString( ref nodeInfo );
  237. m_passStencilOpIdx.WriteToString( ref nodeInfo );
  238. m_failStencilOpIdx.WriteToString( ref nodeInfo );
  239. m_zFailStencilOpIdx.WriteToString( ref nodeInfo );
  240. m_comparisonFunctionBackIdx.WriteToString( ref nodeInfo );
  241. m_passStencilOpBackIdx.WriteToString( ref nodeInfo );
  242. m_failStencilOpBackIdx.WriteToString( ref nodeInfo );
  243. m_zFailStencilOpBackIdx.WriteToString( ref nodeInfo );
  244. }
  245. public bool Active
  246. {
  247. get { return m_active; }
  248. set { m_active = value; }
  249. }
  250. }
  251. }