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.

415 lines
10 KiB

  1. using System;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.Collections.Generic;
  5. namespace AmplifyShaderEditor
  6. {
  7. [Serializable]
  8. public class CustomTagData
  9. {
  10. private const string TagFormat = "\"{0}\"=\"{1}\"";
  11. public string TagName;
  12. public string TagValue;
  13. public int TagId = -1;
  14. public bool TagFoldout = true;
  15. [SerializeField]
  16. private TemplateSpecialTags m_specialTag = TemplateSpecialTags.None;
  17. [SerializeField]
  18. private RenderType m_renderType = RenderType.Opaque;
  19. [SerializeField]
  20. private RenderQueue m_renderQueue = RenderQueue.Geometry;
  21. [SerializeField]
  22. private int m_renderQueueOffset = 0;
  23. public CustomTagData()
  24. {
  25. TagName = string.Empty;
  26. TagValue = string.Empty;
  27. m_specialTag = TemplateSpecialTags.None;
  28. m_renderType = RenderType.Opaque;
  29. m_renderQueue = RenderQueue.Geometry;
  30. m_renderQueueOffset = 0;
  31. }
  32. public CustomTagData( CustomTagData other )
  33. {
  34. TagName = other.TagName;
  35. TagValue = other.TagValue;
  36. TagId = other.TagId;
  37. TagFoldout = other.TagFoldout;
  38. m_specialTag = other.m_specialTag;
  39. m_renderType = other.m_renderType;
  40. m_renderQueue = other.m_renderQueue;
  41. m_renderQueueOffset = other.m_renderQueueOffset;
  42. }
  43. public void SetTagValue( params string[] value )
  44. {
  45. TagValue = value[ 0 ];
  46. switch( m_specialTag )
  47. {
  48. case TemplateSpecialTags.RenderType:
  49. m_renderType = TemplateHelperFunctions.StringToRenderType[ value[ 0 ] ];
  50. break;
  51. case TemplateSpecialTags.Queue:
  52. {
  53. if( value.Length == 2 )
  54. {
  55. m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ value[ 0 ] ];
  56. int.TryParse( value[ 1 ], out m_renderQueueOffset );
  57. }
  58. else
  59. {
  60. int indexPlus = value[ 0 ].IndexOf( '+' );
  61. if( indexPlus > 0 )
  62. {
  63. string[] args = value[ 0 ].Split( '+' );
  64. m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ args[ 0 ] ];
  65. int.TryParse( args[ 1 ], out m_renderQueueOffset );
  66. }
  67. else
  68. {
  69. int indexMinus = value[ 0 ].IndexOf( '-' );
  70. if( indexMinus > 0 )
  71. {
  72. string[] args = value[ 0 ].Split( '-' );
  73. m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ args[ 0 ] ];
  74. int.TryParse( args[ 1 ], out m_renderQueueOffset );
  75. m_renderQueueOffset *= -1;
  76. }
  77. else
  78. {
  79. m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ value[ 0 ] ];
  80. m_renderQueueOffset = 0;
  81. }
  82. }
  83. }
  84. BuildQueueTagValue();
  85. }
  86. break;
  87. }
  88. }
  89. void CheckSpecialTag()
  90. {
  91. if( TagName.Equals( Constants.RenderTypeHelperStr ) )
  92. {
  93. m_specialTag = TemplateSpecialTags.RenderType;
  94. m_renderType = TemplateHelperFunctions.StringToRenderType[ TagValue ];
  95. }
  96. else if( TagName.Equals( Constants.RenderQueueHelperStr ) )
  97. {
  98. m_specialTag = TemplateSpecialTags.Queue;
  99. SetTagValue( TagValue );
  100. }
  101. else
  102. {
  103. m_specialTag = TemplateSpecialTags.None;
  104. }
  105. }
  106. public CustomTagData( string name, string value, int id )
  107. {
  108. TagName = name;
  109. TagValue = value;
  110. TagId = id;
  111. CheckSpecialTag();
  112. }
  113. //Used on Template based shaders loading
  114. public CustomTagData( string data, int id )
  115. {
  116. TagId = id;
  117. string[] arr = data.Split( IOUtils.VALUE_SEPARATOR );
  118. if( arr.Length > 1 )
  119. {
  120. TagName = arr[ 0 ];
  121. TagValue = arr[ 1 ];
  122. }
  123. if( arr.Length > 2 )
  124. {
  125. m_specialTag = (TemplateSpecialTags)Enum.Parse( typeof( TemplateSpecialTags ), arr[ 2 ] );
  126. switch( m_specialTag )
  127. {
  128. case TemplateSpecialTags.RenderType:
  129. {
  130. m_renderType = (RenderType)Enum.Parse( typeof( RenderType ), TagValue );
  131. }
  132. break;
  133. case TemplateSpecialTags.Queue:
  134. {
  135. if( arr.Length == 4 )
  136. {
  137. m_renderQueue = (RenderQueue)Enum.Parse( typeof( RenderQueue ), TagValue );
  138. int.TryParse( arr[ 3 ], out m_renderQueueOffset );
  139. }
  140. BuildQueueTagValue();
  141. }
  142. break;
  143. }
  144. }
  145. else if( UIUtils.CurrentShaderVersion() < 15600 )
  146. {
  147. CheckSpecialTag();
  148. }
  149. }
  150. //Used on Standard Surface shaders loading
  151. public CustomTagData( string data )
  152. {
  153. string[] arr = data.Split( IOUtils.VALUE_SEPARATOR );
  154. if( arr.Length > 1 )
  155. {
  156. TagName = arr[ 0 ];
  157. TagValue = arr[ 1 ];
  158. }
  159. }
  160. public override string ToString()
  161. {
  162. switch( m_specialTag )
  163. {
  164. case TemplateSpecialTags.RenderType:
  165. return TagName + IOUtils.VALUE_SEPARATOR +
  166. TagValue + IOUtils.VALUE_SEPARATOR +
  167. m_specialTag;
  168. case TemplateSpecialTags.Queue:
  169. return TagName + IOUtils.VALUE_SEPARATOR +
  170. m_renderQueue.ToString() + IOUtils.VALUE_SEPARATOR +
  171. m_specialTag + IOUtils.VALUE_SEPARATOR +
  172. m_renderQueueOffset;
  173. }
  174. return TagName + IOUtils.VALUE_SEPARATOR + TagValue;
  175. }
  176. public string GenerateTag()
  177. {
  178. return string.Format( TagFormat, TagName, TagValue );
  179. }
  180. public void BuildQueueTagValue()
  181. {
  182. TagValue = m_renderQueue.ToString();
  183. if( m_renderQueueOffset > 0 )
  184. {
  185. TagValue += "+" + m_renderQueueOffset;
  186. }
  187. else if( m_renderQueueOffset < 0 )
  188. {
  189. TagValue += m_renderQueueOffset;
  190. }
  191. }
  192. public TemplateSpecialTags SpecialTag
  193. {
  194. get { return m_specialTag; }
  195. set
  196. {
  197. m_specialTag = value;
  198. switch( value )
  199. {
  200. case TemplateSpecialTags.RenderType:
  201. {
  202. TagValue = m_renderType.ToString();
  203. }
  204. break;
  205. case TemplateSpecialTags.Queue:
  206. {
  207. BuildQueueTagValue();
  208. }
  209. break;
  210. }
  211. }
  212. }
  213. public RenderType RenderType
  214. {
  215. get { return m_renderType; }
  216. set
  217. {
  218. m_renderType = value;
  219. TagValue = value.ToString();
  220. }
  221. }
  222. public RenderQueue RenderQueue
  223. {
  224. get { return m_renderQueue; }
  225. set { m_renderQueue = value; }
  226. }
  227. public int RenderQueueOffset
  228. {
  229. get { return m_renderQueueOffset; }
  230. set { m_renderQueueOffset = value; }
  231. }
  232. public bool IsValid { get { return ( !string.IsNullOrEmpty( TagValue ) && !string.IsNullOrEmpty( TagName ) ); } }
  233. }
  234. [Serializable]
  235. public class CustomTagsHelper
  236. {
  237. private const string CustomTagsStr = " Custom SubShader Tags";
  238. private const string TagNameStr = "Name";
  239. private const string TagValueStr = "Value";
  240. private const float ShaderKeywordButtonLayoutWidth = 15;
  241. private ParentNode m_currentOwner;
  242. [SerializeField]
  243. private List<CustomTagData> m_availableTags = new List<CustomTagData>();
  244. public void Draw( ParentNode owner )
  245. {
  246. m_currentOwner = owner;
  247. bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags;
  248. NodeUtils.DrawPropertyGroup( ref value, CustomTagsStr, DrawMainBody, DrawButtons );
  249. owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags = value;
  250. }
  251. void DrawButtons()
  252. {
  253. EditorGUILayout.Separator();
  254. // Add tag
  255. if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  256. {
  257. m_availableTags.Add( new CustomTagData() );
  258. EditorGUI.FocusTextInControl( null );
  259. }
  260. //Remove tag
  261. if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  262. {
  263. if( m_availableTags.Count > 0 )
  264. {
  265. m_availableTags.RemoveAt( m_availableTags.Count - 1 );
  266. EditorGUI.FocusTextInControl( null );
  267. }
  268. }
  269. }
  270. void DrawMainBody()
  271. {
  272. EditorGUILayout.Separator();
  273. int itemCount = m_availableTags.Count;
  274. if( itemCount == 0 )
  275. {
  276. EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info );
  277. }
  278. int markedToDelete = -1;
  279. float originalLabelWidth = EditorGUIUtility.labelWidth;
  280. for( int i = 0; i < itemCount; i++ )
  281. {
  282. m_availableTags[ i ].TagFoldout = m_currentOwner.EditorGUILayoutFoldout( m_availableTags[ i ].TagFoldout, string.Format( "[{0}] - {1}", i, m_availableTags[ i ].TagName ) );
  283. if( m_availableTags[ i ].TagFoldout )
  284. {
  285. EditorGUI.indentLevel += 1;
  286. EditorGUIUtility.labelWidth = 70;
  287. //Tag Name
  288. EditorGUI.BeginChangeCheck();
  289. m_availableTags[ i ].TagName = EditorGUILayout.TextField( TagNameStr, m_availableTags[ i ].TagName );
  290. if( EditorGUI.EndChangeCheck() )
  291. {
  292. m_availableTags[ i ].TagName = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagName );
  293. }
  294. //Tag Value
  295. EditorGUI.BeginChangeCheck();
  296. m_availableTags[ i ].TagValue = EditorGUILayout.TextField( TagValueStr, m_availableTags[ i ].TagValue );
  297. if( EditorGUI.EndChangeCheck() )
  298. {
  299. m_availableTags[ i ].TagValue = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagValue );
  300. }
  301. EditorGUIUtility.labelWidth = originalLabelWidth;
  302. EditorGUILayout.BeginHorizontal();
  303. {
  304. GUILayout.Label( " " );
  305. // Add new port
  306. if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  307. {
  308. m_availableTags.Insert( i + 1, new CustomTagData() );
  309. EditorGUI.FocusTextInControl( null );
  310. }
  311. //Remove port
  312. if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  313. {
  314. markedToDelete = i;
  315. }
  316. }
  317. EditorGUILayout.EndHorizontal();
  318. EditorGUI.indentLevel -= 1;
  319. }
  320. }
  321. if( markedToDelete > -1 )
  322. {
  323. if( m_availableTags.Count > markedToDelete )
  324. {
  325. m_availableTags.RemoveAt( markedToDelete );
  326. EditorGUI.FocusTextInControl( null );
  327. }
  328. }
  329. EditorGUILayout.Separator();
  330. }
  331. public void ReadFromString( ref uint index, ref string[] nodeParams )
  332. {
  333. int count = Convert.ToInt32( nodeParams[ index++ ] );
  334. for( int i = 0; i < count; i++ )
  335. {
  336. m_availableTags.Add( new CustomTagData( nodeParams[ index++ ] ) );
  337. }
  338. }
  339. public void WriteToString( ref string nodeInfo )
  340. {
  341. int tagsCount = m_availableTags.Count;
  342. IOUtils.AddFieldValueToString( ref nodeInfo, tagsCount );
  343. for( int i = 0; i < tagsCount; i++ )
  344. {
  345. IOUtils.AddFieldValueToString( ref nodeInfo, m_availableTags[ i ].ToString() );
  346. }
  347. }
  348. public string GenerateCustomTags()
  349. {
  350. int tagsCount = m_availableTags.Count;
  351. string result = tagsCount == 0 ? string.Empty : " ";
  352. for( int i = 0; i < tagsCount; i++ )
  353. {
  354. if( m_availableTags[ i ].IsValid )
  355. {
  356. result += m_availableTags[ i ].GenerateTag();
  357. if( i < tagsCount - 1 )
  358. {
  359. result += " ";
  360. }
  361. }
  362. }
  363. return result;
  364. }
  365. public void Destroy()
  366. {
  367. m_availableTags.Clear();
  368. m_availableTags = null;
  369. m_currentOwner = null;
  370. }
  371. }
  372. }