TemplateAdditionalDirectivesHelper.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using System;
  4. using System.IO;
  5. using System.Collections.Generic;
  6. using UnityEditor;
  7. using UnityEngine;
  8. using UnityEditorInternal;
  9. using System.Linq;
  10. namespace AmplifyShaderEditor
  11. {
  12. public enum AdditionalLineType
  13. {
  14. Include,
  15. Define,
  16. Pragma,
  17. Custom
  18. }
  19. public enum AdditionalContainerOrigin
  20. {
  21. Native,
  22. ShaderFunction,
  23. Custom
  24. }
  25. [Serializable]
  26. public class AdditionalDirectiveContainerSaveItem
  27. {
  28. public AdditionalLineType LineType = AdditionalLineType.Include;
  29. public string LineValue = string.Empty;
  30. public bool GUIDToggle = false;
  31. public string GUIDValue = string.Empty;
  32. public bool ShowConditionals = false;
  33. public int VersionMin = 0;
  34. public int VersionMax = 0;
  35. public string Passes = string.Empty;
  36. public AdditionalContainerOrigin Origin = AdditionalContainerOrigin.Custom;
  37. public AdditionalDirectiveContainerSaveItem( AdditionalDirectiveContainer container )
  38. {
  39. LineType = container.LineType;
  40. LineValue = container.LineValue;
  41. GUIDToggle = container.GUIDToggle;
  42. GUIDValue = container.GUIDValue;
  43. ShowConditionals = container.ShowConditionals;
  44. VersionMin = container.VersionMin;
  45. VersionMax = container.VersionMax;
  46. Passes = container.Passes;
  47. Origin = container.Origin;
  48. }
  49. }
  50. [Serializable]
  51. public class AdditionalDirectiveContainer : ScriptableObject
  52. {
  53. public AdditionalLineType LineType = AdditionalLineType.Include;
  54. public string LineValue = string.Empty;
  55. public bool GUIDToggle = false;
  56. public string GUIDValue = string.Empty;
  57. public bool ShowConditionals = false;
  58. public int VersionMin = 0;
  59. public int VersionMax = 0;
  60. public string Passes = string.Empty;
  61. public AdditionalContainerOrigin Origin = AdditionalContainerOrigin.Custom;
  62. public TextAsset LibObject = null;
  63. public string OwnerId = string.Empty;
  64. public void Init( string ownerId, AdditionalDirectiveContainer item )
  65. {
  66. LineType = item.LineType;
  67. LineValue = item.LineValue;
  68. GUIDToggle = item.GUIDToggle;
  69. GUIDValue = item.GUIDValue;
  70. ShowConditionals = item.ShowConditionals;
  71. VersionMin = item.VersionMin;
  72. VersionMax = item.VersionMax;
  73. Passes = item.Passes;
  74. Origin = item.Origin;
  75. LibObject = item.LibObject;
  76. OwnerId = ownerId;
  77. }
  78. public void Init( AdditionalDirectiveContainerSaveItem item )
  79. {
  80. LineType = item.LineType;
  81. LineValue = item.LineValue;
  82. GUIDToggle = item.GUIDToggle;
  83. GUIDValue = item.GUIDValue;
  84. ShowConditionals = item.ShowConditionals;
  85. VersionMin = item.VersionMin;
  86. VersionMax = item.VersionMax;
  87. Passes = item.Passes;
  88. Origin = item.Origin;
  89. if( GUIDToggle )
  90. {
  91. LibObject = AssetDatabase.LoadAssetAtPath<TextAsset>( AssetDatabase.GUIDToAssetPath( GUIDValue ) );
  92. }
  93. }
  94. public void OnDestroy()
  95. {
  96. //Debug.Log( "Destoying directives" );
  97. LibObject = null;
  98. }
  99. public string Value
  100. {
  101. get
  102. {
  103. switch( LineType )
  104. {
  105. case AdditionalLineType.Include:
  106. {
  107. if( GUIDToggle )
  108. {
  109. string shaderPath = AssetDatabase.GUIDToAssetPath( GUIDValue );
  110. if( !string.IsNullOrEmpty( shaderPath ) )
  111. return shaderPath;
  112. }
  113. return LineValue;
  114. }
  115. case AdditionalLineType.Define: return LineValue;
  116. case AdditionalLineType.Pragma: return LineValue;
  117. }
  118. return LineValue;
  119. }
  120. }
  121. public string FormattedValue
  122. {
  123. get
  124. {
  125. switch( LineType )
  126. {
  127. case AdditionalLineType.Include:
  128. {
  129. if( GUIDToggle )
  130. {
  131. string shaderPath = AssetDatabase.GUIDToAssetPath( GUIDValue );
  132. if( !string.IsNullOrEmpty( shaderPath ) )
  133. return string.Format( Constants.IncludeFormat, shaderPath );
  134. }
  135. return string.Format( Constants.IncludeFormat, LineValue );
  136. }
  137. case AdditionalLineType.Define:
  138. return string.Format( Constants.DefineFormat, LineValue );
  139. case AdditionalLineType.Pragma:
  140. return string.Format( Constants.PragmaFormat, LineValue );
  141. }
  142. return LineValue;
  143. }
  144. }
  145. }
  146. public enum ReordableAction
  147. {
  148. None,
  149. Add,
  150. Remove
  151. }
  152. [Serializable]
  153. public sealed class TemplateAdditionalDirectivesHelper : TemplateModuleParent
  154. {
  155. private string NativeFoldoutStr = "Native";
  156. [SerializeField]
  157. private List<AdditionalDirectiveContainer> m_additionalDirectives = new List<AdditionalDirectiveContainer>();
  158. [SerializeField]
  159. private List<AdditionalDirectiveContainer> m_shaderFunctionDirectives = new List<AdditionalDirectiveContainer>();
  160. [SerializeField]
  161. private List<string> m_nativeDirectives = new List<string>();
  162. [SerializeField]
  163. private int m_nativeDirectivesIndex = -1;
  164. [SerializeField]
  165. private bool m_nativeDirectivesFoldout = false;
  166. //ONLY USED BY SHADER FUNCTIONS
  167. // Since AdditionalDirectiveContainer must be a ScriptableObject because of serialization shenanigans it will not serialize the info correctly into the shader function when saving it into a file ( it only saves the id )
  168. // For it to properly work, each AdditionalDirectiveContainer should be added to the SF asset, but that would make it to have children ( which are seen on the project inspector )
  169. // Must revisit this later on and come up with a proper solution
  170. [SerializeField]
  171. private List<AdditionalDirectiveContainerSaveItem> m_directivesSaveItems = new List<AdditionalDirectiveContainerSaveItem>();
  172. private ReordableAction m_actionType = ReordableAction.None;
  173. private int m_actionIndex = 0;
  174. private ReorderableList m_reordableList = null;
  175. private GUIStyle m_propertyAdjustment;
  176. private UndoParentNode m_currOwner;
  177. private Rect m_nativeRect = Rect.zero;
  178. public TemplateAdditionalDirectivesHelper( string moduleName ) : base( moduleName ) { }
  179. //public void AddShaderFunctionItem( AdditionalLineType type, string item )
  180. //{
  181. // UpdateShaderFunctionDictionary();
  182. // string id = type + item;
  183. // if( !m_shaderFunctionDictionary.ContainsKey( id ) )
  184. // {
  185. // AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  186. // newItem.LineType = type;
  187. // newItem.LineValue = item;
  188. // newItem.hideFlags = HideFlags.HideAndDontSave;
  189. // m_shaderFunctionDirectives.Add( newItem );
  190. // m_shaderFunctionDictionary.Add( id, newItem );
  191. // }
  192. //}
  193. public void AddShaderFunctionItems( string ownerOutputId, List<AdditionalDirectiveContainer> functionList )
  194. {
  195. RemoveShaderFunctionItems( ownerOutputId );
  196. if( functionList.Count > 0 )
  197. {
  198. for( int i = 0; i < functionList.Count; i++ )
  199. {
  200. AdditionalDirectiveContainer item = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  201. item.Init( ownerOutputId, functionList[ i ] );
  202. item.hideFlags = HideFlags.HideAndDontSave;
  203. m_shaderFunctionDirectives.Add( item );
  204. }
  205. }
  206. //if( functionList.Count > 0 )
  207. //{
  208. // m_shaderFunctionDirectives.AddRange( functionList );
  209. //}
  210. }
  211. public void RemoveShaderFunctionItems( string ownerOutputId/*, List<AdditionalDirectiveContainer> functionList */)
  212. {
  213. List<AdditionalDirectiveContainer> list = m_shaderFunctionDirectives.FindAll( ( x ) => x.OwnerId.Equals( ownerOutputId ));
  214. for( int i = 0; i < list.Count; i++ )
  215. {
  216. m_shaderFunctionDirectives.Remove( list[ i ] );
  217. ScriptableObject.DestroyImmediate( list[ i ] );
  218. }
  219. list.Clear();
  220. list = null;
  221. //for( int i = 0; i < functionList.Count; i++ )
  222. //{
  223. // m_shaderFunctionDirectives.Remove( functionList[ i ] );
  224. //}
  225. }
  226. //public void RemoveShaderFunctionItem( AdditionalLineType type, string item )
  227. //{
  228. // m_shaderFunctionDirectives.RemoveAll( x => x.LineType == type && x.LineValue.Equals( item ) );
  229. //}
  230. public void AddItems( AdditionalLineType type, List<string> items )
  231. {
  232. int count = items.Count;
  233. for( int i = 0; i < count; i++ )
  234. {
  235. AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  236. newItem.LineType = type;
  237. newItem.LineValue = items[ i ];
  238. newItem.hideFlags = HideFlags.HideAndDontSave;
  239. m_additionalDirectives.Add( newItem );
  240. }
  241. UpdateNativeIndex();
  242. }
  243. public void AddNativeContainer()
  244. {
  245. if( m_nativeDirectives.Count > 0 )
  246. {
  247. if( m_additionalDirectives.FindIndex( x => x.Origin.Equals( AdditionalContainerOrigin.Native ) ) == -1 )
  248. {
  249. AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  250. newItem.Origin = AdditionalContainerOrigin.Native;
  251. newItem.hideFlags = HideFlags.HideAndDontSave;
  252. //m_additionalDirectives.Add( newItem );
  253. //m_nativeDirectivesIndex = m_additionalDirectives.Count - 1;
  254. m_additionalDirectives.Insert( 0, newItem );
  255. m_nativeDirectivesIndex = 0;
  256. }
  257. }
  258. }
  259. public void FillNativeItems( List<string> nativeItems )
  260. {
  261. m_nativeDirectives.Clear();
  262. m_nativeDirectives.AddRange( nativeItems );
  263. AddNativeContainer();
  264. }
  265. void DrawNativeItems()
  266. {
  267. EditorGUILayout.Separator();
  268. EditorGUI.indentLevel++;
  269. int count = m_nativeDirectives.Count;
  270. for( int i = 0; i < count; i++ )
  271. {
  272. EditorGUILayout.LabelField( m_nativeDirectives[ i ] );
  273. }
  274. EditorGUI.indentLevel--;
  275. EditorGUILayout.Separator();
  276. }
  277. void DrawNativeItemsRect()
  278. {
  279. int count = m_nativeDirectives.Count;
  280. m_nativeRect.y += EditorGUIUtility.singleLineHeight;
  281. for( int i = 0; i < count; i++ )
  282. {
  283. EditorGUI.LabelField( m_nativeRect, m_nativeDirectives[ i ] );
  284. m_nativeRect.y += EditorGUIUtility.singleLineHeight;
  285. }
  286. }
  287. void DrawButtons()
  288. {
  289. EditorGUILayout.Separator();
  290. // Add keyword
  291. if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( Constants.PlusMinusButtonLayoutWidth ) ) )
  292. {
  293. AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  294. newItem.hideFlags = HideFlags.HideAndDontSave;
  295. m_additionalDirectives.Add( newItem );
  296. UpdateNativeIndex();
  297. EditorGUI.FocusTextInControl( null );
  298. m_isDirty = true;
  299. }
  300. //Remove keyword
  301. if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( Constants.PlusMinusButtonLayoutWidth ) ) )
  302. {
  303. if( m_additionalDirectives.Count > 0 )
  304. {
  305. AdditionalDirectiveContainer itemToDelete = m_additionalDirectives[ m_additionalDirectives.Count - 1 ];
  306. m_additionalDirectives.RemoveAt( m_additionalDirectives.Count - 1 );
  307. ScriptableObject.DestroyImmediate( itemToDelete );
  308. EditorGUI.FocusTextInControl( null );
  309. }
  310. m_isDirty = true;
  311. }
  312. }
  313. void DrawConditionals( Rect rect, AdditionalDirectiveContainer directive )
  314. {
  315. var tog = rect;
  316. tog.width = 15;
  317. tog.x += 5;
  318. tog.y -= ( tog.height - ( EditorGUIUtility.singleLineHeight + 5 ) ) * 0.5f + 1;
  319. tog.xMin += 2;
  320. tog.yMin -= 2;
  321. bool value = GUI.Toggle( tog, directive.ShowConditionals, "", UIUtils.MenuItemToggleStyle );
  322. if ( Event.current.button == Constants.FoldoutMouseId )
  323. {
  324. directive.ShowConditionals = value;
  325. }
  326. if ( directive.ShowConditionals )
  327. {
  328. const int labelWidth = 70;
  329. const int versionEditWidth = 55;
  330. Rect condPos = rect;
  331. condPos.height = EditorGUIUtility.singleLineHeight;
  332. // List of passes to apply directive
  333. directive.Passes = ( directive.Passes != null ) ? directive.Passes : string.Empty;
  334. condPos.x = rect.x + 23;
  335. condPos.y += EditorGUIUtility.singleLineHeight + 2;
  336. condPos.width = labelWidth;
  337. EditorGUI.LabelField( condPos, new GUIContent( "Passes", "Template pass names separated by semicolon (;). Empty means it will be included in all passes." ) );
  338. condPos.x += labelWidth;
  339. condPos.xMax = rect.xMax + 1;
  340. directive.Passes = m_currOwner.EditorGUITextField( condPos, string.Empty, directive.Passes );
  341. // Range of SRP versions to apply directive
  342. condPos.x = rect.x + 23;
  343. condPos.y += EditorGUIUtility.singleLineHeight + 2;
  344. condPos.width = labelWidth;
  345. EditorGUI.LabelField( condPos, new GUIContent( "SRPVersion", "Valid SRP version numbers must have 6 digits and be equal or higher than 100000, the lowest supported version." ) );
  346. condPos.x += labelWidth;
  347. condPos.width = versionEditWidth;
  348. string minText = ( directive.VersionMin == 0 ) ? string.Empty : directive.VersionMin.ToString();
  349. minText = m_currOwner.EditorGUITextField( condPos, string.Empty, minText );
  350. directive.VersionMin = int.TryParse( minText, out int min ) ? min : 0;
  351. condPos.x += versionEditWidth + 5;
  352. EditorGUI.LabelField( condPos, "to" );
  353. condPos.x += 20;
  354. string maxText = ( directive.VersionMax == 0 ) ? string.Empty : directive.VersionMax.ToString();
  355. maxText = m_currOwner.EditorGUITextField( condPos, string.Empty, maxText );
  356. directive.VersionMax = int.TryParse( maxText, out int max ) ? max : 0;
  357. condPos.x = rect.x + 40;
  358. }
  359. }
  360. public override void Draw( UndoParentNode currOwner, bool style = true )
  361. {
  362. m_currOwner = currOwner;
  363. if( m_reordableList == null )
  364. {
  365. m_reordableList = new ReorderableList( m_additionalDirectives, typeof( AdditionalDirectiveContainer ), true, false, false, false )
  366. {
  367. headerHeight = 0,
  368. footerHeight = 0,
  369. showDefaultBackground = false,
  370. elementHeightCallback = ( index ) =>
  371. {
  372. if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native && m_nativeDirectivesFoldout )
  373. {
  374. return ( m_nativeDirectives.Count + 1 ) * ( EditorGUIUtility.singleLineHeight ) + 5;
  375. }
  376. int lineCount = ( m_additionalDirectives[ index ].ShowConditionals ) ? 3 : 1;
  377. return EditorGUIUtility.singleLineHeight * lineCount + 5;
  378. },
  379. drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) =>
  380. {
  381. if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native && m_nativeDirectivesFoldout )
  382. {
  383. rect.height = ( m_nativeDirectives.Count + 1 ) * ( EditorGUIUtility.singleLineHeight ) + 5;
  384. }
  385. if( m_additionalDirectives[ index ] != null )
  386. {
  387. float labelWidthStyleAdjust = 0;
  388. if ( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native )
  389. {
  390. rect.xMin -= 5;
  391. rect.xMax += 1;
  392. m_nativeRect = rect;
  393. m_nativeRect.y -= ( m_nativeRect.height - ( EditorGUIUtility.singleLineHeight + 5 ) ) * 0.5f;
  394. m_nativeRect.xMin += 2;
  395. m_nativeRect.xMax -= 2;
  396. m_nativeRect.yMax -= 2;
  397. NodeUtils.DrawNestedPropertyGroup( ref m_nativeDirectivesFoldout, rect, NativeFoldoutStr, DrawNativeItemsRect, 4 );
  398. return;
  399. }
  400. else
  401. {
  402. rect.xMin -= 10;
  403. labelWidthStyleAdjust = 15;
  404. DrawConditionals( rect, m_additionalDirectives[ index ] );
  405. }
  406. const int conditionalsOffset = 20;
  407. rect.x += conditionalsOffset;
  408. float popUpWidth = 88;
  409. float widthAdjust = m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ? -14 : 0;
  410. widthAdjust -= conditionalsOffset;
  411. Rect popupPos = new Rect( rect.x, rect.y, popUpWidth, EditorGUIUtility.singleLineHeight );
  412. Rect GUIDTogglePos = m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ? new Rect( rect.x + rect.width - 3 * Constants.PlusMinusButtonLayoutWidth - conditionalsOffset + 3, rect.y, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth ) : new Rect();
  413. Rect buttonPlusPos = new Rect( rect.x + rect.width - 2 * Constants.PlusMinusButtonLayoutWidth - conditionalsOffset + 1, rect.y - 2, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth );
  414. Rect buttonMinusPos = new Rect( rect.x + rect.width - Constants.PlusMinusButtonLayoutWidth - conditionalsOffset + 1, rect.y - 2, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth );
  415. float labelWidthBuffer = EditorGUIUtility.labelWidth;
  416. Rect labelPos = new Rect( rect.x + popupPos.width - labelWidthStyleAdjust, rect.y, labelWidthStyleAdjust + rect.width - popupPos.width - buttonPlusPos.width - buttonMinusPos.width + widthAdjust, EditorGUIUtility.singleLineHeight );
  417. m_additionalDirectives[ index ].LineType = (AdditionalLineType)m_currOwner.EditorGUIEnumPopup( popupPos, m_additionalDirectives[ index ].LineType );
  418. if( m_additionalDirectives[ index ].LineType == AdditionalLineType.Include )
  419. {
  420. if( m_additionalDirectives[ index ].GUIDToggle )
  421. {
  422. //if( m_additionalDirectives[ index ].LibObject == null && !string.IsNullOrEmpty( m_additionalDirectives[ index ].GUIDValue ) )
  423. //{
  424. // m_additionalDirectives[ index ].LibObject = AssetDatabase.LoadAssetAtPath<TextAsset>( AssetDatabase.GUIDToAssetPath( m_additionalDirectives[ index ].GUIDValue ) );
  425. //}
  426. EditorGUI.BeginChangeCheck();
  427. TextAsset obj = m_currOwner.EditorGUIObjectField( labelPos, m_additionalDirectives[ index ].LibObject, typeof( TextAsset ), false ) as TextAsset;
  428. if( EditorGUI.EndChangeCheck() )
  429. {
  430. string pathName = AssetDatabase.GetAssetPath( obj );
  431. string extension = Path.GetExtension( pathName );
  432. extension = extension.ToLower();
  433. if( extension.Equals( ".cginc" ) || extension.Equals( ".hlsl" ) )
  434. {
  435. m_additionalDirectives[ index ].LibObject = obj;
  436. m_additionalDirectives[ index ].GUIDValue = AssetDatabase.AssetPathToGUID( pathName );
  437. }
  438. }
  439. }
  440. else
  441. {
  442. m_additionalDirectives[ index ].LineValue = m_currOwner.EditorGUITextField( labelPos, string.Empty, m_additionalDirectives[ index ].LineValue );
  443. }
  444. if( GUI.Button( GUIDTogglePos, m_additionalDirectives[ index ].GUIDToggle ? UIUtils.FloatIntIconOFF : UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF ) )
  445. m_additionalDirectives[ index ].GUIDToggle = !m_additionalDirectives[ index ].GUIDToggle;
  446. }
  447. else
  448. {
  449. m_additionalDirectives[ index ].LineValue = m_currOwner.EditorGUITextField( labelPos, string.Empty, m_additionalDirectives[ index ].LineValue );
  450. }
  451. //NodeUtils.DrawNestedPropertyGroup( ref m_additionalDirectives[ index ].ShowConditionals, rect, "TEMP", DrawConditionals, 4 );
  452. if ( GUI.Button( buttonPlusPos, string.Empty, UIUtils.PlusStyle ) )
  453. {
  454. m_actionType = ReordableAction.Add;
  455. m_actionIndex = index;
  456. }
  457. if( GUI.Button( buttonMinusPos, string.Empty, UIUtils.MinusStyle ) )
  458. {
  459. m_actionType = ReordableAction.Remove;
  460. m_actionIndex = index;
  461. }
  462. }
  463. },
  464. onReorderCallback = ( ReorderableList list ) =>
  465. {
  466. UpdateNativeIndex();
  467. }
  468. };
  469. }
  470. if( m_actionType != ReordableAction.None )
  471. {
  472. switch( m_actionType )
  473. {
  474. case ReordableAction.Add:
  475. {
  476. AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  477. newItem.hideFlags = HideFlags.HideAndDontSave;
  478. m_additionalDirectives.Insert( m_actionIndex + 1, newItem );
  479. }
  480. break;
  481. case ReordableAction.Remove:
  482. AdditionalDirectiveContainer itemToDelete = m_additionalDirectives[ m_actionIndex ];
  483. m_additionalDirectives.RemoveAt( m_actionIndex );
  484. ScriptableObject.DestroyImmediate( itemToDelete );
  485. break;
  486. }
  487. m_isDirty = true;
  488. m_actionType = ReordableAction.None;
  489. EditorGUI.FocusTextInControl( null );
  490. }
  491. bool foldoutValue = currOwner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDirectives;
  492. if( style )
  493. {
  494. NodeUtils.DrawPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons );
  495. }
  496. else
  497. {
  498. NodeUtils.DrawNestedPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons );
  499. }
  500. currOwner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDirectives = foldoutValue;
  501. }
  502. void DrawReordableList()
  503. {
  504. if( m_reordableList != null )
  505. {
  506. if( m_propertyAdjustment == null )
  507. {
  508. m_propertyAdjustment = new GUIStyle();
  509. m_propertyAdjustment.padding.left = 17;
  510. }
  511. //EditorGUILayout.BeginVertical( m_propertyAdjustment );
  512. EditorGUILayout.Space();
  513. if( m_nativeDirectives.Count > 0 )
  514. {
  515. //NodeUtils.DrawNestedPropertyGroup( ref m_nativeDirectivesFoldout, NativeFoldoutStr, DrawNativeItems, 4 );
  516. }
  517. if( m_additionalDirectives.Count == 0 )
  518. {
  519. EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info );
  520. }
  521. else
  522. {
  523. m_reordableList.DoLayoutList();
  524. }
  525. EditorGUILayout.Space();
  526. //EditorGUILayout.EndVertical();
  527. }
  528. }
  529. public void AddAllToDataCollector( ref MasterNodeDataCollector dataCollector, TemplatePass pass, TemplateIncludePragmaContainter nativesContainer )
  530. {
  531. //List<AdditionalDirectiveContainer> list = m_additionalDirectives;
  532. //int count = list.FindIndex( x => x.Origin.Equals( AdditionalContainerOrigin.Native ) );
  533. //for( int i = 0; i < count; i++ )
  534. //{
  535. // switch( list[ i ].LineType )
  536. // {
  537. // case AdditionalLineType.Include:
  538. // {
  539. // string value = list[ i ].Value;
  540. // if( !string.IsNullOrEmpty( value ) &&
  541. // !nativesContainer.HasInclude( value ) )
  542. // {
  543. // dataCollector.AddToMisc( list[ i ].FormattedValue );
  544. // }
  545. // }
  546. // break;
  547. // case AdditionalLineType.Define:
  548. // {
  549. // if( !string.IsNullOrEmpty( list[ i ].LineValue ) &&
  550. // !nativesContainer.HasDefine( list[ i ].LineValue ) )
  551. // {
  552. // dataCollector.AddToMisc( list[ i ].FormattedValue );
  553. // }
  554. // }
  555. // break;
  556. // case AdditionalLineType.Pragma:
  557. // {
  558. // if( !string.IsNullOrEmpty( list[ i ].LineValue ) &&
  559. // !nativesContainer.HasPragma( list[ i ].LineValue ) )
  560. // {
  561. // dataCollector.AddToMisc( list[ i ].FormattedValue );
  562. // }
  563. // }
  564. // break;
  565. // default:
  566. // case AdditionalLineType.Custom:
  567. // dataCollector.AddToMisc( list[ i ].LineValue );
  568. // break;
  569. // }
  570. //}
  571. AddToDataCollector( ref dataCollector, pass, nativesContainer, false );
  572. AddToDataCollector( ref dataCollector, pass, nativesContainer, true );
  573. }
  574. public void AddAllToDataCollector( ref MasterNodeDataCollector dataCollector )
  575. {
  576. AddToDataCollector( ref dataCollector, null, false );
  577. AddToDataCollector( ref dataCollector, null, true );
  578. }
  579. bool TestConditionals( TemplatePass pass, AdditionalDirectiveContainer directive )
  580. {
  581. bool isSRP = ASEPackageManagerHelper.CurrentSRPVersion > 0;
  582. if ( isSRP && directive.VersionMin != 0 && ASEPackageManagerHelper.CurrentSRPVersion < directive.VersionMin )
  583. {
  584. return false;
  585. }
  586. if ( isSRP && directive.VersionMax != 0 && ASEPackageManagerHelper.CurrentSRPVersion > directive.VersionMax )
  587. {
  588. return false;
  589. }
  590. if ( pass != null && !string.IsNullOrEmpty( directive.Passes ) )
  591. {
  592. string[] passes = directive.Passes.Split( ';' );
  593. if ( !passes.Contains( pass.PassNameContainer.Data ) )
  594. {
  595. return false;
  596. }
  597. }
  598. return true;
  599. }
  600. void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplatePass pass, TemplateIncludePragmaContainter nativesContainer, bool fromSF )
  601. {
  602. List<AdditionalDirectiveContainer> list = fromSF ? m_shaderFunctionDirectives : m_additionalDirectives;
  603. int count = list.Count;
  604. for( int i = 0; i < count; i++ )
  605. {
  606. AdditionalDirectiveContainer directive = list[ i ];
  607. int orderIdx = fromSF ? 1 : ( i > m_nativeDirectivesIndex ? 1 : -1 );
  608. if ( !TestConditionals( pass, directive ) )
  609. {
  610. continue;
  611. }
  612. switch( directive.LineType )
  613. {
  614. case AdditionalLineType.Include:
  615. {
  616. string value = directive.Value;
  617. if( !string.IsNullOrEmpty( value ) &&
  618. !nativesContainer.HasInclude( value ) )
  619. {
  620. dataCollector.AddToDirectives( directive.FormattedValue, orderIdx );
  621. }
  622. }
  623. break;
  624. case AdditionalLineType.Define:
  625. {
  626. if( !string.IsNullOrEmpty( directive.LineValue ) &&
  627. !nativesContainer.HasDefine( directive.LineValue ) )
  628. {
  629. dataCollector.AddToDirectives( directive.FormattedValue, orderIdx );
  630. }
  631. }
  632. break;
  633. case AdditionalLineType.Pragma:
  634. {
  635. if( !string.IsNullOrEmpty( directive.LineValue ) &&
  636. !nativesContainer.HasPragma( directive.LineValue ) )
  637. {
  638. dataCollector.AddToDirectives( directive.FormattedValue, orderIdx );
  639. }
  640. }
  641. break;
  642. default:
  643. case AdditionalLineType.Custom:
  644. dataCollector.AddToDirectives( directive.LineValue, orderIdx );
  645. break;
  646. }
  647. }
  648. }
  649. void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplatePass pass, bool fromSF )
  650. {
  651. List<AdditionalDirectiveContainer> list = fromSF ? m_shaderFunctionDirectives : m_additionalDirectives;
  652. int orderIdx = 1;
  653. int count = list.Count;
  654. for( int i = 0; i < count; i++ )
  655. {
  656. AdditionalDirectiveContainer directive = list[ i ];
  657. if ( !TestConditionals( pass, directive ) )
  658. {
  659. continue;
  660. }
  661. switch ( directive.LineType )
  662. {
  663. case AdditionalLineType.Include:
  664. {
  665. string value = directive.FormattedValue;
  666. if( !string.IsNullOrEmpty( value ) )
  667. {
  668. dataCollector.AddToDirectives( value, orderIdx );
  669. }
  670. }
  671. break;
  672. case AdditionalLineType.Define:
  673. {
  674. if( !string.IsNullOrEmpty( directive.LineValue ) )
  675. {
  676. dataCollector.AddToDirectives( directive.FormattedValue, orderIdx );
  677. }
  678. }
  679. break;
  680. case AdditionalLineType.Pragma:
  681. {
  682. if( !string.IsNullOrEmpty( directive.LineValue ) )
  683. {
  684. dataCollector.AddToDirectives( directive.FormattedValue, orderIdx );
  685. }
  686. }
  687. break;
  688. default:
  689. case AdditionalLineType.Custom:
  690. dataCollector.AddToDirectives( directive.LineValue, orderIdx );
  691. break;
  692. }
  693. }
  694. }
  695. public override void ReadFromString( ref uint index, ref string[] nodeParams )
  696. {
  697. try
  698. {
  699. m_nativeDirectivesIndex = -1;
  700. int count = Convert.ToInt32( nodeParams[ index++ ] );
  701. m_additionalDirectives.Clear();
  702. for( int i = 0; i < count; i++ )
  703. {
  704. AdditionalLineType lineType = (AdditionalLineType)Enum.Parse( typeof( AdditionalLineType ), nodeParams[ index++ ] );
  705. string lineValue = nodeParams[ index++ ];
  706. AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  707. newItem.hideFlags = HideFlags.HideAndDontSave;
  708. newItem.LineType = lineType;
  709. newItem.LineValue = lineValue.Replace( Constants.SemiColonSeparator, ';' );
  710. if( UIUtils.CurrentShaderVersion() > 15607 )
  711. {
  712. newItem.GUIDToggle = Convert.ToBoolean( nodeParams[ index++ ] );
  713. newItem.GUIDValue = nodeParams[ index++ ];
  714. if( newItem.GUIDToggle )
  715. {
  716. newItem.LibObject = AssetDatabase.LoadAssetAtPath<TextAsset>( AssetDatabase.GUIDToAssetPath( newItem.GUIDValue ) );
  717. if( newItem.LibObject == null )
  718. {
  719. Debug.LogWarning( "Include file not found with GUID " + newItem.GUIDValue );
  720. }
  721. }
  722. }
  723. AdditionalContainerOrigin origin = AdditionalContainerOrigin.Custom;
  724. if( UIUtils.CurrentShaderVersion() > 16902 )
  725. {
  726. origin = (AdditionalContainerOrigin)Enum.Parse( typeof( AdditionalContainerOrigin ), nodeParams[ index++ ] );
  727. newItem.Origin = origin;
  728. }
  729. if ( UIUtils.CurrentShaderVersion() > 19103 )
  730. {
  731. newItem.ShowConditionals = Convert.ToBoolean( nodeParams[ index++ ] );
  732. newItem.VersionMin = Convert.ToInt32( nodeParams[ index++ ] );
  733. newItem.VersionMax = Convert.ToInt32( nodeParams[ index++ ] );
  734. newItem.Passes = nodeParams[ index++ ];
  735. newItem.Passes.Replace( Constants.SemiColonSeparator, ';' );
  736. }
  737. m_additionalDirectives.Add( newItem );
  738. if( origin == AdditionalContainerOrigin.Native )
  739. {
  740. m_nativeDirectivesIndex = i;
  741. }
  742. }
  743. AddNativeContainer();
  744. }
  745. catch( Exception e )
  746. {
  747. Debug.LogException( e );
  748. }
  749. }
  750. public override void WriteToString( ref string nodeInfo )
  751. {
  752. if( m_additionalDirectives.Count == 1 && m_additionalDirectives[ 0 ].Origin == AdditionalContainerOrigin.Native )
  753. {
  754. IOUtils.AddFieldValueToString( ref nodeInfo, 0 );
  755. return;
  756. }
  757. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives.Count );
  758. for( int i = 0; i < m_additionalDirectives.Count; i++ )
  759. {
  760. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].LineType );
  761. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].LineValue.Replace( ';', Constants.SemiColonSeparator ) );
  762. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].GUIDToggle );
  763. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].GUIDValue );
  764. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].Origin );
  765. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].ShowConditionals );
  766. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].VersionMin );
  767. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].VersionMax );
  768. IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].Passes.Replace( ';', Constants.SemiColonSeparator ) );
  769. }
  770. }
  771. // read comment on m_directivesSaveItems declaration
  772. public void UpdateSaveItemsFromDirectives()
  773. {
  774. bool foundNull = false;
  775. m_directivesSaveItems.Clear();
  776. for( int i = 0; i < m_additionalDirectives.Count; i++ )
  777. {
  778. if( m_additionalDirectives[ i ] != null )
  779. {
  780. m_directivesSaveItems.Add( new AdditionalDirectiveContainerSaveItem( m_additionalDirectives[ i ] ) );
  781. }
  782. else
  783. {
  784. foundNull = true;
  785. }
  786. }
  787. if( foundNull )
  788. {
  789. m_additionalDirectives.RemoveAll( item => item == null );
  790. }
  791. }
  792. public void CleanNullDirectives()
  793. {
  794. m_additionalDirectives.RemoveAll( item => item == null );
  795. }
  796. public void ResetDirectivesOrigin()
  797. {
  798. for( int i = 0; i < m_directivesSaveItems.Count; i++ )
  799. {
  800. m_directivesSaveItems[ i ].Origin = AdditionalContainerOrigin.Custom;
  801. }
  802. }
  803. // read comment on m_directivesSaveItems declaration
  804. public void UpdateDirectivesFromSaveItems()
  805. {
  806. if( m_directivesSaveItems.Count > 0 )
  807. {
  808. for( int i = 0; i < m_additionalDirectives.Count; i++ )
  809. {
  810. if( m_additionalDirectives[ i ] != null )
  811. ScriptableObject.DestroyImmediate( m_additionalDirectives[ i ] );
  812. }
  813. m_additionalDirectives.Clear();
  814. for( int i = 0; i < m_directivesSaveItems.Count; i++ )
  815. {
  816. AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
  817. newItem.hideFlags = HideFlags.HideAndDontSave;
  818. newItem.Init( m_directivesSaveItems[ i ] );
  819. m_additionalDirectives.Add( newItem );
  820. }
  821. UpdateNativeIndex();
  822. //m_directivesSaveItems.Clear();
  823. }
  824. }
  825. void UpdateNativeIndex()
  826. {
  827. m_nativeDirectivesIndex = -1;
  828. int count = m_additionalDirectives.Count;
  829. for( int i = 0; i < count; i++ )
  830. {
  831. if( m_additionalDirectives[ i ].Origin == AdditionalContainerOrigin.Native )
  832. {
  833. m_nativeDirectivesIndex = i;
  834. break;
  835. }
  836. }
  837. }
  838. public override void Destroy()
  839. {
  840. base.Destroy();
  841. m_nativeDirectives.Clear();
  842. m_nativeDirectives = null;
  843. for( int i = 0; i < m_additionalDirectives.Count; i++ )
  844. {
  845. ScriptableObject.DestroyImmediate( m_additionalDirectives[ i ] );
  846. }
  847. m_additionalDirectives.Clear();
  848. m_additionalDirectives = null;
  849. for( int i = 0; i < m_shaderFunctionDirectives.Count; i++ )
  850. {
  851. ScriptableObject.DestroyImmediate( m_shaderFunctionDirectives[ i ] );
  852. }
  853. m_shaderFunctionDirectives.Clear();
  854. m_shaderFunctionDirectives = null;
  855. m_propertyAdjustment = null;
  856. m_reordableList = null;
  857. }
  858. public List<AdditionalDirectiveContainer> DirectivesList { get { return m_additionalDirectives; } }
  859. public bool IsValid { get { return m_validData; } set { m_validData = value; } }
  860. }
  861. }