TemplateOptionsUIHelper.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System;
  6. using System.Linq;
  7. using System.Collections.Generic;
  8. namespace AmplifyShaderEditor
  9. {
  10. [Serializable]
  11. public class TemplateOptionsUIHelper
  12. {
  13. public struct ReadOptions
  14. {
  15. public string Name;
  16. public string Selection;
  17. public Int64 Timestamp;
  18. }
  19. private const string CustomOptionsLabel = " Custom Options";
  20. private bool m_isSubShader = false;
  21. [SerializeField]
  22. private bool m_passCustomOptionsFoldout = true;
  23. [SerializeField]
  24. private string m_passCustomOptionsLabel = CustomOptionsLabel;
  25. [SerializeField]
  26. private int m_passCustomOptionsSizeCheck = 0;
  27. [SerializeField]
  28. private List<TemplateOptionUIItem> m_passCustomOptionsUI = new List<TemplateOptionUIItem>();
  29. [NonSerialized]
  30. private Dictionary<string, TemplateOptionUIItem> m_passCustomOptionsUIDict = new Dictionary<string, TemplateOptionUIItem>();
  31. [NonSerialized]
  32. private TemplateMultiPassMasterNode m_owner;
  33. [NonSerialized]
  34. private List<ReadOptions> m_readOptions = null;
  35. [SerializeField]
  36. private List<TemplateOptionPortItem> m_passCustomOptionsPorts = new List<TemplateOptionPortItem>();
  37. public TemplateOptionsUIHelper( bool isSubShader )
  38. {
  39. m_isSubShader = isSubShader;
  40. }
  41. public void CopyOptionsValuesFrom( TemplateOptionsUIHelper origin )
  42. {
  43. for( int i = 0; i < origin.PassCustomOptionsUI.Count; i++ )
  44. {
  45. m_passCustomOptionsUI[ i ].CopyValuesFrom( origin.PassCustomOptionsUI[ i ] );
  46. }
  47. }
  48. public void Destroy()
  49. {
  50. for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
  51. {
  52. m_passCustomOptionsUI[ i ].Destroy();
  53. }
  54. m_passCustomOptionsUI.Clear();
  55. m_passCustomOptionsUI = null;
  56. m_passCustomOptionsUIDict.Clear();
  57. m_passCustomOptionsUIDict = null;
  58. m_passCustomOptionsPorts.Clear();
  59. m_passCustomOptionsPorts = null;
  60. }
  61. public void DrawCustomOptions( TemplateMultiPassMasterNode owner )
  62. {
  63. m_owner = owner;
  64. if( m_passCustomOptionsUI.Count > 0 )
  65. {
  66. NodeUtils.DrawNestedPropertyGroup( ref m_passCustomOptionsFoldout, m_passCustomOptionsLabel, DrawCustomOptionsBlock );
  67. }
  68. }
  69. public void DrawCustomOptionsBlock()
  70. {
  71. float currWidth = EditorGUIUtility.labelWidth;
  72. float size = Mathf.Max( UIUtils.CurrentWindow.ParametersWindow.TransformedArea.width * 0.385f, 0 );
  73. EditorGUIUtility.labelWidth = size;
  74. for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
  75. {
  76. m_passCustomOptionsUI[ i ].Draw( m_owner );
  77. }
  78. EditorGUILayout.Space();
  79. EditorGUIUtility.labelWidth = currWidth;
  80. }
  81. private InputPort MatchInputPortForTemplateAction( TemplateMultiPassMasterNode passMasterNode, TemplateActionItem action )
  82. {
  83. InputPort port;
  84. if ( action.ActionDataIdx > -1 )
  85. {
  86. port = passMasterNode.GetInputPortByUniqueId( action.ActionDataIdx );
  87. }
  88. else
  89. {
  90. // @diogo: hacky.. but it'll have to do, for crude backwards compatibility
  91. if ( action.ActionData.StartsWith( "_" ) )
  92. {
  93. port = passMasterNode.GetInputPortByExternalLinkId( action.ActionData );
  94. }
  95. else
  96. {
  97. port = passMasterNode.GetInputPortByName( action.ActionData );
  98. }
  99. }
  100. return port;
  101. }
  102. private bool TestActionItemConditional( TemplateActionItem actionItem )
  103. {
  104. bool succeeded = true;
  105. TemplateActionItemConditional conditional = actionItem.ActionConditional;
  106. if ( conditional != null && conditional.IsValid )
  107. {
  108. TemplateOptionUIItem referenceItem = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( conditional.Option ) ) );
  109. if ( referenceItem != null )
  110. {
  111. bool equal = conditional.Value.Equals( referenceItem.Options.Options[ referenceItem.CurrentOption ] );
  112. if ( conditional.Condition == TemplateActionItemConditional.Conditional.Equal )
  113. {
  114. succeeded = equal;
  115. }
  116. else if ( conditional.Condition == TemplateActionItemConditional.Conditional.NotEqual )
  117. {
  118. succeeded = !equal;
  119. }
  120. }
  121. }
  122. return succeeded;
  123. }
  124. public void OnCustomOptionSelected( bool actionFromUser, bool isRefreshing, bool invertAction, TemplateMultiPassMasterNode owner, TemplateOptionUIItem uiItem, int recursionLevel, params TemplateActionItem[] validActions )
  125. {
  126. uiItem.CheckOnExecute = false;
  127. for( int i = 0; i < validActions.Length; i++ )
  128. {
  129. // @diogo: test conditional before running
  130. if ( !TestActionItemConditional( validActions[ i ] ) )
  131. {
  132. continue;
  133. }
  134. AseOptionsActionType actionType = validActions[ i ].ActionType;
  135. if( invertAction )
  136. {
  137. if( !TemplateOptionsToolsHelper.InvertAction( validActions[ i ].ActionType, ref actionType ) )
  138. {
  139. continue;
  140. }
  141. }
  142. switch( actionType )
  143. {
  144. case AseOptionsActionType.RefreshOption:
  145. {
  146. if ( !uiItem.IsVisible || recursionLevel > 0 )
  147. break;
  148. TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
  149. if ( item != null )
  150. {
  151. item.Update( recursionLevel + 1, isRefreshing );
  152. }
  153. else
  154. {
  155. Debug.LogFormat( "Could not find Option {0} for action '{1}' on template {2}", validActions[ i ].ActionData, validActions[ i ].ActionType, owner.CurrentTemplate.DefaultShaderName );
  156. }
  157. }
  158. break;
  159. case AseOptionsActionType.ShowOption:
  160. {
  161. TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
  162. if( item != null )
  163. {
  164. if( isRefreshing )
  165. {
  166. string optionId = validActions[ i ].PassName + validActions[ i ].ActionData + "Option";
  167. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true );
  168. }
  169. // this prevents options from showing up when loading by checking if they were hidden by another option
  170. // it works on the assumption that an option that may possible hide this one is checked first
  171. if( !isRefreshing )
  172. item.IsVisible = true;
  173. else if( item.WasVisible )
  174. item.IsVisible = true;
  175. if( !invertAction && validActions[ i ].ActionDataIdx > -1 )
  176. item.CurrentOption = validActions[ i ].ActionDataIdx;
  177. item.CheckEnDisable( actionFromUser );
  178. }
  179. else
  180. {
  181. Debug.LogFormat( "Could not find Option {0} for action '{1}' on template {2}", validActions[ i ].ActionData, validActions[ i ].ActionType, owner.CurrentTemplate.DefaultShaderName );
  182. }
  183. }
  184. break;
  185. case AseOptionsActionType.HideOption:
  186. {
  187. TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
  188. if( item != null )
  189. {
  190. bool flag = false;
  191. if( isRefreshing )
  192. {
  193. string optionId = validActions[ i ].PassName + validActions[ i ].ActionData + "Option";
  194. flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false );
  195. }
  196. item.IsVisible = false || flag;
  197. if( !invertAction && validActions[ i ].ActionDataIdx > -1 )
  198. item.CurrentOption = validActions[ i ].ActionDataIdx;
  199. item.CheckEnDisable( actionFromUser );
  200. }
  201. else
  202. {
  203. Debug.LogFormat( "Could not find Option {0} for action '{1}' on template {2}", validActions[ i ].ActionData, validActions[ i ].ActionType, owner.CurrentTemplate.DefaultShaderName );
  204. }
  205. }
  206. break;
  207. case AseOptionsActionType.SetOption:
  208. {
  209. if( !uiItem.IsVisible )
  210. break;
  211. TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
  212. if( item != null )
  213. {
  214. item.CurrentOption = validActions[ i ].ActionDataIdx;
  215. item.Update( recursionLevel, isRefreshing );
  216. }
  217. else
  218. {
  219. Debug.LogFormat( "Could not find Option {0} for action '{1}' on template {2}", validActions[ i ].ActionData, validActions[ i ].ActionType, owner.CurrentTemplate.DefaultShaderName );
  220. }
  221. }
  222. break;
  223. case AseOptionsActionType.HidePort:
  224. {
  225. TemplateMultiPassMasterNode passMasterNode = owner;
  226. if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  227. {
  228. passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName,owner.LODIndex );
  229. }
  230. if( passMasterNode != null )
  231. {
  232. InputPort port = MatchInputPortForTemplateAction( passMasterNode, validActions[ i ] );
  233. if( port != null )
  234. {
  235. if( isRefreshing )
  236. {
  237. string optionId = validActions[ i ].PassName + port.Name;
  238. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, port.IsConnected );
  239. port.Visible = port.IsConnected;
  240. }
  241. else
  242. {
  243. port.Visible = false;
  244. }
  245. passMasterNode.SizeIsDirty = true;
  246. }
  247. else
  248. {
  249. Debug.LogFormat( "Could not find port {0},{1} for action '{2}' on template {3}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType, owner.CurrentTemplate.DefaultShaderName );
  250. }
  251. }
  252. else
  253. {
  254. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  255. }
  256. }
  257. break;
  258. case AseOptionsActionType.ShowPort:
  259. {
  260. if( !uiItem.IsVisible )
  261. break;
  262. TemplateMultiPassMasterNode passMasterNode = owner;
  263. if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  264. {
  265. passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  266. }
  267. if( passMasterNode != null )
  268. {
  269. InputPort port = MatchInputPortForTemplateAction( passMasterNode, validActions[ i ] );
  270. if( port != null )
  271. {
  272. if( isRefreshing )
  273. {
  274. string optionId = validActions[ i ].PassName + port.Name;
  275. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true );
  276. }
  277. port.Visible = true;
  278. passMasterNode.SizeIsDirty = true;
  279. }
  280. else
  281. {
  282. Debug.LogFormat( "Could not find port {0},{1} for action '{2}' on template {3}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType, owner.CurrentTemplate.DefaultShaderName );
  283. }
  284. }
  285. else
  286. {
  287. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  288. }
  289. }
  290. break;
  291. case AseOptionsActionType.SetPortName:
  292. {
  293. if( !uiItem.IsVisible )
  294. break;
  295. TemplateMultiPassMasterNode passMasterNode = owner;
  296. if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  297. {
  298. passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  299. }
  300. if( passMasterNode != null )
  301. {
  302. InputPort port = MatchInputPortForTemplateAction( passMasterNode, validActions[ i ] );
  303. if( port != null )
  304. {
  305. port.Name = validActions[ i ].ActionData2;
  306. passMasterNode.SizeIsDirty = true;
  307. }
  308. else
  309. {
  310. Debug.LogFormat( "Could not find port {0},{1} for action '{2}' on template {3}", validActions[ i ].ActionData, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  311. }
  312. }
  313. else
  314. {
  315. Debug.LogFormat( "Could not find pass {0}, {1} for action '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  316. }
  317. }
  318. break;
  319. case AseOptionsActionType.SetDefine:
  320. {
  321. if( !uiItem.IsVisible )
  322. {
  323. uiItem.CheckOnExecute = true;
  324. break;
  325. }
  326. //Debug.Log( "DEFINE " + validActions[ i ].ActionData );
  327. if( validActions[ i ].AllPasses )
  328. {
  329. string actionData = validActions[ i ].ActionData;
  330. string defineValue = string.Empty;
  331. bool isPragma = false;
  332. if( actionData.StartsWith( "pragma" ) )
  333. {
  334. defineValue = "#" + actionData;
  335. isPragma = true;
  336. }
  337. else
  338. {
  339. defineValue = "#define " + validActions[ i ].ActionData;
  340. }
  341. if( isRefreshing )
  342. {
  343. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, true );
  344. }
  345. List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
  346. int count = nodes.Count;
  347. for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
  348. {
  349. nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( defineValue, false, isPragma );
  350. }
  351. }
  352. else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  353. {
  354. TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  355. if( passMasterNode != null )
  356. {
  357. string actionData = validActions[ i ].ActionData;
  358. string defineValue = string.Empty;
  359. bool isPragma = false;
  360. if( actionData.StartsWith( "pragma" ) )
  361. {
  362. defineValue = "#" + actionData;
  363. isPragma = true;
  364. }
  365. else
  366. {
  367. defineValue = "#define " + validActions[ i ].ActionData;
  368. }
  369. if( isRefreshing )
  370. {
  371. string optionsId = validActions[ i ].PassName + defineValue;
  372. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionsId, true );
  373. }
  374. passMasterNode.OptionsDefineContainer.AddDirective( defineValue, false, isPragma );
  375. }
  376. else
  377. {
  378. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  379. }
  380. }
  381. else
  382. {
  383. uiItem.CheckOnExecute = true;
  384. }
  385. }
  386. break;
  387. case AseOptionsActionType.RemoveDefine:
  388. {
  389. //Debug.Log( "UNDEFINE " + validActions[ i ].ActionData );
  390. if( validActions[ i ].AllPasses )
  391. {
  392. string actionData = validActions[ i ].ActionData;
  393. string defineValue = string.Empty;
  394. if( actionData.StartsWith( "pragma" ) )
  395. {
  396. defineValue = "#" + actionData;
  397. }
  398. else
  399. {
  400. defineValue = "#define " + validActions[ i ].ActionData;
  401. }
  402. bool flag = false;
  403. if( isRefreshing )
  404. {
  405. flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, false );
  406. }
  407. if( !flag )
  408. {
  409. List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
  410. int count = nodes.Count;
  411. for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
  412. {
  413. nodes[ nodeIdx ].OptionsDefineContainer.RemoveDirective( defineValue );
  414. }
  415. }
  416. }
  417. else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  418. {
  419. TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  420. if( passMasterNode != null )
  421. {
  422. string actionData = validActions[ i ].ActionData;
  423. string defineValue = string.Empty;
  424. if( actionData.StartsWith( "pragma" ) )
  425. {
  426. defineValue = "#" + actionData;
  427. }
  428. else
  429. {
  430. defineValue = "#define " + validActions[ i ].ActionData;
  431. }
  432. bool flag = false;
  433. if( isRefreshing )
  434. {
  435. string optionId = validActions[ i ].PassName + defineValue;
  436. flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false );
  437. }
  438. if( !flag )
  439. {
  440. passMasterNode.OptionsDefineContainer.RemoveDirective( defineValue );
  441. }
  442. }
  443. else
  444. {
  445. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  446. }
  447. }
  448. else
  449. {
  450. uiItem.CheckOnExecute = false;
  451. }
  452. }
  453. break;
  454. case AseOptionsActionType.SetUndefine:
  455. {
  456. if( !uiItem.IsVisible )
  457. {
  458. uiItem.CheckOnExecute = true;
  459. break;
  460. }
  461. if( validActions[ i ].AllPasses )
  462. {
  463. string defineValue = "#undef " + validActions[ i ].ActionData;
  464. if( isRefreshing )
  465. {
  466. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, true );
  467. }
  468. List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes(owner.LODIndex);
  469. int count = nodes.Count;
  470. for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
  471. {
  472. nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( defineValue, false );
  473. }
  474. }
  475. else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  476. {
  477. TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  478. if( passMasterNode != null )
  479. {
  480. string defineValue = "#undef " + validActions[ i ].ActionData;
  481. if( isRefreshing )
  482. {
  483. string optionsId = validActions[ i ].PassName + defineValue;
  484. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionsId, true );
  485. }
  486. passMasterNode.OptionsDefineContainer.AddDirective( defineValue, false );
  487. }
  488. else
  489. {
  490. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  491. }
  492. }
  493. else
  494. {
  495. uiItem.CheckOnExecute = true;
  496. }
  497. }
  498. break;
  499. case AseOptionsActionType.RemoveUndefine:
  500. {
  501. if( validActions[ i ].AllPasses )
  502. {
  503. string defineValue = "#undef " + validActions[ i ].ActionData;
  504. bool flag = false;
  505. if( isRefreshing )
  506. {
  507. flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, false );
  508. }
  509. if( !flag )
  510. {
  511. List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
  512. int count = nodes.Count;
  513. for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
  514. {
  515. nodes[ nodeIdx ].OptionsDefineContainer.RemoveDirective( defineValue );
  516. }
  517. }
  518. }
  519. else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  520. {
  521. TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  522. if( passMasterNode != null )
  523. {
  524. bool flag = false;
  525. string defineValue = "#undef " + validActions[ i ].ActionData;
  526. if( isRefreshing )
  527. {
  528. string optionId = validActions[ i ].PassName + defineValue;
  529. flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false );
  530. }
  531. if( !flag )
  532. {
  533. passMasterNode.OptionsDefineContainer.RemoveDirective( defineValue );
  534. }
  535. }
  536. else
  537. {
  538. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  539. }
  540. }
  541. else
  542. {
  543. uiItem.CheckOnExecute = false;
  544. }
  545. }
  546. break;
  547. case AseOptionsActionType.ExcludePass:
  548. {
  549. string optionId = validActions[ i ].ActionData + "Pass";
  550. //bool flag = isRefreshing ? owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false ) : false;
  551. //if( !flag )
  552. // owner.SetPassVisible( validActions[ i ].ActionData, false );
  553. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId , false ) ;
  554. owner.SetPassVisible( validActions[ i ].ActionData , false );
  555. }
  556. break;
  557. case AseOptionsActionType.IncludePass:
  558. {
  559. if( !uiItem.IsVisible )
  560. break;
  561. string optionId = validActions[ i ].ActionData + "Pass";
  562. owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true );
  563. owner.SetPassVisible( validActions[ i ].ActionData, true );
  564. }
  565. break;
  566. case AseOptionsActionType.SetPropertyOnPass:
  567. {
  568. //Debug.Log( "PASSPROP " + validActions[ i ].ActionData );
  569. //Refresh happens on hotcode reload and shader load and in those situation
  570. // The property own serialization handles its setup
  571. if( isRefreshing )
  572. continue;
  573. if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
  574. {
  575. TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
  576. if( passMasterNode != null )
  577. {
  578. passMasterNode.SetPropertyActionFromItem( actionFromUser, passMasterNode.PassModule, validActions[ i ] );
  579. }
  580. else
  581. {
  582. Debug.LogFormat( "Could not find pass {0} for action {1} '{2}' on template {3}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData, owner.CurrentTemplate.DefaultShaderName );
  583. }
  584. }
  585. else
  586. {
  587. owner.SetPropertyActionFromItem( actionFromUser, owner.PassModule, validActions[ i ] );
  588. }
  589. }
  590. break;
  591. case AseOptionsActionType.SetPropertyOnSubShader:
  592. {
  593. //Refresh happens on hotcode reload and shader load and in those situation
  594. // The property own serialization handles its setup
  595. if( isRefreshing )
  596. continue;
  597. owner.SetPropertyActionFromItem( actionFromUser, owner.SubShaderModule, validActions[ i ] );
  598. }
  599. break;
  600. case AseOptionsActionType.SetShaderProperty:
  601. {
  602. //This action is only check when shader is compiled over
  603. //the TemplateMultiPassMasterNode via the on CheckPropertyChangesOnOptions() method
  604. }
  605. break;
  606. case AseOptionsActionType.ExcludeAllPassesBut:
  607. {
  608. //This action is only check when shader is compiled over
  609. //the TemplateMultiPassMasterNode via the on CheckExcludeAllPassOptions() method
  610. }
  611. break;
  612. case AseOptionsActionType.SetMaterialProperty:
  613. {
  614. if( isRefreshing )
  615. continue;
  616. if( !uiItem.IsVisible )
  617. break;
  618. if( owner.ContainerGraph.CurrentMaterial != null )
  619. {
  620. string prop = validActions[ i ].ActionData;
  621. if( owner.ContainerGraph.CurrentMaterial.HasProperty( prop ) )
  622. {
  623. if( uiItem.Options.UIWidget == AseOptionsUIWidget.Float || uiItem.Options.UIWidget == AseOptionsUIWidget.FloatRange )
  624. owner.ContainerGraph.CurrentMaterial.SetFloat( prop, uiItem.CurrentFieldValue );
  625. else
  626. owner.ContainerGraph.CurrentMaterial.SetInt( prop, (int)uiItem.CurrentFieldValue );
  627. if( MaterialInspector.Instance != null )
  628. MaterialInspector.Instance.Repaint();
  629. }
  630. }
  631. }
  632. break;
  633. }
  634. }
  635. }
  636. public void SetupCustomOptionsFromTemplate( TemplateMultiPassMasterNode owner, bool newTemplate )
  637. {
  638. TemplateOptionsContainer customOptionsContainer = m_isSubShader ? owner.SubShader.CustomOptionsContainer : owner.Pass.CustomOptionsContainer;
  639. if( !newTemplate && customOptionsContainer.Body.Length == m_passCustomOptionsSizeCheck )
  640. {
  641. for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
  642. {
  643. if( m_passCustomOptionsUI[ i ].EmptyEvent )
  644. {
  645. if( m_isSubShader )
  646. {
  647. m_passCustomOptionsUI[ i ].OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected;
  648. }
  649. else
  650. {
  651. m_passCustomOptionsUI[ i ].OnActionPerformedEvt += owner.OnCustomPassOptionSelected;
  652. }
  653. }
  654. }
  655. return;
  656. }
  657. m_passCustomOptionsLabel = string.IsNullOrEmpty( customOptionsContainer.Name ) ? CustomOptionsLabel : " " + customOptionsContainer.Name;
  658. for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
  659. {
  660. m_passCustomOptionsUI[ i ].Destroy();
  661. }
  662. m_passCustomOptionsUI.Clear();
  663. m_passCustomOptionsUIDict.Clear();
  664. m_passCustomOptionsPorts.Clear();
  665. if( customOptionsContainer.Enabled )
  666. {
  667. m_passCustomOptionsSizeCheck = customOptionsContainer.Body.Length;
  668. for( int i = 0; i < customOptionsContainer.Options.Length; i++ )
  669. {
  670. switch( customOptionsContainer.Options[ i ].Type )
  671. {
  672. case AseOptionsType.Option:
  673. {
  674. TemplateOptionUIItem item = new TemplateOptionUIItem( customOptionsContainer.Options[ i ] );
  675. if( m_isSubShader )
  676. {
  677. item.OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected;
  678. }
  679. else
  680. {
  681. item.OnActionPerformedEvt += owner.OnCustomPassOptionSelected;
  682. }
  683. m_passCustomOptionsUI.Add( item );
  684. m_passCustomOptionsUIDict.Add( customOptionsContainer.Options[ i ].Id, item );
  685. }
  686. break;
  687. case AseOptionsType.Port:
  688. {
  689. TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
  690. m_passCustomOptionsPorts.Add( item );
  691. //if( m_isSubShader )
  692. //{
  693. // if( string.IsNullOrEmpty( customOptionsContainer.Options[ i ].Id ) )
  694. // {
  695. // //No pass name selected. inject on all passes
  696. // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
  697. // m_passCustomOptionsPorts.Add( item );
  698. // }
  699. // else if( customOptionsContainer.Options[ i ].Id.Equals( owner.PassName ) )
  700. // {
  701. // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
  702. // m_passCustomOptionsPorts.Add( item );
  703. // }
  704. //}
  705. //else
  706. //{
  707. // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
  708. // m_passCustomOptionsPorts.Add( item );
  709. //}
  710. }
  711. break;
  712. case AseOptionsType.Field:
  713. {
  714. TemplateOptionUIItem item = new TemplateOptionUIItem( customOptionsContainer.Options[ i ] );
  715. if( m_isSubShader )
  716. {
  717. item.OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected;
  718. }
  719. else
  720. {
  721. item.OnActionPerformedEvt += owner.OnCustomPassOptionSelected;
  722. }
  723. m_passCustomOptionsUI.Add( item );
  724. m_passCustomOptionsUIDict.Add( customOptionsContainer.Options[ i ].Id, item );
  725. }
  726. break;
  727. }
  728. }
  729. }
  730. else
  731. {
  732. m_passCustomOptionsSizeCheck = 0;
  733. }
  734. }
  735. public void SetCustomOptionsInfo( TemplateMultiPassMasterNode masterNode, ref MasterNodeDataCollector dataCollector )
  736. {
  737. if( masterNode == null )
  738. return;
  739. for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
  740. {
  741. m_passCustomOptionsUI[ i ].FillDataCollector( ref dataCollector );
  742. }
  743. for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
  744. {
  745. m_passCustomOptionsPorts[ i ].FillDataCollector( masterNode, ref dataCollector );
  746. }
  747. }
  748. public void CheckImediateActionsForPort( TemplateMultiPassMasterNode masterNode , int portId )
  749. {
  750. for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
  751. {
  752. m_passCustomOptionsPorts[ i ].CheckImediateActionsForPort( masterNode, portId );
  753. }
  754. }
  755. public void SetSubShaderCustomOptionsPortsInfo( TemplateMultiPassMasterNode masterNode, ref MasterNodeDataCollector dataCollector )
  756. {
  757. if( masterNode == null )
  758. return;
  759. //for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
  760. //{
  761. // if( string.IsNullOrEmpty( m_passCustomOptionsPorts[ i ].Options.Id ) ||
  762. // masterNode.PassUniqueName.Equals( m_passCustomOptionsPorts[ i ].Options.Id ) )
  763. // {
  764. // m_passCustomOptionsPorts[ i ].FillDataCollector( masterNode, ref dataCollector );
  765. // }
  766. //}
  767. for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
  768. {
  769. m_passCustomOptionsPorts[ i ].SubShaderFillDataCollector( masterNode, ref dataCollector );
  770. }
  771. }
  772. public void RefreshCustomOptionsDict()
  773. {
  774. if( m_passCustomOptionsUIDict.Count != m_passCustomOptionsUI.Count )
  775. {
  776. m_passCustomOptionsUIDict.Clear();
  777. int count = m_passCustomOptionsUI.Count;
  778. for( int i = 0; i < count; i++ )
  779. {
  780. m_passCustomOptionsUIDict.Add( m_passCustomOptionsUI[ i ].Options.Id, m_passCustomOptionsUI[ i ] );
  781. }
  782. }
  783. }
  784. public void ReadFromString( ref uint index, ref string[] nodeParams )
  785. {
  786. RefreshCustomOptionsDict();
  787. int savedOptions = Convert.ToInt32( nodeParams[ index++ ] );
  788. m_readOptions = new List<ReadOptions>();
  789. for( int i = 0; i < savedOptions; i++ )
  790. {
  791. string optionName = nodeParams[ index++ ];
  792. string optionSelection = nodeParams[ index++ ];
  793. Int64 optionTimestamp = ( UIUtils.CurrentShaderVersion() > 18929 ) ? Convert.ToInt64( nodeParams[ index++ ] ):0;
  794. m_readOptions.Add( new ReadOptions() { Name = optionName , Selection = optionSelection , Timestamp = optionTimestamp });
  795. }
  796. }
  797. public void WriteToString( ref string nodeInfo )
  798. {
  799. int optionsCount = m_passCustomOptionsUI.Count;
  800. IOUtils.AddFieldValueToString( ref nodeInfo , optionsCount );
  801. for( int i = 0 ; i < optionsCount ; i++ )
  802. {
  803. IOUtils.AddFieldValueToString( ref nodeInfo , m_passCustomOptionsUI[ i ].Options.Id );
  804. if( m_passCustomOptionsUI[ i ].Options.Type == AseOptionsType.Field )
  805. IOUtils.AddFieldValueToString( ref nodeInfo , m_passCustomOptionsUI[ i ].FieldValue.WriteToSingle() );
  806. else
  807. IOUtils.AddFieldValueToString( ref nodeInfo , m_passCustomOptionsUI[ i ].CurrentOption );
  808. IOUtils.AddFieldValueToString( ref nodeInfo , m_passCustomOptionsUI[ i ].LastClickedTimestamp );
  809. }
  810. }
  811. public void SetReadOptions()
  812. {
  813. if( m_readOptions != null )
  814. {
  815. for( int i = 0 ; i < m_readOptions.Count ; i++ )
  816. {
  817. if( m_passCustomOptionsUIDict.ContainsKey( m_readOptions[ i ].Name ) )
  818. {
  819. m_passCustomOptionsUIDict[ m_readOptions[ i ].Name ].LastClickedTimestamp = m_readOptions[ i ].Timestamp;
  820. if( m_passCustomOptionsUIDict[ m_readOptions[ i ].Name ].Options.Type == AseOptionsType.Field )
  821. {
  822. m_passCustomOptionsUIDict[ m_readOptions[ i ].Name ].FieldValue.ReadFromSingle( m_readOptions[ i ].Selection );
  823. foreach( var item in m_passCustomOptionsUIDict[ m_readOptions[ i ].Name ].Options.ActionsPerOption.Rows )
  824. {
  825. if( item.Columns.Length > 0 && item.Columns[ 0 ].ActionType == AseOptionsActionType.SetMaterialProperty )
  826. {
  827. if( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial != null )
  828. {
  829. if( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial.HasProperty( item.Columns[ 0 ].ActionData ) )
  830. {
  831. m_passCustomOptionsUIDict[ m_readOptions[ i ].Name ].CurrentFieldValue = UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial.GetFloat( item.Columns[ 0 ].ActionData );
  832. }
  833. }
  834. }
  835. }
  836. }
  837. else
  838. m_passCustomOptionsUIDict[ m_readOptions[ i ].Name ].CurrentOptionIdx = Convert.ToInt32( m_readOptions[ i ].Selection );
  839. }
  840. }
  841. }
  842. }
  843. public void Refresh()
  844. {
  845. //int count = m_passCustomOptionsUI.Count;
  846. //for( int i = 0; i < count; i++ )
  847. //{
  848. // m_passCustomOptionsUI[ i ].Refresh();
  849. //}
  850. List<TemplateOptionUIItem> sortedList = m_passCustomOptionsUI.OrderBy( item => item.LastClickedTimestamp ).ToList();
  851. int count = sortedList.Count;
  852. for( int i = 0 ; i < count ; i++ )
  853. {
  854. sortedList[ i ].Update();
  855. }
  856. }
  857. public void CheckDisable()
  858. {
  859. int count = m_passCustomOptionsUI.Count;
  860. for( int i = 0; i < count; i++ )
  861. {
  862. m_passCustomOptionsUI[ i ].CheckEnDisable(false);
  863. }
  864. }
  865. public List<TemplateOptionUIItem> PassCustomOptionsUI { get { return m_passCustomOptionsUI; } }
  866. }
  867. }