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.

1168 lines
38 KiB

  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. //#define ADD_SHADER_FUNCTION_HEADERS
  4. using UnityEngine;
  5. using UnityEditor;
  6. using System.Collections.Generic;
  7. using System;
  8. namespace AmplifyShaderEditor
  9. {
  10. [Serializable]
  11. [NodeAttributes( "Function Node", "Functions", "Function Node", KeyCode.None, false, 0, int.MaxValue, typeof( AmplifyShaderFunction ) )]
  12. public class FunctionNode : ParentNode
  13. {
  14. [SerializeField]
  15. private AmplifyShaderFunction m_function;
  16. [SerializeField]
  17. private ParentGraph m_functionGraph;
  18. [SerializeField]
  19. private int m_functionGraphId = -1;
  20. [SerializeField]
  21. private List<FunctionInput> m_allFunctionInputs;
  22. private Dictionary<int, FunctionInput> m_allFunctionInputsDict = new Dictionary<int, FunctionInput>();
  23. [SerializeField]
  24. private List<FunctionOutput> m_allFunctionOutputs;
  25. private Dictionary<int, FunctionOutput> m_allFunctionOutputsDict = new Dictionary<int, FunctionOutput>();
  26. [SerializeField]
  27. private List<FunctionSwitch> m_allFunctionSwitches;
  28. private Dictionary<int, FunctionSwitch> m_allFunctionSwitchesDict = new Dictionary<int, FunctionSwitch>();
  29. [SerializeField]
  30. private ReordenatorNode m_reordenator;
  31. [SerializeField]
  32. private string m_filename;
  33. [SerializeField]
  34. private string m_headerTitle = string.Empty;
  35. [SerializeField]
  36. private int m_orderIndex;
  37. [SerializeField]
  38. private string m_functionCheckSum;
  39. [SerializeField]
  40. private string m_functionGUID = string.Empty;
  41. //[SerializeField]
  42. //private List<string> m_includes = new List<string>();
  43. //[SerializeField]
  44. //private List<string> m_pragmas = new List<string>();
  45. [SerializeField]
  46. private List<AdditionalDirectiveContainer> m_directives = new List<AdditionalDirectiveContainer>();
  47. private bool m_parametersFoldout = true;
  48. [SerializeField]
  49. private ParentGraph m_outsideGraph = null;
  50. [SerializeField]
  51. private FunctionOutput m_mainPreviewNode;
  52. bool m_portsChanged = false;
  53. //[SerializeField]
  54. bool m_initialGraphDraw = false;
  55. private bool m_refreshIdsRequired = false;
  56. public string[] ReadOptionsHelper = new string[] { };
  57. private bool m_lateRefresh = false;
  58. string LastLine( string text )
  59. {
  60. string[] lines = text.Replace( "\r", "" ).Split( '\n' );
  61. return lines[ lines.Length - 1 ];
  62. }
  63. public void CommonInit( AmplifyShaderFunction function, int uniqueId )
  64. {
  65. SetBaseUniqueId( uniqueId );
  66. if( function == null )
  67. return;
  68. m_refreshIdsRequired = UIUtils.IsLoading && ( UIUtils.CurrentShaderVersion() < 14004 );
  69. m_function = function;
  70. if( Function.FunctionName.Length > 1 )
  71. {
  72. bool lastIsUpper = Char.IsUpper( Function.FunctionName, 0 );
  73. System.Text.StringBuilder title = new System.Text.StringBuilder();
  74. title.Append( Function.FunctionName[ 0 ] );
  75. for( int i = 1; i < Function.FunctionName.Length; i++ )
  76. {
  77. bool currIsUpper = Char.IsUpper( Function.FunctionName, i );
  78. if( currIsUpper && !lastIsUpper && Char.IsLetter( Function.FunctionName[ i - 1 ] ))
  79. {
  80. title.Append( " " );
  81. }
  82. lastIsUpper = currIsUpper;
  83. title.Append( Function.FunctionName[ i ] );
  84. SetTitleText( title.ToString() );
  85. }
  86. }
  87. else
  88. {
  89. SetTitleText( Function.FunctionName );
  90. }
  91. m_tooltipText = Function.Description;
  92. m_hasTooltipLink = false;
  93. if( m_functionGraph == null )
  94. {
  95. //m_functionGraph = new ParentGraph();
  96. m_functionGraph = CreateInstance<ParentGraph>();
  97. m_functionGraph.Init();
  98. m_functionGraph.ParentWindow = ContainerGraph.ParentWindow;
  99. }
  100. if( string.IsNullOrEmpty( m_functionGUID ) )
  101. {
  102. m_functionGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_function ) );
  103. }
  104. m_functionGraphId = Mathf.Max( m_functionGraphId, ContainerGraph.ParentWindow.GraphCount );
  105. ContainerGraph.ParentWindow.GraphCount = m_functionGraphId + 1;
  106. m_functionGraph.SetGraphId( m_functionGraphId );
  107. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  108. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  109. AmplifyShaderEditorWindow.LoadFromMeta( ref m_functionGraph, ContainerGraph.ParentWindow.ContextMenuInstance, Function.FunctionInfo );
  110. //m_functionCheckSum = LastLine( m_function.FunctionInfo );
  111. m_functionCheckSum = AssetDatabase.GetAssetDependencyHash( AssetDatabase.GetAssetPath( m_function ) ).ToString();
  112. List<PropertyNode> propertyList = UIUtils.PropertyNodesList();
  113. m_allFunctionInputs = UIUtils.FunctionInputList();
  114. m_allFunctionOutputs = UIUtils.FunctionOutputList();
  115. m_allFunctionSwitches = UIUtils.FunctionSwitchList();
  116. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  117. m_allFunctionInputs.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  118. m_allFunctionOutputs.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  119. m_allFunctionSwitches.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  120. int inputCount = m_allFunctionInputs.Count;
  121. for( int i = 0; i < inputCount; i++ )
  122. {
  123. if( m_refreshIdsRequired )
  124. {
  125. AddInputPort( m_allFunctionInputs[ i ].SelectedInputType, false, m_allFunctionInputs[ i ].InputName );
  126. }
  127. else
  128. {
  129. AddInputPort( m_allFunctionInputs[ i ].SelectedInputType, false, m_allFunctionInputs[ i ].InputName, -1, MasterNodePortCategory.Fragment, m_allFunctionInputs[ i ].UniqueId );
  130. }
  131. InputPortSwitchRestriction( m_inputPorts[ i ] );
  132. if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected )
  133. {
  134. m_inputPorts[ i ].AutoDrawInternalData = true;
  135. m_inputPorts[ i ].InternalData = m_allFunctionInputs[ i ].InputPorts[ 0 ].InternalData;
  136. }
  137. }
  138. int outputCount = m_allFunctionOutputs.Count;
  139. FunctionOutput first = null;
  140. for( int i = 0; i < outputCount; i++ )
  141. {
  142. if( i == 0 )
  143. first = m_allFunctionOutputs[ i ];
  144. if( m_allFunctionOutputs[ i ].PreviewNode )
  145. {
  146. m_mainPreviewNode = m_allFunctionOutputs[ i ];
  147. }
  148. if( m_refreshIdsRequired )
  149. {
  150. AddOutputPort( m_allFunctionOutputs[ i ].AutoOutputType, m_allFunctionOutputs[ i ].OutputName );
  151. }
  152. else
  153. {
  154. AddOutputPort( m_allFunctionOutputs[ i ].AutoOutputType, m_allFunctionOutputs[ i ].OutputName, m_allFunctionOutputs[ i ].UniqueId );
  155. }
  156. OutputPortSwitchRestriction( m_outputPorts[ i ] );
  157. }
  158. // make sure to hide the ports properly
  159. CheckPortVisibility();
  160. if( m_mainPreviewNode == null )
  161. m_mainPreviewNode = first;
  162. //create reordenator to main graph
  163. bool inside = false;
  164. if( ContainerGraph.ParentWindow.CustomGraph != null )
  165. inside = true;
  166. if( /*hasConnectedProperties*/propertyList.Count > 0 )
  167. {
  168. m_reordenator = ScriptableObject.CreateInstance<ReordenatorNode>();
  169. m_reordenator.Init( "_" + Function.FunctionName, Function.FunctionName, propertyList, false );
  170. m_reordenator.OrderIndex = m_orderIndex;
  171. m_reordenator.HeaderTitle = Function.FunctionName;
  172. m_reordenator.IsInside = inside;
  173. }
  174. if( m_reordenator != null )
  175. {
  176. cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  177. ContainerGraph.ParentWindow.CustomGraph = null;
  178. UIUtils.RegisterPropertyNode( m_reordenator );
  179. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  180. }
  181. m_textLabelWidth = 120;
  182. UIUtils.RegisterFunctionNode( this );
  183. m_previewShaderGUID = "aca70c900c50c004e8ef0b47c4fac4d4";
  184. m_useInternalPortData = false;
  185. m_selectedLocation = function.PreviewPosition;
  186. }
  187. public override void SetPreviewInputs()
  188. {
  189. base.SetPreviewInputs();
  190. if( !m_initialized || m_inputPorts == null )
  191. return;
  192. int count = m_inputPorts.Count;
  193. for( int i = 0; i < count; i++ )
  194. {
  195. if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected )
  196. {
  197. m_allFunctionInputs[ i ].m_ignoreConnection = true;
  198. m_allFunctionInputs[ i ].InputPorts[ 0 ].PreparePortCacheID();
  199. m_allFunctionInputs[ i ].PreviewMaterial.SetTexture( m_allFunctionInputs[ i ].InputPorts[ 0 ].CachedPropertyId, m_inputPorts[ i ].InputPreviewTexture );
  200. }
  201. else
  202. {
  203. m_allFunctionInputs[ i ].m_ignoreConnection = false;
  204. }
  205. }
  206. if( m_mainPreviewNode != null )
  207. {
  208. if( m_drawPreviewAsSphere != m_mainPreviewNode.SpherePreview )
  209. {
  210. m_drawPreviewAsSphere = m_mainPreviewNode.SpherePreview;
  211. OnNodeChange();
  212. }
  213. }
  214. }
  215. public override void RenderNodePreview()
  216. {
  217. if( m_outputPorts == null )
  218. return;
  219. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  220. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  221. if( m_functionGraph != null )
  222. {
  223. for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ )
  224. {
  225. ParentNode node = m_functionGraph.AllNodes[ i ];
  226. if( node != null )
  227. {
  228. node.RenderNodePreview();
  229. }
  230. }
  231. }
  232. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  233. SetPreviewInputs();
  234. int count = m_outputPorts.Count;
  235. for( int i = 0; i < count; i++ )
  236. {
  237. m_outputPorts[ i ].OutputPreviewTexture = m_allFunctionOutputs[ i ].PreviewTexture;
  238. }
  239. }
  240. public override RenderTexture PreviewTexture
  241. {
  242. get
  243. {
  244. if( m_mainPreviewNode != null )
  245. return m_mainPreviewNode.PreviewTexture;
  246. else
  247. return base.PreviewTexture;
  248. }
  249. }
  250. public override void RefreshExternalReferences()
  251. {
  252. base.RefreshExternalReferences();
  253. if( Function == null )
  254. return;
  255. //Debug.Log( "RefreshExternalReferences " + m_function.FunctionName + " " + UIUtils.CurrentWindow.IsShaderFunctionWindow );
  256. Function.UpdateDirectivesList();
  257. MasterNode masterNode = UIUtils.CurrentWindow.OutsideGraph.CurrentMasterNode;
  258. StandardSurfaceOutputNode surface = masterNode as StandardSurfaceOutputNode;
  259. if( surface != null )
  260. {
  261. //for( int i = 0; i < Function.AdditionalIncludes.IncludeList.Count; i++ )
  262. //{
  263. // //ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Add( Function.AdditionalIncludes.IncludeList[ i ] );
  264. // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.AddShaderFunctionItem( AdditionalLineType.Include, Function.AdditionalIncludes.IncludeList[ i ] );
  265. // m_includes.Add( Function.AdditionalIncludes.IncludeList[ i ] );
  266. //}
  267. //for( int i = 0; i < Function.AdditionalPragmas.PragmaList.Count; i++ )
  268. //{
  269. // //ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Add( Function.AdditionalPragmas.PragmaList[ i ] );
  270. // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.AddShaderFunctionItem(AdditionalLineType.Pragma, Function.AdditionalPragmas.PragmaList[ i ] );
  271. // m_pragmas.Add( Function.AdditionalPragmas.PragmaList[ i ] );
  272. //}
  273. surface.AdditionalDirectives.AddShaderFunctionItems( Function.AdditionalDirectives.DirectivesList );
  274. }
  275. else
  276. {
  277. if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 )
  278. {
  279. List<TemplateMultiPassMasterNode> nodes = ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.NodesList;
  280. int count = nodes.Count;
  281. for( int i = 0; i < count; i++ )
  282. {
  283. nodes[ i ].PassModule.AdditionalDirectives.AddShaderFunctionItems( Function.AdditionalDirectives.DirectivesList );
  284. }
  285. }
  286. else
  287. {
  288. // Assuring that we're not editing a Shader Function, as directives setup is not needed there
  289. if( !UIUtils.CurrentWindow.IsShaderFunctionWindow )
  290. {
  291. // This function is nested inside a shader function itself and this method
  292. // was called before the main output node was created.
  293. // This is possible since all nodes RefreshExternalReferences(...) are called at the end
  294. // of a LoadFromMeta
  295. // Need to delay this setup to after all nodes are loaded to then setup the directives
  296. m_lateRefresh = true;
  297. return;
  298. }
  299. }
  300. }
  301. m_directives.AddRange( Function.AdditionalDirectives.DirectivesList );
  302. if( m_refreshIdsRequired )
  303. {
  304. m_refreshIdsRequired = false;
  305. int inputCount = m_inputPorts.Count;
  306. for( int i = 0; i < inputCount; i++ )
  307. {
  308. m_inputPorts[ i ].ChangePortId( m_allFunctionInputs[ i ].UniqueId );
  309. }
  310. int outputCount = m_outputPorts.Count;
  311. for( int i = 0; i < outputCount; i++ )
  312. {
  313. m_outputPorts[ i ].ChangePortId( m_allFunctionOutputs[ i ].UniqueId );
  314. }
  315. }
  316. if( ContainerGraph.ParentWindow.CurrentGraph != m_functionGraph )
  317. ContainerGraph.ParentWindow.CurrentGraph.InstancePropertyCount += m_functionGraph.InstancePropertyCount;
  318. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  319. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  320. if( ReadOptionsHelper.Length > 2 )
  321. {
  322. for( int i = 1; i < ReadOptionsHelper.Length; i += 2 )
  323. {
  324. int optionId = Convert.ToInt32( ReadOptionsHelper[ i ] );
  325. int optionValue = Convert.ToInt32( ReadOptionsHelper[ i + 1 ] );
  326. for( int j = 0; j < m_allFunctionSwitches.Count; j++ )
  327. {
  328. if( m_allFunctionSwitches[ j ].UniqueId == optionId )
  329. {
  330. m_allFunctionSwitches[ j ].SetCurrentSelectedInput( optionValue, m_allFunctionSwitches[ j ].GetCurrentSelectedInput() );
  331. break;
  332. }
  333. }
  334. }
  335. }
  336. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  337. m_portsChanged = true;
  338. }
  339. void InputPortSwitchRestriction( WirePort port )
  340. {
  341. switch( port.DataType )
  342. {
  343. case WirePortDataType.OBJECT:
  344. break;
  345. case WirePortDataType.FLOAT:
  346. case WirePortDataType.FLOAT2:
  347. case WirePortDataType.FLOAT3:
  348. case WirePortDataType.FLOAT4:
  349. case WirePortDataType.COLOR:
  350. case WirePortDataType.INT:
  351. {
  352. port.CreatePortRestrictions( WirePortDataType.FLOAT, WirePortDataType.FLOAT2, WirePortDataType.FLOAT3, WirePortDataType.FLOAT4, WirePortDataType.COLOR, WirePortDataType.INT, WirePortDataType.OBJECT );
  353. }
  354. break;
  355. case WirePortDataType.FLOAT3x3:
  356. case WirePortDataType.FLOAT4x4:
  357. {
  358. port.CreatePortRestrictions( WirePortDataType.FLOAT3x3, WirePortDataType.FLOAT4x4, WirePortDataType.OBJECT );
  359. }
  360. break;
  361. case WirePortDataType.SAMPLER1D:
  362. case WirePortDataType.SAMPLER2D:
  363. case WirePortDataType.SAMPLER3D:
  364. case WirePortDataType.SAMPLERCUBE:
  365. {
  366. port.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.OBJECT );
  367. }
  368. break;
  369. default:
  370. break;
  371. }
  372. }
  373. void OutputPortSwitchRestriction( WirePort port )
  374. {
  375. switch( port.DataType )
  376. {
  377. case WirePortDataType.OBJECT:
  378. break;
  379. case WirePortDataType.FLOAT:
  380. case WirePortDataType.FLOAT2:
  381. case WirePortDataType.FLOAT3:
  382. case WirePortDataType.FLOAT4:
  383. case WirePortDataType.COLOR:
  384. case WirePortDataType.INT:
  385. case WirePortDataType.FLOAT3x3:
  386. case WirePortDataType.FLOAT4x4:
  387. {
  388. port.AddPortForbiddenTypes( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE );
  389. }
  390. break;
  391. case WirePortDataType.SAMPLER1D:
  392. case WirePortDataType.SAMPLER2D:
  393. case WirePortDataType.SAMPLER3D:
  394. case WirePortDataType.SAMPLERCUBE:
  395. {
  396. port.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.OBJECT );
  397. }
  398. break;
  399. default:
  400. break;
  401. }
  402. }
  403. public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector )
  404. {
  405. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  406. m_outsideGraph = cachedGraph;
  407. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  408. for( int i = 0; i < m_allFunctionOutputs.Count; i++ )
  409. {
  410. m_allFunctionOutputs[ i ].PropagateNodeData( nodeData, ref dataCollector );
  411. }
  412. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  413. base.PropagateNodeData( nodeData, ref dataCollector );
  414. }
  415. protected override void OnUniqueIDAssigned()
  416. {
  417. base.OnUniqueIDAssigned();
  418. UIUtils.RegisterFunctionNode( this );
  419. }
  420. public override void SetupFromCastObject( UnityEngine.Object obj )
  421. {
  422. base.SetupFromCastObject( obj );
  423. AmplifyShaderFunction function = obj as AmplifyShaderFunction;
  424. CommonInit( function, UniqueId );
  425. RefreshExternalReferences();
  426. }
  427. public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
  428. {
  429. base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
  430. FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ portId ] : GetFunctionInputByUniqueId( portId );
  431. if( functionInput.AutoCast )
  432. {
  433. InputPort inputPort = m_refreshIdsRequired ? m_inputPorts[ portId ] : GetInputPortByUniqueId( portId );
  434. inputPort.MatchPortToConnection();
  435. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  436. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  437. functionInput.ChangeOutputType( inputPort.DataType, false );
  438. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  439. }
  440. for( int i = 0; i < m_allFunctionOutputs.Count; i++ )
  441. {
  442. m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false );
  443. }
  444. }
  445. public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type )
  446. {
  447. base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type );
  448. FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ inputPortId ] : GetFunctionInputByUniqueId( inputPortId );
  449. if( functionInput.AutoCast )
  450. {
  451. InputPort inputPort = m_refreshIdsRequired ? m_inputPorts[ inputPortId ] : GetInputPortByUniqueId( inputPortId );
  452. inputPort.MatchPortToConnection();
  453. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  454. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  455. functionInput.ChangeOutputType( inputPort.DataType, false );
  456. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  457. }
  458. for( int i = 0; i < m_allFunctionOutputs.Count; i++ )
  459. {
  460. m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false );
  461. }
  462. }
  463. public override void DrawProperties()
  464. {
  465. base.DrawProperties();
  466. if( Function == null )
  467. return;
  468. if( Function.Description.Length > 0 || m_allFunctionSwitches.Count > 0 )
  469. NodeUtils.DrawPropertyGroup( ref m_parametersFoldout, "Parameters", DrawDescription );
  470. bool drawInternalDataUI = false;
  471. int inputCount = m_inputPorts.Count;
  472. if( inputCount > 0 )
  473. {
  474. for( int i = 0; i < inputCount; i++ )
  475. {
  476. if( m_inputPorts[ i ].Available && m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].AutoDrawInternalData /*&& ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) )*/ /*&& m_inputPorts[ i ].AutoDrawInternalData*/ )
  477. {
  478. drawInternalDataUI = true;
  479. break;
  480. }
  481. }
  482. }
  483. if( drawInternalDataUI )
  484. NodeUtils.DrawPropertyGroup( ref m_internalDataFoldout, Constants.InternalDataLabelStr, () =>
  485. {
  486. for( int i = 0; i < m_inputPorts.Count; i++ )
  487. {
  488. if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible && m_inputPorts[ i ].AutoDrawInternalData )
  489. {
  490. m_inputPorts[ i ].ShowInternalData( this );
  491. }
  492. }
  493. } );
  494. }
  495. private void DrawDescription()
  496. {
  497. if( Function.Description.Length > 0 )
  498. EditorGUILayout.HelpBox( Function.Description, MessageType.Info );
  499. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  500. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  501. for( int i = 0; i < m_allFunctionSwitches.Count; i++ )
  502. {
  503. m_allFunctionSwitches[ i ].AsDrawn = false;
  504. }
  505. for( int i = 0; i < m_allFunctionSwitches.Count; i++ )
  506. {
  507. if( m_allFunctionSwitches[ i ].DrawOption( this ) )
  508. {
  509. m_portsChanged = true;
  510. }
  511. }
  512. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  513. }
  514. public override void Destroy()
  515. {
  516. m_mainPreviewNode = null;
  517. base.Destroy();
  518. if( m_functionGraph != null && ContainerGraph.ParentWindow.CurrentGraph != m_functionGraph )
  519. ContainerGraph.ParentWindow.CurrentGraph.InstancePropertyCount -= m_functionGraph.InstancePropertyCount;
  520. if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface != null )
  521. {
  522. //for( int i = 0; i < m_includes.Count; i++ )
  523. //{
  524. // //if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Contains( m_includes[ i ] ) )
  525. // //{
  526. // // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Remove( m_includes[ i ] );
  527. // //}
  528. // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItem( AdditionalLineType.Include, m_includes[ i ] );
  529. //}
  530. //for( int i = 0; i < m_pragmas.Count; i++ )
  531. //{
  532. // //if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Contains( m_pragmas[ i ] ) )
  533. // //{
  534. // // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Remove( m_pragmas[ i ] );
  535. // //}
  536. // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItem( AdditionalLineType.Pragma, m_pragmas[ i ] );
  537. //}
  538. ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItems( m_directives );
  539. }
  540. else
  541. {
  542. if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 )
  543. {
  544. List<TemplateMultiPassMasterNode> nodes = ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.NodesList;
  545. int count = nodes.Count;
  546. for( int i = 0; i < count; i++ )
  547. {
  548. nodes[ i ].PassModule.AdditionalDirectives.RemoveShaderFunctionItems( m_directives );
  549. }
  550. }
  551. }
  552. // Cannot GameObject.Destroy(m_directives[i]) since we would be removing them from
  553. // the shader function asset itself
  554. m_directives.Clear();
  555. m_directives = null;
  556. if( m_reordenator != null )
  557. {
  558. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  559. ContainerGraph.ParentWindow.CustomGraph = null;
  560. UIUtils.UnregisterPropertyNode( m_reordenator );
  561. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  562. m_reordenator.Destroy();
  563. m_reordenator = null;
  564. }
  565. UIUtils.UnregisterFunctionNode( this );
  566. ParentGraph cachedGraph2 = ContainerGraph.ParentWindow.CustomGraph;
  567. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  568. if( m_allFunctionInputs != null )
  569. m_allFunctionInputs.Clear();
  570. m_allFunctionInputs = null;
  571. if( m_allFunctionOutputs != null )
  572. m_allFunctionOutputs.Clear();
  573. m_allFunctionOutputs = null;
  574. if( m_functionGraph != null )
  575. m_functionGraph.SoftDestroy();
  576. m_functionGraph = null;
  577. ContainerGraph.ParentWindow.CustomGraph = cachedGraph2;
  578. m_function = null;
  579. m_allFunctionOutputsDict.Clear();
  580. m_allFunctionOutputsDict = null;
  581. m_allFunctionSwitchesDict.Clear();
  582. m_allFunctionSwitchesDict = null;
  583. m_allFunctionInputsDict.Clear();
  584. m_allFunctionInputsDict = null;
  585. }
  586. public override void OnNodeLogicUpdate( DrawInfo drawInfo )
  587. {
  588. if( m_lateRefresh )
  589. {
  590. m_lateRefresh = false;
  591. RefreshExternalReferences();
  592. }
  593. CheckForChangesRecursively();
  594. base.OnNodeLogicUpdate( drawInfo );
  595. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  596. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  597. if( m_functionGraph != null )
  598. {
  599. int nodeCount = m_functionGraph.AllNodes.Count;
  600. for( int i = 0; i < nodeCount; i++ )
  601. {
  602. m_functionGraph.AllNodes[ i ].OnNodeLogicUpdate( drawInfo );
  603. }
  604. if( !string.IsNullOrEmpty( FunctionGraph.CurrentFunctionOutput.SubTitle ) )
  605. {
  606. SetAdditonalTitleText( FunctionGraph.CurrentFunctionOutput.SubTitle );
  607. }
  608. }
  609. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  610. if( m_portsChanged )
  611. {
  612. m_portsChanged = false;
  613. for( int i = 0; i < m_allFunctionOutputs.Count; i++ )
  614. {
  615. m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false );
  616. }
  617. CheckPortVisibility();
  618. }
  619. }
  620. public override void Draw( DrawInfo drawInfo )
  621. {
  622. //CheckForChangesRecursively();
  623. if( !m_initialGraphDraw && drawInfo.CurrentEventType == EventType.Repaint )
  624. {
  625. m_initialGraphDraw = true;
  626. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  627. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  628. if( m_functionGraph != null )
  629. {
  630. for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ )
  631. {
  632. ParentNode node = m_functionGraph.AllNodes[ i ];
  633. if( node != null )
  634. {
  635. node.OnNodeLayout( drawInfo );
  636. }
  637. }
  638. }
  639. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  640. }
  641. base.Draw( drawInfo );
  642. }
  643. public bool CheckForChanges( bool forceCheck = false, bool forceChange = false )
  644. {
  645. if( ( ContainerGraph.ParentWindow.CheckFunctions || forceCheck || forceChange ) && m_function != null )
  646. {
  647. //string newCheckSum = LastLine( m_function.FunctionInfo );
  648. string newCheckSum = AssetDatabase.GetAssetDependencyHash( AssetDatabase.GetAssetPath( m_function ) ).ToString();
  649. if( !m_functionCheckSum.Equals( newCheckSum ) || forceChange )
  650. {
  651. m_functionCheckSum = newCheckSum;
  652. ContainerGraph.OnDuplicateEvent += DuplicateMe;
  653. return true;
  654. }
  655. }
  656. return false;
  657. }
  658. public bool CheckForChangesRecursively()
  659. {
  660. if( m_functionGraph == null )
  661. return false;
  662. bool result = false;
  663. for( int i = 0; i < m_functionGraph.FunctionNodes.NodesList.Count; i++ )
  664. {
  665. if( m_functionGraph.FunctionNodes.NodesList[ i ].CheckForChangesRecursively() )
  666. result = true;
  667. }
  668. if( CheckForChanges( false, result ) )
  669. result = true;
  670. return result;
  671. }
  672. public void DuplicateMe()
  673. {
  674. bool previewOpen = m_showPreview;
  675. string allOptions = m_allFunctionSwitches.Count.ToString();
  676. for( int i = 0; i < m_allFunctionSwitches.Count; i++ )
  677. {
  678. allOptions += "," + m_allFunctionSwitches[ i ].UniqueId + "," + m_allFunctionSwitches[ i ].GetCurrentSelectedInput();
  679. }
  680. ReadOptionsHelper = allOptions.Split( ',' );
  681. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  682. ContainerGraph.ParentWindow.CustomGraph = null;
  683. MasterNode masterNode = ContainerGraph.ParentWindow.CurrentGraph.CurrentMasterNode;
  684. if( masterNode != null )
  685. masterNode.InvalidateMaterialPropertyCount();
  686. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  687. ParentNode newNode = ContainerGraph.CreateNode( m_function, false, Vec2Position );
  688. newNode.ShowPreview = previewOpen;
  689. ( newNode as FunctionNode ).ReadOptionsHelper = ReadOptionsHelper;
  690. newNode.RefreshExternalReferences();
  691. if( ( newNode as FunctionNode ).m_reordenator && m_reordenator )
  692. ( newNode as FunctionNode ).m_reordenator.OrderIndex = m_reordenator.OrderIndex;
  693. for( int i = 0; i < m_outputPorts.Count; i++ )
  694. {
  695. if( m_outputPorts[ i ].IsConnected )
  696. {
  697. OutputPort newOutputPort = newNode.GetOutputPortByUniqueId( m_outputPorts[ i ].PortId );
  698. if( newNode.OutputPorts != null && newOutputPort != null )
  699. {
  700. for( int j = m_outputPorts[ i ].ExternalReferences.Count - 1; j >= 0; j-- )
  701. {
  702. ContainerGraph.CreateConnection( m_outputPorts[ i ].ExternalReferences[ j ].NodeId, m_outputPorts[ i ].ExternalReferences[ j ].PortId, newOutputPort.NodeId, newOutputPort.PortId );
  703. }
  704. }
  705. }
  706. //else
  707. //{
  708. //if( newNode.OutputPorts != null && newNode.OutputPorts[ i ] != null )
  709. //{
  710. // ContainerGraph.DeleteConnection( false, newNode.UniqueId, newNode.OutputPorts[ i ].PortId, false, false, false );
  711. //}
  712. //}
  713. }
  714. for( int i = 0; i < m_inputPorts.Count; i++ )
  715. {
  716. if( m_inputPorts[ i ].IsConnected )
  717. {
  718. InputPort newInputPort = newNode.GetInputPortByUniqueId( m_inputPorts[ i ].PortId );
  719. if( newNode.InputPorts != null && newInputPort != null )
  720. {
  721. ContainerGraph.CreateConnection( newInputPort.NodeId, newInputPort.PortId, m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId, m_inputPorts[ i ].ExternalReferences[ 0 ].PortId );
  722. }
  723. }
  724. }
  725. ContainerGraph.OnDuplicateEvent -= DuplicateMe;
  726. if( Selected )
  727. {
  728. ContainerGraph.DeselectNode( this );
  729. ContainerGraph.SelectNode( newNode, true, false );
  730. }
  731. ContainerGraph.DestroyNode( this, false );
  732. }
  733. private FunctionOutput GetFunctionOutputByUniqueId( int uniqueId )
  734. {
  735. int listCount = m_allFunctionOutputs.Count;
  736. if( m_allFunctionOutputsDict.Count != m_allFunctionOutputs.Count )
  737. {
  738. m_allFunctionOutputsDict.Clear();
  739. for( int i = 0; i < listCount; i++ )
  740. {
  741. m_allFunctionOutputsDict.Add( m_allFunctionOutputs[ i ].UniqueId, m_allFunctionOutputs[ i ] );
  742. }
  743. }
  744. if( m_allFunctionOutputsDict.ContainsKey( uniqueId ) )
  745. return m_allFunctionOutputsDict[ uniqueId ];
  746. return null;
  747. }
  748. private FunctionInput GetFunctionInputByUniqueId( int uniqueId )
  749. {
  750. int listCount = m_allFunctionInputs.Count;
  751. if( m_allFunctionInputsDict.Count != m_allFunctionInputs.Count )
  752. {
  753. m_allFunctionInputsDict.Clear();
  754. for( int i = 0; i < listCount; i++ )
  755. {
  756. m_allFunctionInputsDict.Add( m_allFunctionInputs[ i ].UniqueId, m_allFunctionInputs[ i ] );
  757. }
  758. }
  759. if( m_allFunctionInputsDict.ContainsKey( uniqueId ) )
  760. return m_allFunctionInputsDict[ uniqueId ];
  761. return null;
  762. }
  763. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  764. {
  765. OutputPort outputPort = GetOutputPortByUniqueId( outputId );
  766. FunctionOutput functionOutput = GetFunctionOutputByUniqueId( outputId );
  767. if( outputPort.IsLocalValue( dataCollector.PortCategory ) )
  768. return outputPort.LocalValue( dataCollector.PortCategory );
  769. m_functionGraph.CurrentPrecision = ContainerGraph.ParentWindow.CurrentGraph.CurrentPrecision;
  770. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  771. m_outsideGraph = cachedGraph;
  772. ContainerGraph.ParentWindow.CustomGraph = m_functionGraph;
  773. #if ADD_SHADER_FUNCTION_HEADERS
  774. if( m_reordenator != null && m_reordenator.RecursiveCount() > 0 && m_reordenator.HasTitle )
  775. {
  776. dataCollector.AddToProperties( UniqueId, "[Header(" + m_reordenator.HeaderTitle.Replace( "-", " " ) + ")]", m_reordenator.OrderIndex );
  777. }
  778. #endif
  779. string result = string.Empty;
  780. for( int i = 0; i < m_allFunctionInputs.Count; i++ )
  781. {
  782. if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected )
  783. m_allFunctionInputs[ i ].OnPortGeneration += FunctionNodeOnPortGeneration;
  784. }
  785. result += functionOutput.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
  786. for( int i = 0; i < m_allFunctionInputs.Count; i++ )
  787. {
  788. if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected )
  789. m_allFunctionInputs[ i ].OnPortGeneration -= FunctionNodeOnPortGeneration;
  790. }
  791. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  792. if( outputPort.ConnectionCount > 1 )
  793. RegisterLocalVariable( outputId, result, ref dataCollector );
  794. else
  795. outputPort.SetLocalValue( result, dataCollector.PortCategory );
  796. return outputPort.LocalValue( dataCollector.PortCategory );
  797. }
  798. private string FunctionNodeOnPortGeneration( ref MasterNodeDataCollector dataCollector, int index, ParentGraph graph )
  799. {
  800. ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph;
  801. ContainerGraph.ParentWindow.CustomGraph = m_outsideGraph;
  802. string result = m_inputPorts[ index ].GeneratePortInstructions( ref dataCollector );
  803. ContainerGraph.ParentWindow.CustomGraph = cachedGraph;
  804. return result;
  805. }
  806. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  807. {
  808. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  809. if( Function != null )
  810. IOUtils.AddFieldValueToString( ref nodeInfo, m_function.name );
  811. else
  812. IOUtils.AddFieldValueToString( ref nodeInfo, m_filename );
  813. IOUtils.AddFieldValueToString( ref nodeInfo, m_reordenator != null ? m_reordenator.RawOrderIndex : -1 );
  814. IOUtils.AddFieldValueToString( ref nodeInfo, m_headerTitle );
  815. IOUtils.AddFieldValueToString( ref nodeInfo, m_functionGraphId );
  816. IOUtils.AddFieldValueToString( ref nodeInfo, m_functionGUID );
  817. int functionSwitchCount = m_allFunctionSwitches != null ? m_allFunctionSwitches.Count : 0;
  818. string allOptions = functionSwitchCount.ToString();
  819. for( int i = 0; i < functionSwitchCount; i++ )
  820. {
  821. allOptions += "," + m_allFunctionSwitches[ i ].UniqueId + "," + m_allFunctionSwitches[ i ].GetCurrentSelectedInput();
  822. }
  823. IOUtils.AddFieldValueToString( ref nodeInfo, allOptions );
  824. }
  825. public override void ReadFromString( ref string[] nodeParams )
  826. {
  827. base.ReadFromString( ref nodeParams );
  828. m_filename = GetCurrentParam( ref nodeParams );
  829. m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  830. m_headerTitle = GetCurrentParam( ref nodeParams );
  831. if( UIUtils.CurrentShaderVersion() > 7203 )
  832. {
  833. m_functionGraphId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  834. }
  835. if( UIUtils.CurrentShaderVersion() > 13704 )
  836. {
  837. m_functionGUID = GetCurrentParam( ref nodeParams );
  838. }
  839. AmplifyShaderFunction loaded = AssetDatabase.LoadAssetAtPath<AmplifyShaderFunction>( AssetDatabase.GUIDToAssetPath( m_functionGUID ) );
  840. if( loaded != null )
  841. {
  842. CommonInit( loaded, UniqueId );
  843. }
  844. else
  845. {
  846. string[] guids = AssetDatabase.FindAssets( "t:AmplifyShaderFunction " + m_filename );
  847. if( guids.Length > 0 )
  848. {
  849. string sfGuid = null;
  850. foreach( string guid in guids )
  851. {
  852. string assetPath = AssetDatabase.GUIDToAssetPath( guid );
  853. string name = System.IO.Path.GetFileNameWithoutExtension( assetPath );
  854. if( name.Equals( m_filename, StringComparison.OrdinalIgnoreCase ) )
  855. {
  856. sfGuid = guid;
  857. break;
  858. }
  859. }
  860. loaded = AssetDatabase.LoadAssetAtPath<AmplifyShaderFunction>( AssetDatabase.GUIDToAssetPath( sfGuid ) );
  861. if( loaded != null )
  862. {
  863. CommonInit( loaded, UniqueId );
  864. }
  865. else
  866. {
  867. SetTitleText( "ERROR" );
  868. UIUtils.ShowMessage( string.Format( "Error loading {0} shader function from project folder", m_filename ), MessageSeverity.Error );
  869. }
  870. }
  871. else
  872. {
  873. SetTitleText( "Missing Function" );
  874. UIUtils.ShowMessage( string.Format( "Missing {0} shader function on project folder", m_filename ), MessageSeverity.Error );
  875. }
  876. }
  877. if( UIUtils.CurrentShaderVersion() > 14203 )
  878. {
  879. ReadOptionsHelper = GetCurrentParam( ref nodeParams ).Split( ',' );
  880. }
  881. }
  882. public override void ReadOutputDataFromString( ref string[] nodeParams )
  883. {
  884. if( Function == null )
  885. return;
  886. base.ReadOutputDataFromString( ref nodeParams );
  887. ConfigureInputportsAfterRead();
  888. }
  889. public override void OnNodeDoubleClicked( Vector2 currentMousePos2D )
  890. {
  891. if( Function == null )
  892. return;
  893. ContainerGraph.DeSelectAll();
  894. this.Selected = true;
  895. ContainerGraph.ParentWindow.OnLeftMouseUp();
  896. AmplifyShaderEditorWindow.LoadShaderFunctionToASE( Function, true );
  897. this.Selected = false;
  898. }
  899. private void ConfigureInputportsAfterRead()
  900. {
  901. if( InputPorts != null )
  902. {
  903. int inputCount = InputPorts.Count;
  904. for( int i = 0; i < inputCount; i++ )
  905. {
  906. InputPorts[ i ].ChangeProperties( m_allFunctionInputs[ i ].InputName, m_allFunctionInputs[ i ].SelectedInputType, false );
  907. }
  908. }
  909. if( OutputPorts != null )
  910. {
  911. int outputCount = OutputPorts.Count;
  912. for( int i = 0; i < outputCount; i++ )
  913. {
  914. OutputPorts[ i ].ChangeProperties( m_allFunctionOutputs[ i ].OutputName, m_allFunctionOutputs[ i ].AutoOutputType, false );
  915. }
  916. }
  917. }
  918. private void CheckPortVisibility()
  919. {
  920. bool changes = false;
  921. if( InputPorts != null )
  922. {
  923. for( int i = 0; i < m_allFunctionInputs.Count; i++ )
  924. {
  925. if( m_inputPorts[ i ].Visible != m_allFunctionInputs[ i ].IsConnected )
  926. {
  927. m_inputPorts[ i ].Visible = m_allFunctionInputs[ i ].IsConnected;
  928. changes = true;
  929. }
  930. }
  931. }
  932. if( changes )
  933. m_sizeIsDirty = true;
  934. }
  935. public bool HasProperties { get { return m_reordenator != null; } }
  936. public ParentGraph FunctionGraph
  937. {
  938. get { return m_functionGraph; }
  939. set { m_functionGraph = value; }
  940. }
  941. public AmplifyShaderFunction Function
  942. {
  943. get { return m_function; }
  944. set { m_function = value; }
  945. }
  946. public override void RecordObjectOnDestroy( string Id )
  947. {
  948. base.RecordObjectOnDestroy( Id );
  949. if( m_reordenator != null )
  950. m_reordenator.RecordObject( Id );
  951. if( m_functionGraph != null )
  952. {
  953. Undo.RegisterCompleteObjectUndo( m_functionGraph, Id );
  954. for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ )
  955. {
  956. m_functionGraph.AllNodes[ i ].RecordObject( Id );
  957. }
  958. }
  959. }
  960. public override void SetContainerGraph( ParentGraph newgraph )
  961. {
  962. base.SetContainerGraph( newgraph );
  963. if( m_functionGraph == null )
  964. return;
  965. for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ )
  966. {
  967. m_functionGraph.AllNodes[ i ].SetContainerGraph( m_functionGraph );
  968. }
  969. }
  970. public override void OnMasterNodeReplaced( MasterNode newMasterNode )
  971. {
  972. base.OnMasterNodeReplaced( newMasterNode );
  973. m_functionGraph.FireMasterNodeReplacedEvent( newMasterNode );
  974. StandardSurfaceOutputNode surface = newMasterNode as StandardSurfaceOutputNode;
  975. if( surface != null )
  976. {
  977. surface.AdditionalDirectives.AddShaderFunctionItems( Function.AdditionalDirectives.DirectivesList );
  978. }
  979. else
  980. {
  981. if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 )
  982. {
  983. List<TemplateMultiPassMasterNode> nodes = ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.NodesList;
  984. int count = nodes.Count;
  985. for( int i = 0; i < count; i++ )
  986. {
  987. nodes[ i ].PassModule.AdditionalDirectives.AddShaderFunctionItems( Function.AdditionalDirectives.DirectivesList );
  988. }
  989. }
  990. }
  991. }
  992. }
  993. }