UsePassHelper.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. using UnityEditorInternal;
  6. namespace AmplifyShaderEditor
  7. {
  8. public enum UsePassLocation
  9. {
  10. Above,
  11. Below
  12. }
  13. [Serializable]
  14. public class UsePassItem : ScriptableObject
  15. {
  16. public UsePassLocation Location;
  17. public string Value;
  18. public UsePassItem()
  19. {
  20. Location = UsePassLocation.Above;
  21. Value = string.Empty;
  22. }
  23. public UsePassItem( UsePassLocation location, string name )
  24. {
  25. Location = location;
  26. Value = name;
  27. }
  28. }
  29. [Serializable]
  30. public class UsePassHelper : ScriptableObject
  31. {
  32. private const string UseGrabFormatNewLine = "UsePass \"{0}\"\n";
  33. private const string UseGrabFormat = "UsePass \"{0}\"";
  34. private const float ShaderKeywordButtonLayoutWidth = 15;
  35. private const string ShaderPoputContext = "CONTEXT/ShaderPopup";
  36. [SerializeField]
  37. private List<UsePassItem> m_items = new List<UsePassItem>();
  38. [SerializeField]
  39. private UndoParentNode m_owner = null;
  40. [SerializeField]
  41. protected bool m_isDirty = false;
  42. [SerializeField]
  43. protected string m_moduleName = string.Empty;
  44. private ReorderableList m_reordableList = null;
  45. private ReordableAction m_actionType = ReordableAction.None;
  46. private int m_actionIndex = 0;
  47. private GUIStyle m_propertyAdjustment;
  48. private Material m_dummyMaterial;
  49. private MenuCommand m_dummyCommand;
  50. private int m_currentUsePassIdx = 0;
  51. public void Init( string moduleName )
  52. {
  53. hideFlags = HideFlags.HideAndDontSave;
  54. m_moduleName = moduleName;
  55. }
  56. void DrawButtons()
  57. {
  58. EditorGUILayout.Separator();
  59. // Add keyword
  60. if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  61. {
  62. UsePassItem newItem = ScriptableObject.CreateInstance<UsePassItem>();
  63. newItem.hideFlags = HideFlags.HideAndDontSave;
  64. m_items.Add( newItem );
  65. EditorGUI.FocusTextInControl( null );
  66. m_isDirty = true;
  67. }
  68. //Remove keyword
  69. if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  70. {
  71. if( m_items.Count > 0 )
  72. {
  73. UsePassItem itemToDelete = m_items[ m_items.Count - 1 ];
  74. m_items.RemoveAt( m_items.Count - 1 );
  75. ScriptableObject.DestroyImmediate( itemToDelete );
  76. EditorGUI.FocusTextInControl( null );
  77. }
  78. m_isDirty = true;
  79. }
  80. }
  81. public void Draw( UndoParentNode owner, bool style = true )
  82. {
  83. if( m_owner == null )
  84. m_owner = owner;
  85. if( m_reordableList == null )
  86. {
  87. m_reordableList = new ReorderableList( m_items, typeof( UsePassItem ), true, false, false, false )
  88. {
  89. headerHeight = 0,
  90. footerHeight = 0,
  91. showDefaultBackground = false,
  92. drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) =>
  93. {
  94. if( m_items[ index ] != null )
  95. {
  96. float labelWidthMultiplier;
  97. float popUpWidth;
  98. float shaderSelectorMultiplier;
  99. float buttonPlusPosMultiplier;
  100. if( style )
  101. {
  102. rect.x -= 10;
  103. labelWidthMultiplier = 0.9f;
  104. popUpWidth = 0.31f;
  105. shaderSelectorMultiplier = 1.01f;
  106. buttonPlusPosMultiplier = 0.78f;
  107. }
  108. else
  109. {
  110. rect.x -= 1;
  111. labelWidthMultiplier = 1.01f;
  112. popUpWidth = 0.25f;
  113. shaderSelectorMultiplier = 1.0f;
  114. buttonPlusPosMultiplier = 0.55f;
  115. }
  116. Rect popupPos = new Rect( rect.x, rect.y + 2, popUpWidth * rect.width, rect.height );
  117. Rect labelPos = new Rect( rect.x + popupPos.width * labelWidthMultiplier, rect.y, 0.59f * rect.width, rect.height );
  118. Rect shaderSelectorPos = new Rect( labelPos.x + labelPos.width* shaderSelectorMultiplier, rect.y, 15, rect.height );
  119. Rect buttonPlusPos = new Rect( shaderSelectorPos.x + shaderSelectorPos.width * buttonPlusPosMultiplier, rect.y, ShaderKeywordButtonLayoutWidth, rect.height );
  120. Rect buttonMinusPos = new Rect( buttonPlusPos.x + buttonPlusPos.width, rect.y, ShaderKeywordButtonLayoutWidth, rect.height );
  121. EditorGUI.BeginChangeCheck();
  122. m_items[ index ].Location = (UsePassLocation)owner.EditorGUIEnumPopup( popupPos, m_items[ index ].Location );
  123. if( EditorGUI.EndChangeCheck() && m_items[ index ].Location == UsePassLocation.Below && m_owner != null && m_owner.ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader )
  124. {
  125. m_items[ index ].Location = UsePassLocation.Above;
  126. UIUtils.ShowMessage( "Below option still not available on templates" );
  127. }
  128. m_items[ index ].Value = owner.EditorGUITextField( labelPos, string.Empty, m_items[ index ].Value );
  129. if( GUI.Button( shaderSelectorPos, string.Empty, UIUtils.InspectorPopdropdownFallback ) )
  130. {
  131. EditorGUI.FocusTextInControl( null );
  132. GUI.FocusControl( null );
  133. m_currentUsePassIdx = index;
  134. DisplayShaderContext( owner, GUILayoutUtility.GetRect( GUIContent.none, EditorStyles.popup ) );
  135. }
  136. if( GUI.Button( buttonPlusPos, string.Empty, UIUtils.PlusStyle ) )
  137. {
  138. m_actionType = ReordableAction.Add;
  139. m_actionIndex = index;
  140. }
  141. if( GUI.Button( buttonMinusPos, string.Empty, UIUtils.MinusStyle ) )
  142. {
  143. m_actionType = ReordableAction.Remove;
  144. m_actionIndex = index;
  145. }
  146. }
  147. }
  148. };
  149. }
  150. if( m_actionType != ReordableAction.None )
  151. {
  152. switch( m_actionType )
  153. {
  154. case ReordableAction.Add:
  155. UsePassItem newItem = ScriptableObject.CreateInstance<UsePassItem>();
  156. newItem.hideFlags = HideFlags.HideAndDontSave;
  157. m_items.Insert( m_actionIndex + 1, newItem );
  158. break;
  159. case ReordableAction.Remove:
  160. UsePassItem itemToDelete = m_items[ m_actionIndex ];
  161. m_items.RemoveAt( m_actionIndex );
  162. ScriptableObject.DestroyImmediate( itemToDelete );
  163. break;
  164. }
  165. m_isDirty = true;
  166. m_actionType = ReordableAction.None;
  167. EditorGUI.FocusTextInControl( null );
  168. }
  169. bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedUsePass;
  170. if( style )
  171. {
  172. NodeUtils.DrawPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons );
  173. }
  174. else
  175. {
  176. NodeUtils.DrawNestedPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons );
  177. }
  178. owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedUsePass = foldoutValue;
  179. }
  180. private void DisplayShaderContext( UndoParentNode node, Rect r )
  181. {
  182. if( m_dummyCommand == null )
  183. m_dummyCommand = new MenuCommand( this, 0 );
  184. if( m_dummyMaterial == null )
  185. m_dummyMaterial = new Material( Shader.Find( "Hidden/ASESShaderSelectorUnlit" ) );
  186. #pragma warning disable 0618
  187. UnityEditorInternal.InternalEditorUtility.SetupShaderMenu( m_dummyMaterial );
  188. #pragma warning restore 0618
  189. EditorUtility.DisplayPopupMenu( r, ShaderPoputContext, m_dummyCommand );
  190. }
  191. private void OnSelectedShaderPopup( string command, Shader shader )
  192. {
  193. if( shader != null )
  194. {
  195. UIUtils.MarkUndoAction();
  196. UndoUtils.RecordObject( m_owner, "Selected Use Pass shader" );
  197. m_items[ m_currentUsePassIdx ].Value = shader.name;
  198. }
  199. }
  200. void DrawReordableList()
  201. {
  202. if( m_reordableList != null )
  203. {
  204. if( m_propertyAdjustment == null )
  205. {
  206. m_propertyAdjustment = new GUIStyle();
  207. m_propertyAdjustment.padding.left = 17;
  208. }
  209. EditorGUILayout.Space();
  210. if( m_items.Count == 0 )
  211. {
  212. EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info );
  213. }
  214. else
  215. {
  216. m_reordableList.DoLayoutList();
  217. }
  218. EditorGUILayout.Space();
  219. }
  220. }
  221. public void ReadFromString( ref uint index, ref string[] nodeParams )
  222. {
  223. try
  224. {
  225. int count = Convert.ToInt32( nodeParams[ index++ ] );
  226. for( int i = 0; i < count; i++ )
  227. {
  228. string locationValue = nodeParams[ index++ ];
  229. // REMOVE THIS TEST AFTER A COUPLE OF VERSIONS (curr v1.5.6 r02)
  230. if( locationValue.Equals( "Bellow" ) ) locationValue = "Below";
  231. UsePassLocation location = (UsePassLocation)Enum.Parse( typeof( UsePassLocation ), locationValue );
  232. string name = nodeParams[ index++ ];
  233. UsePassItem newItem = ScriptableObject.CreateInstance<UsePassItem>();
  234. newItem.hideFlags = HideFlags.HideAndDontSave;
  235. newItem.Location = location;
  236. newItem.Value = name;
  237. m_items.Add( newItem );
  238. }
  239. }
  240. catch( Exception e )
  241. {
  242. Debug.LogException( e );
  243. }
  244. }
  245. public void WriteToString( ref string nodeInfo )
  246. {
  247. IOUtils.AddFieldValueToString( ref nodeInfo, m_items.Count );
  248. for( int i = 0; i < m_items.Count; i++ )
  249. {
  250. IOUtils.AddFieldValueToString( ref nodeInfo, m_items[ i ].Location );
  251. IOUtils.AddFieldValueToString( ref nodeInfo, m_items[ i ].Value );
  252. }
  253. }
  254. public void BuildUsePassInfo( MasterNodeDataCollector dataCollector, ref string aboveItems, ref string bellowItems, string tabs)
  255. {
  256. int count = 0;
  257. count = dataCollector.AboveUsePassesList.Count;
  258. for( int i = 0; i < count; i++ )
  259. {
  260. aboveItems += tabs + string.Format( UseGrabFormatNewLine, dataCollector.AboveUsePassesList[ i ].PropertyName );
  261. }
  262. count = dataCollector.BelowUsePassesList.Count;
  263. for( int i = 0; i < count; i++ )
  264. {
  265. bellowItems += tabs + string.Format( UseGrabFormatNewLine, dataCollector.BelowUsePassesList[ i ].PropertyName );
  266. }
  267. count = m_items.Count;
  268. for( int i = 0; i < count; i++ )
  269. {
  270. if( m_items[ i ].Location == UsePassLocation.Above )
  271. {
  272. aboveItems += tabs + string.Format( UseGrabFormatNewLine, m_items[ i ].Value );
  273. }
  274. else
  275. {
  276. bellowItems += tabs + string.Format( UseGrabFormatNewLine, m_items[ i ].Value );
  277. }
  278. }
  279. }
  280. public void BuildUsePassInfo( MasterNodeDataCollector dataCollector, ref List<PropertyDataCollector> aboveItems, ref List<PropertyDataCollector> bellowItems )
  281. {
  282. int count = 0;
  283. count = dataCollector.AboveUsePassesList.Count;
  284. for( int i = 0; i < count; i++ )
  285. {
  286. aboveItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, dataCollector.AboveUsePassesList[ i ].PropertyName ) ) );
  287. }
  288. count = dataCollector.BelowUsePassesList.Count;
  289. for( int i = 0; i < count; i++ )
  290. {
  291. bellowItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, dataCollector.BelowUsePassesList[ i ].PropertyName ) ) );
  292. }
  293. count = m_items.Count;
  294. for( int i = 0; i < count; i++ )
  295. {
  296. if( m_items[ i ].Location == UsePassLocation.Above )
  297. {
  298. aboveItems.Add( new PropertyDataCollector(-1,string.Format( UseGrabFormat, m_items[ i ].Value )));
  299. }
  300. else
  301. {
  302. bellowItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, m_items[ i ].Value ) ) );
  303. }
  304. }
  305. }
  306. //public string ModuleName { set { m_moduleName = value; } }
  307. public void Destroy()
  308. {
  309. m_owner = null;
  310. m_items.Clear();
  311. m_items = null;
  312. m_reordableList = null;
  313. m_dummyMaterial = null;
  314. m_dummyCommand = null;
  315. }
  316. }
  317. }