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.

333 lines
9.8 KiB

  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. Undo.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( ref string aboveItems, ref string bellowItems, string tabs )
  255. {
  256. int count = m_items.Count;
  257. for( int i = 0; i < count; i++ )
  258. {
  259. if( m_items[ i ].Location == UsePassLocation.Above )
  260. {
  261. aboveItems += tabs + string.Format( UseGrabFormatNewLine, m_items[ i ].Value );
  262. }
  263. else
  264. {
  265. bellowItems += tabs + string.Format( UseGrabFormatNewLine, m_items[ i ].Value );
  266. }
  267. }
  268. }
  269. public void BuildUsePassInfo( ref List<PropertyDataCollector> aboveItems, ref List<PropertyDataCollector> bellowItems )
  270. {
  271. int count = m_items.Count;
  272. for( int i = 0; i < count; i++ )
  273. {
  274. if( m_items[ i ].Location == UsePassLocation.Above )
  275. {
  276. aboveItems.Add( new PropertyDataCollector(-1,string.Format( UseGrabFormat, m_items[ i ].Value )));
  277. }
  278. else
  279. {
  280. bellowItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, m_items[ i ].Value ) ) );
  281. }
  282. }
  283. }
  284. //public string ModuleName { set { m_moduleName = value; } }
  285. public void Destroy()
  286. {
  287. m_owner = null;
  288. m_items.Clear();
  289. m_items = null;
  290. m_reordableList = null;
  291. m_dummyMaterial = null;
  292. m_dummyCommand = null;
  293. }
  294. }
  295. }