MasterNode.cs 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using System;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEditor;
  7. using UnityEditorInternal;
  8. namespace AmplifyShaderEditor
  9. {
  10. public enum PrecisionType
  11. {
  12. Float = 0,
  13. Half,
  14. Inherit
  15. }
  16. public enum AvailableShaderTypes
  17. {
  18. SurfaceShader = 0,
  19. Template
  20. }
  21. [Serializable]
  22. public class MasterNodeCategoriesData
  23. {
  24. public AvailableShaderTypes Category;
  25. public string Name;
  26. public MasterNodeCategoriesData( AvailableShaderTypes category, string name ) { Category = category; Name = name; }
  27. }
  28. [Serializable]
  29. public class MasterNode : OutputNode
  30. {
  31. protected const string CustomInspectorStr = "Custom Editor";
  32. protected const string CustomInspectorFormat = "CustomEditor \"{0}\"";
  33. private const string PropertyOrderFoldoutStr = " Material Properties";
  34. private const string PropertyOrderTemplateFoldoutStr = "Material Properties";
  35. protected MasterNodeDataCollector m_currentDataCollector;
  36. protected const string ShaderNameStr = "Shader Name";
  37. protected GUIContent m_shaderNameContent;
  38. private const string IndentationHelper = "\t\t{0}\n";
  39. private const string ShaderLODFormat = "\t\tLOD {0}\n";
  40. public delegate void OnMaterialUpdated( MasterNode masterNode );
  41. public event OnMaterialUpdated OnMaterialUpdatedEvent;
  42. public event OnMaterialUpdated OnShaderUpdatedEvent;
  43. protected const string GeneralFoldoutStr = " General";
  44. protected readonly string[] ShaderModelTypeArr = { "2.0", "2.5", "3.0", "3.5", "4.0", "4.5", "4.6", "5.0" };
  45. private const string ShaderKeywordsStr = "Shader Keywords";
  46. [SerializeField]
  47. protected int m_shaderLOD = 0;
  48. [SerializeField]
  49. protected int m_shaderModelIdx = 3;
  50. [SerializeField]
  51. protected Shader m_currentShader;
  52. [SerializeField]
  53. protected Material m_currentMaterial;
  54. //[SerializeField]
  55. //private bool m_isMainMasterNode = false;
  56. [SerializeField]
  57. private Rect m_masterNodeIconCoords;
  58. [SerializeField]
  59. protected string m_shaderName = Constants.DefaultShaderName;
  60. [SerializeField]
  61. protected string m_croppedShaderName = Constants.DefaultShaderName;
  62. [SerializeField]
  63. protected string m_customInspectorName = Constants.DefaultCustomInspector;
  64. [SerializeField]
  65. protected int m_masterNodeCategory = 0;// MasterNodeCategories.SurfaceShader;
  66. [SerializeField]
  67. protected bool m_samplingMacros = false;
  68. [SerializeField]
  69. protected string m_currentShaderData = string.Empty;
  70. private Texture2D m_masterNodeOnTex;
  71. private Texture2D m_masterNodeOffTex;
  72. private Texture2D m_gpuInstanceOnTex;
  73. private Texture2D m_gpuInstanceOffTex;
  74. // Shader Keywords
  75. [SerializeField]
  76. private List<string> m_shaderKeywords = new List<string>();
  77. [SerializeField]
  78. private bool m_shaderKeywordsFoldout = true;
  79. private GUIStyle m_addShaderKeywordStyle;
  80. private GUIStyle m_removeShaderKeywordStyle;
  81. private GUIStyle m_smallAddShaderKeywordItemStyle;
  82. private GUIStyle m_smallRemoveShaderKeywordStyle;
  83. private const float ShaderKeywordButtonLayoutWidth = 15;
  84. public MasterNode() : base() { CommonInit(); }
  85. public MasterNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { CommonInit(); }
  86. protected GUIContent m_categoryLabel = new GUIContent( "Shader Type ", "Specify the shader type you want to be working on" );
  87. protected GUIContent[] m_availableCategoryLabels;
  88. protected MasterNodeCategoriesData[] m_availableCategories;
  89. [SerializeField]
  90. private List<PropertyNode> m_propertyNodesVisibleList = new List<PropertyNode>();
  91. private ReorderableList m_propertyReordableList;
  92. protected bool m_propertyOrderChanged = false;
  93. //private int m_availableCount = 0;
  94. private int m_lastCount = 0;
  95. private GUIStyle m_propertyAdjustment;
  96. protected bool m_shaderNameIsTitle = true;
  97. void CommonInit()
  98. {
  99. m_currentMaterial = null;
  100. m_masterNodeIconCoords = new Rect( 0, 0, 64, 64 );
  101. m_isMainOutputNode = false;
  102. m_connStatus = NodeConnectionStatus.Connected;
  103. m_activeType = GetType();
  104. m_currentPrecisionType = PrecisionType.Float;
  105. m_textLabelWidth = 120;
  106. m_shaderNameContent = new GUIContent( ShaderNameStr, string.Empty );
  107. AddMasterPorts();
  108. }
  109. void InitAvailableCategories()
  110. {
  111. int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount;
  112. m_availableCategories = new MasterNodeCategoriesData[ templateCount + 1 ];
  113. m_availableCategoryLabels = new GUIContent[ templateCount + 1 ];
  114. m_availableCategories[ 0 ] = new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, string.Empty );
  115. m_availableCategoryLabels[ 0 ] = new GUIContent( "Surface" );
  116. for( int i = 0; i < templateCount; i++ )
  117. {
  118. int idx = i + 1;
  119. TemplateDataParent templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i );
  120. m_availableCategories[ idx ] = new MasterNodeCategoriesData( AvailableShaderTypes.Template, templateData.GUID );
  121. m_availableCategoryLabels[ idx ] = new GUIContent( templateData.Name );
  122. }
  123. }
  124. public void SetMasterNodeCategoryFromGUID( string GUID )
  125. {
  126. if( m_availableCategories == null )
  127. InitAvailableCategories();
  128. m_masterNodeCategory = 0;
  129. for( int i = 1; i < m_availableCategories.Length; i++ )
  130. {
  131. if( m_availableCategories[ i ].Name.Equals( GUID ) )
  132. m_masterNodeCategory = i;
  133. }
  134. }
  135. public override void SetupNodeCategories()
  136. {
  137. //base.SetupNodeCategories();
  138. ContainerGraph.ResetNodesData();
  139. int count = m_inputPorts.Count;
  140. for( int i = 0; i < count; i++ )
  141. {
  142. if( m_inputPorts[ i ].IsConnected )
  143. {
  144. NodeData nodeData = new NodeData( m_inputPorts[ i ].Category );
  145. ParentNode node = m_inputPorts[ i ].GetOutputNode();
  146. node.PropagateNodeData( nodeData, ref m_currentDataCollector );
  147. }
  148. else if( m_inputPorts[ i ].HasExternalLink )
  149. {
  150. InputPort linkedPort = m_inputPorts[ i ].ExternalLink;
  151. if( linkedPort != null && linkedPort.IsConnected )
  152. {
  153. NodeData nodeData = new NodeData( linkedPort.Category );
  154. ParentNode node = linkedPort.GetOutputNode();
  155. node.PropagateNodeData( nodeData, ref m_currentDataCollector );
  156. }
  157. }
  158. }
  159. }
  160. public virtual void RefreshAvailableCategories()
  161. {
  162. InitAvailableCategories();
  163. }
  164. public virtual void AddMasterPorts() { }
  165. public virtual void ForcePortType() { }
  166. public virtual void UpdateMasterNodeMaterial( Material material ) { }
  167. public virtual void SetName( string name ) { }
  168. public void CopyFrom( MasterNode other )
  169. {
  170. Vec2Position = other.Vec2Position;
  171. CurrentShader = other.CurrentShader;
  172. CurrentMaterial = other.CurrentMaterial;
  173. ShaderName = other.ShaderName;
  174. m_masterNodeCategory = other.CurrentMasterNodeCategoryIdx;
  175. }
  176. protected void DrawCurrentShaderType()
  177. {
  178. if( m_availableCategories == null )
  179. InitAvailableCategories();
  180. int oldType = m_masterNodeCategory;
  181. m_masterNodeCategory = EditorGUILayoutPopup( m_categoryLabel, m_masterNodeCategory, m_availableCategoryLabels );
  182. if( oldType != m_masterNodeCategory )
  183. {
  184. m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ], false );
  185. }
  186. }
  187. protected void DrawCustomInspector( bool dropdown )
  188. {
  189. EditorGUILayout.BeginHorizontal();
  190. m_customInspectorName = EditorGUILayoutTextField( CustomInspectorStr, m_customInspectorName );
  191. if( !dropdown )
  192. {
  193. if( GUILayoutButton( string.Empty, UIUtils.GetCustomStyle( CustomStyle.ResetToDefaultInspectorButton ), GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) )
  194. {
  195. GUIUtility.keyboardControl = 0;
  196. m_customInspectorName = Constants.DefaultCustomInspector;
  197. }
  198. }
  199. else
  200. {
  201. if( GUILayoutButton( string.Empty, UIUtils.InspectorPopdropdownFallback, GUILayout.Width( 17 ), GUILayout.Height( 19 ) ) )
  202. {
  203. EditorGUI.FocusTextInControl( null );
  204. GUI.FocusControl( null );
  205. GenericMenu menu = new GenericMenu();
  206. AddMenuItem( menu, Constants.DefaultCustomInspector );
  207. ASESRPBaseline version = ASESRPBaseline.ASE_SRP_INVALID;
  208. bool foundHDRP = ASEPackageManagerHelper.FoundHDRPVersion;
  209. bool foundURP = ASEPackageManagerHelper.FoundURPVersion;
  210. if( foundHDRP && foundURP )
  211. {
  212. version = ( ASEPackageManagerHelper.CurrentHDRPBaseline > ASEPackageManagerHelper.CurrentURPBaseline ) ? ASEPackageManagerHelper.CurrentHDRPBaseline : ASEPackageManagerHelper.CurrentURPBaseline;
  213. }
  214. else if( foundHDRP )
  215. {
  216. version = ASEPackageManagerHelper.CurrentHDRPBaseline;
  217. }
  218. else if( foundURP )
  219. {
  220. version = ASEPackageManagerHelper.CurrentURPBaseline;
  221. }
  222. if( foundHDRP )
  223. {
  224. if( version >= ASESRPBaseline.ASE_SRP_11 )
  225. {
  226. AddMenuItem( menu , "Rendering.HighDefinition.DecalShaderGraphGUI" );
  227. AddMenuItem( menu , "Rendering.HighDefinition.LightingShaderGraphGUI" );
  228. AddMenuItem( menu , "Rendering.HighDefinition.LitShaderGraphGUI" );
  229. AddMenuItem( menu , "Rendering.HighDefinition.HDUnlitGUI" );
  230. }
  231. else
  232. if( version >= ASESRPBaseline.ASE_SRP_10 )
  233. {
  234. AddMenuItem( menu , "Rendering.HighDefinition.DecalGUI" );
  235. AddMenuItem( menu , "Rendering.HighDefinition.LitShaderGraphGUI" );
  236. AddMenuItem( menu , "Rendering.HighDefinition.LightingShaderGraphGUI" );
  237. AddMenuItem( menu , "Rendering.HighDefinition.HDUnlitGUI" );
  238. }
  239. else if( version >= ASESRPBaseline.ASE_SRP_12 )
  240. {
  241. AddMenuItem( menu , "Rendering.HighDefinition.DecalGUI" );
  242. AddMenuItem( menu , "Rendering.HighDefinition.LitShaderGraphGUI" );
  243. AddMenuItem( menu , "Rendering.HighDefinition.LightingShaderGraphGUI" );
  244. AddMenuItem( menu , "Rendering.HighDefinition.HDUnlitGUI" );
  245. }
  246. else
  247. {
  248. AddMenuItem( menu , "UnityEditor.Rendering.HighDefinition.HDLitGUI" );
  249. }
  250. }
  251. if( foundURP )
  252. {
  253. if( version >= ASESRPBaseline.ASE_SRP_12 )
  254. {
  255. AddMenuItem( menu , "UnityEditor.ShaderGraphLitGUI" );
  256. AddMenuItem( menu , "UnityEditor.ShaderGraphUnlitGUI" );
  257. AddMenuItem( menu , "UnityEditor.Rendering.Universal.DecalShaderGraphGUI" );
  258. AddMenuItem( menu , "UnityEditor.ShaderGraphLitGUI" );
  259. }
  260. else
  261. {
  262. AddMenuItem( menu , "UnityEditor.ShaderGraph.PBRMasterGUI" );
  263. }
  264. }
  265. menu.ShowAsContext();
  266. }
  267. }
  268. EditorGUILayout.EndHorizontal();
  269. }
  270. private void AddMenuItem( GenericMenu menu, string newClass )
  271. {
  272. menu.AddItem( new GUIContent( newClass ), m_customInspectorName.Equals( newClass ), OnSelection, newClass );
  273. }
  274. private void OnSelection( object newClass )
  275. {
  276. m_customInspectorName = (string)newClass;
  277. }
  278. protected void DrawShaderName()
  279. {
  280. // this is a hack to control the automatic selection of text fields when the window is selected after serialization
  281. // by having a selectable label the focus happens on it instead and doesn't interupt the usual flow of the editor
  282. EditorGUILayout.SelectableLabel( "", GUILayout.Height( 0 ) );
  283. EditorGUI.BeginChangeCheck();
  284. string newShaderName = EditorGUILayoutTextField( m_shaderNameContent, m_shaderName );
  285. if( EditorGUI.EndChangeCheck() )
  286. {
  287. if( newShaderName.Length > 0 )
  288. {
  289. newShaderName = UIUtils.RemoveShaderInvalidCharacters( newShaderName );
  290. }
  291. else
  292. {
  293. newShaderName = Constants.DefaultShaderName;
  294. }
  295. ShaderName = newShaderName;
  296. ContainerGraph.ParentWindow.UpdateTabTitle( ShaderName, true );
  297. }
  298. m_shaderNameContent.tooltip = m_shaderName;
  299. }
  300. protected void DrawSamplingMacros()
  301. {
  302. EditorGUI.BeginChangeCheck();
  303. m_samplingMacros = EditorGUILayoutToggle( "Use Sampling Macros", m_samplingMacros );
  304. if( EditorGUI.EndChangeCheck() )
  305. ContainerGraph.SamplingMacros = SamplingMacros;
  306. }
  307. public void DrawShaderKeywords()
  308. {
  309. if( m_addShaderKeywordStyle == null )
  310. m_addShaderKeywordStyle = UIUtils.PlusStyle;
  311. if( m_removeShaderKeywordStyle == null )
  312. m_removeShaderKeywordStyle = UIUtils.MinusStyle;
  313. if( m_smallAddShaderKeywordItemStyle == null )
  314. m_smallAddShaderKeywordItemStyle = UIUtils.PlusStyle;
  315. if( m_smallRemoveShaderKeywordStyle == null )
  316. m_smallRemoveShaderKeywordStyle = UIUtils.MinusStyle;
  317. EditorGUILayout.BeginHorizontal();
  318. {
  319. m_shaderKeywordsFoldout = EditorGUILayout.Foldout( m_shaderKeywordsFoldout, ShaderKeywordsStr );
  320. // Add keyword
  321. if( GUILayout.Button( string.Empty, m_addShaderKeywordStyle ) )
  322. {
  323. m_shaderKeywords.Insert( 0, "" );
  324. }
  325. //Remove keyword
  326. if( GUILayout.Button( string.Empty, m_removeShaderKeywordStyle ) )
  327. {
  328. m_shaderKeywords.RemoveAt( m_shaderKeywords.Count - 1 );
  329. }
  330. }
  331. EditorGUILayout.EndHorizontal();
  332. if( m_shaderKeywordsFoldout )
  333. {
  334. EditorGUI.indentLevel += 1;
  335. int itemCount = m_shaderKeywords.Count;
  336. int markedToDelete = -1;
  337. for( int i = 0; i < itemCount; i++ )
  338. {
  339. EditorGUILayout.BeginHorizontal();
  340. {
  341. GUILayout.Label( " " );
  342. // Add new port
  343. if( GUILayoutButton( string.Empty, m_smallAddShaderKeywordItemStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  344. {
  345. m_shaderKeywords.Insert( i, "" );
  346. }
  347. //Remove port
  348. if( GUILayoutButton( string.Empty, m_smallRemoveShaderKeywordStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  349. {
  350. markedToDelete = i;
  351. }
  352. }
  353. EditorGUILayout.EndHorizontal();
  354. }
  355. if( markedToDelete > -1 )
  356. {
  357. m_shaderKeywords.RemoveAt( markedToDelete );
  358. }
  359. EditorGUI.indentLevel -= 1;
  360. }
  361. }
  362. public override void Draw( DrawInfo drawInfo )
  363. {
  364. if( m_availableCategories == null )
  365. InitAvailableCategories();
  366. base.Draw( drawInfo );
  367. }
  368. public override void OnNodeRepaint( DrawInfo drawInfo )
  369. {
  370. base.OnNodeRepaint( drawInfo );
  371. if( m_isMainOutputNode )
  372. {
  373. if( m_masterNodeOnTex == null )
  374. {
  375. m_masterNodeOnTex = UIUtils.MasterNodeOnTexture;
  376. }
  377. if( m_masterNodeOffTex == null )
  378. {
  379. m_masterNodeOffTex = UIUtils.MasterNodeOffTexture;
  380. }
  381. if( m_gpuInstanceOnTex == null )
  382. {
  383. m_gpuInstanceOnTex = UIUtils.GPUInstancedOnTexture;
  384. }
  385. if( m_gpuInstanceOffTex == null )
  386. {
  387. m_gpuInstanceOffTex = UIUtils.GPUInstancedOffTexture;
  388. }
  389. m_masterNodeIconCoords = m_globalPosition;
  390. m_masterNodeIconCoords.x += m_globalPosition.width - m_masterNodeOffTex.width * drawInfo.InvertedZoom;
  391. m_masterNodeIconCoords.y += m_globalPosition.height - m_masterNodeOffTex.height * drawInfo.InvertedZoom;
  392. m_masterNodeIconCoords.width = m_masterNodeOffTex.width * drawInfo.InvertedZoom;
  393. m_masterNodeIconCoords.height = m_masterNodeOffTex.height * drawInfo.InvertedZoom;
  394. GUI.DrawTexture( m_masterNodeIconCoords, m_masterNodeOffTex );
  395. if( m_gpuInstanceOnTex == null )
  396. {
  397. m_gpuInstanceOnTex = UIUtils.GPUInstancedOnTexture;
  398. }
  399. }
  400. }
  401. protected void DrawInstancedIcon( DrawInfo drawInfo )
  402. {
  403. if( m_gpuInstanceOffTex == null || drawInfo.CurrentEventType != EventType.Repaint )
  404. return;
  405. m_masterNodeIconCoords = m_globalPosition;
  406. m_masterNodeIconCoords.x += m_globalPosition.width - 5 - m_gpuInstanceOffTex.width * drawInfo.InvertedZoom;
  407. m_masterNodeIconCoords.y += m_headerPosition.height;
  408. m_masterNodeIconCoords.width = m_gpuInstanceOffTex.width * drawInfo.InvertedZoom;
  409. m_masterNodeIconCoords.height = m_gpuInstanceOffTex.height * drawInfo.InvertedZoom;
  410. GUI.DrawTexture( m_masterNodeIconCoords, m_gpuInstanceOffTex );
  411. }
  412. //public override void DrawProperties()
  413. //{
  414. // base.DrawProperties();
  415. // //EditorGUILayout.LabelField( _shaderTypeLabel );
  416. //}
  417. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  418. {
  419. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  420. //IOUtils.AddFieldValueToString( ref nodeInfo, m_isMainMasterNode );
  421. IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderModelIdx );
  422. IOUtils.AddFieldValueToString( ref nodeInfo, m_customInspectorName );
  423. IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderLOD );
  424. IOUtils.AddFieldValueToString( ref nodeInfo, m_masterNodeCategory );
  425. }
  426. public override void ReadFromString( ref string[] nodeParams )
  427. {
  428. base.ReadFromString( ref nodeParams );
  429. if( UIUtils.CurrentShaderVersion() > 21 )
  430. {
  431. m_shaderModelIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  432. if( UIUtils.CurrentShaderVersion() < 17005 )
  433. {
  434. string val = GetCurrentParam( ref nodeParams );
  435. if( m_customPrecision )
  436. {
  437. if( val.Equals( "Fixed" ) )
  438. m_currentPrecisionType = PrecisionType.Half;
  439. else
  440. m_currentPrecisionType = (PrecisionType)Enum.Parse( typeof( PrecisionType ), val );
  441. }
  442. else
  443. {
  444. m_currentPrecisionType = PrecisionType.Inherit;
  445. }
  446. }
  447. }
  448. if( UIUtils.CurrentShaderVersion() > 2404 )
  449. {
  450. m_customInspectorName = GetCurrentParam( ref nodeParams );
  451. if ( m_customInspectorName.Equals( Constants.OldCustomInspector ) )
  452. {
  453. m_customInspectorName = Constants.DefaultCustomInspector;
  454. }
  455. }
  456. if( UIUtils.CurrentShaderVersion() > 6101 )
  457. {
  458. ShaderLOD = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  459. }
  460. if( UIUtils.CurrentShaderVersion() >= 13001 )
  461. {
  462. //Debug.LogWarning( "Add correct version as soon as it is merged into master" );
  463. m_masterNodeCategory = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  464. }
  465. }
  466. public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
  467. {
  468. if( activateNode )
  469. {
  470. InputPort port = GetInputPortByUniqueId( portId );
  471. port.GetOutputNode().ActivateNode( UniqueId, portId, m_activeType );
  472. }
  473. }
  474. public void FireMaterialChangedEvt()
  475. {
  476. if( OnMaterialUpdatedEvent != null )
  477. {
  478. OnMaterialUpdatedEvent( this );
  479. }
  480. }
  481. public void FireShaderChangedEvt()
  482. {
  483. if( OnShaderUpdatedEvent != null )
  484. OnShaderUpdatedEvent( this );
  485. }
  486. public void RegisterStandaloneFuntions()
  487. {
  488. List<CustomExpressionNode> nodes = m_containerGraph.CustomExpressionOnFunctionMode.NodesList;
  489. int count = nodes.Count;
  490. Dictionary<int, CustomExpressionNode> examinedNodes = new Dictionary<int, CustomExpressionNode>();
  491. for( int i = 0; i < count; i++ )
  492. {
  493. if( nodes[ i ].AutoRegisterMode )
  494. {
  495. nodes[ i ].CheckDependencies( ref m_currentDataCollector, ref examinedNodes );
  496. }
  497. }
  498. examinedNodes.Clear();
  499. examinedNodes = null;
  500. }
  501. // What operation this node does
  502. public virtual void Execute( Shader selectedShader )
  503. {
  504. Execute( AssetDatabase.GetAssetPath( selectedShader ), false );
  505. }
  506. public virtual Shader Execute( string pathname, bool isFullPath )
  507. {
  508. ContainerGraph.ResetNodesLocalVariables();
  509. m_currentDataCollector = new MasterNodeDataCollector( this );
  510. return null;
  511. }
  512. public void CheckSamplingMacrosFlag()
  513. {
  514. if( ContainerGraph.SamplingMacros && m_currentDataCollector != null )
  515. m_currentDataCollector.AddToDirectives( Constants.SamplingMacrosDirective );
  516. }
  517. protected void SortInputPorts( ref List<InputPort> vertexPorts, ref List<InputPort> fragmentPorts )
  518. {
  519. for( int i = 0; i < m_inputPorts.Count; i++ )
  520. {
  521. if( m_inputPorts[ i ].Category == MasterNodePortCategory.Fragment || m_inputPorts[ i ].Category == MasterNodePortCategory.Debug )
  522. {
  523. if( fragmentPorts != null )
  524. fragmentPorts.Add( m_inputPorts[ i ] );
  525. }
  526. else
  527. {
  528. if( vertexPorts != null )
  529. vertexPorts.Add( m_inputPorts[ i ] );
  530. }
  531. }
  532. if( fragmentPorts.Count > 0 )
  533. {
  534. fragmentPorts.Sort( ( x, y ) => x.OrderId.CompareTo( y.OrderId ) );
  535. }
  536. if( vertexPorts.Count > 0 )
  537. {
  538. vertexPorts.Sort( ( x, y ) => x.OrderId.CompareTo( y.OrderId ) );
  539. }
  540. }
  541. protected void UpdateShaderAsset( ref string pathname, ref string shaderBody, bool isFullPath )
  542. {
  543. shaderBody = UIUtils.ForceLFLineEnding( shaderBody );
  544. // Generate Graph info
  545. shaderBody += ContainerGraph.ParentWindow.GenerateGraphInfo();
  546. //TODO: Remove current SaveDebugShader and uncomment SaveToDisk as soon as pathname is editable
  547. if( !String.IsNullOrEmpty( pathname ) )
  548. {
  549. IOUtils.StartSaveThread( shaderBody, ( isFullPath ? pathname : ( IOUtils.dataPath + pathname ) ) );
  550. }
  551. else
  552. {
  553. IOUtils.StartSaveThread( shaderBody, Application.dataPath + "/AmplifyShaderEditor/Samples/Shaders/" + m_shaderName + ".shader" );
  554. }
  555. if( CurrentShader == null )
  556. {
  557. AssetDatabase.Refresh( ImportAssetOptions.ForceUpdate );
  558. CurrentShader = Shader.Find( ShaderName );
  559. }
  560. //else
  561. //{
  562. // // need to always get asset datapath because a user can change and asset location from the project window
  563. // AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentShader ) );
  564. // //ShaderUtil.UpdateShaderAsset( m_currentShader, ShaderBody );
  565. // //ShaderImporter importer = (ShaderImporter)ShaderImporter.GetAtPath( AssetDatabase.GetAssetPath( CurrentShader ) );
  566. // //importer.SaveAndReimport();
  567. //}
  568. if( m_currentShader != null )
  569. {
  570. m_currentDataCollector.UpdateShaderImporter( ref m_currentShader );
  571. if( m_currentMaterial != null )
  572. {
  573. if( m_currentMaterial.shader != m_currentShader )
  574. m_currentMaterial.shader = m_currentShader;
  575. //m_currentDataCollector.UpdateMaterialOnPropertyNodes( m_currentMaterial );
  576. //This master node UpdateMaterial is needed on Standard Surface node to update its internal properties
  577. UpdateMaterial( m_currentMaterial );
  578. UIUtils.CurrentWindow.OutsideGraph.UpdateMaterialOnPropertyNodes( m_currentMaterial );
  579. FireMaterialChangedEvt();
  580. // need to always get asset datapath because a user can change and asset location from the project window
  581. //AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentMaterial ) );
  582. }
  583. }
  584. m_currentDataCollector.Destroy();
  585. m_currentDataCollector = null;
  586. }
  587. public void InvalidateMaterialPropertyCount()
  588. {
  589. m_lastCount = -1;
  590. }
  591. private void RefreshVisibleList( ref List<PropertyNode> allNodes )
  592. {
  593. // temp reference for lambda expression
  594. List<PropertyNode> nodes = allNodes;
  595. m_propertyNodesVisibleList.Clear();
  596. for( int i = 0; i < nodes.Count; i++ )
  597. {
  598. ReordenatorNode rnode = nodes[ i ] as ReordenatorNode;
  599. if( ( rnode == null || !rnode.IsInside ) && ( !m_propertyNodesVisibleList.Exists( x => x.PropertyName.Equals( nodes[ i ].PropertyName ) ) ) )
  600. m_propertyNodesVisibleList.Add( nodes[ i ] );
  601. }
  602. m_propertyNodesVisibleList.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  603. }
  604. public void DrawMaterialInputs( GUIStyle toolbarstyle, bool style = true )
  605. {
  606. m_propertyOrderChanged = false;
  607. Color cachedColor = GUI.color;
  608. GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f );
  609. EditorGUILayout.BeginHorizontal( toolbarstyle );
  610. GUI.color = cachedColor;
  611. EditorGUI.BeginChangeCheck();
  612. if( style )
  613. {
  614. ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties = GUILayoutToggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties, PropertyOrderFoldoutStr, UIUtils.MenuItemToggleStyle );
  615. }
  616. else
  617. {
  618. ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties = GUILayoutToggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties, PropertyOrderTemplateFoldoutStr, UIUtils.MenuItemToggleStyle );
  619. }
  620. if( EditorGUI.EndChangeCheck() )
  621. {
  622. EditorPrefs.SetBool( "ExpandedProperties", ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties );
  623. }
  624. EditorGUILayout.EndHorizontal();
  625. if( !ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties )
  626. return;
  627. cachedColor = GUI.color;
  628. GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) );
  629. EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle );
  630. GUI.color = cachedColor;
  631. List<PropertyNode> nodes = UIUtils.PropertyNodesList();
  632. if( nodes.Count != m_lastCount )
  633. {
  634. RefreshVisibleList( ref nodes );
  635. m_lastCount = nodes.Count;
  636. }
  637. if( m_propertyReordableList == null )
  638. {
  639. m_propertyReordableList = new ReorderableList( m_propertyNodesVisibleList, typeof( PropertyNode ), true, false, false, false )
  640. {
  641. headerHeight = 0,
  642. footerHeight = 0,
  643. showDefaultBackground = false,
  644. drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) =>
  645. {
  646. var first = rect;
  647. first.width *= 0.60f;
  648. EditorGUI.LabelField( first, m_propertyNodesVisibleList[ index ].PropertyInspectorName );
  649. var second = rect;
  650. second.width *= 0.4f;
  651. second.x += first.width;
  652. if( GUI.Button( second, m_propertyNodesVisibleList[ index ].PropertyName, new GUIStyle( "AssetLabel Partial" ) ) )
  653. {
  654. UIUtils.FocusOnNode( m_propertyNodesVisibleList[ index ], 1, false );
  655. }
  656. },
  657. onReorderCallback = ( list ) =>
  658. {
  659. ReorderList( ref nodes );
  660. m_propertyOrderChanged = true;
  661. //RecursiveLog();
  662. }
  663. };
  664. ReorderList( ref nodes );
  665. }
  666. if( m_propertyReordableList != null )
  667. {
  668. if( m_propertyAdjustment == null )
  669. {
  670. m_propertyAdjustment = new GUIStyle();
  671. m_propertyAdjustment.padding.left = 17;
  672. }
  673. EditorGUILayout.BeginVertical( m_propertyAdjustment );
  674. m_propertyReordableList.DoLayoutList();
  675. EditorGUILayout.EndVertical();
  676. }
  677. EditorGUILayout.EndVertical();
  678. }
  679. public void ForceReordering()
  680. {
  681. List<PropertyNode> nodes = UIUtils.PropertyNodesList();
  682. if( nodes.Count != m_lastCount )
  683. {
  684. RefreshVisibleList( ref nodes );
  685. m_lastCount = nodes.Count;
  686. }
  687. ReorderList( ref nodes );
  688. //RecursiveLog();
  689. }
  690. private void RecursiveLog()
  691. {
  692. List<PropertyNode> nodes = UIUtils.PropertyNodesList();
  693. nodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  694. for( int i = 0; i < nodes.Count; i++ )
  695. {
  696. if( ( nodes[ i ] is ReordenatorNode ) )
  697. ( nodes[ i ] as ReordenatorNode ).RecursiveLog();
  698. else
  699. Debug.Log( nodes[ i ].OrderIndex + " " + nodes[ i ].PropertyName );
  700. }
  701. }
  702. private void ReorderList( ref List<PropertyNode> nodes )
  703. {
  704. // clear lock list before reordering because of multiple sf being used
  705. for( int i = 0; i < nodes.Count; i++ )
  706. {
  707. ReordenatorNode rnode = nodes[ i ] as ReordenatorNode;
  708. if( rnode != null )
  709. rnode.RecursiveClear();
  710. }
  711. int propoffset = 0;
  712. int count = 0;
  713. for( int i = 0; i < m_propertyNodesVisibleList.Count; i++ )
  714. {
  715. ReordenatorNode renode = m_propertyNodesVisibleList[ i ] as ReordenatorNode;
  716. if( renode != null )
  717. {
  718. if( !renode.IsInside )
  719. {
  720. m_propertyNodesVisibleList[ i ].OrderIndex = count + propoffset;
  721. if( renode.PropertyListCount > 0 )
  722. {
  723. propoffset += renode.RecursiveCount();
  724. // the same reordenator can exist multiple times, apply ordering to all of them
  725. for( int j = 0; j < nodes.Count; j++ )
  726. {
  727. ReordenatorNode pnode = ( nodes[ j ] as ReordenatorNode );
  728. if( pnode != null && pnode.PropertyName.Equals( renode.PropertyName ) )
  729. {
  730. pnode.OrderIndex = renode.RawOrderIndex;
  731. pnode.RecursiveSetOrderOffset( renode.RawOrderIndex, true );
  732. }
  733. }
  734. }
  735. else
  736. {
  737. count++;
  738. }
  739. }
  740. else
  741. {
  742. m_propertyNodesVisibleList[ i ].OrderIndex = 0;
  743. }
  744. }
  745. else
  746. {
  747. m_propertyNodesVisibleList[ i ].OrderIndex = count + propoffset;
  748. count++;
  749. }
  750. }
  751. }
  752. public void CopyPropertyListFrom( MasterNode masterNode )
  753. {
  754. m_lastCount = masterNode.ReordableListLastCount;
  755. m_propertyNodesVisibleList.Clear();
  756. m_propertyNodesVisibleList.AddRange( masterNode.PropertyNodesVisibleList );
  757. }
  758. public virtual void UpdateFromShader( Shader newShader ) { }
  759. public void ClearUpdateEvents()
  760. {
  761. OnShaderUpdatedEvent = null;
  762. OnMaterialUpdatedEvent = null;
  763. }
  764. public Material CurrentMaterial { get { return m_currentMaterial; } set { m_currentMaterial = value; } }
  765. public Shader CurrentShader
  766. {
  767. set
  768. {
  769. if( value != null )
  770. {
  771. SetName( value.name );
  772. }
  773. m_currentShader = value;
  774. FireShaderChangedEvt();
  775. }
  776. get { return m_currentShader; }
  777. }
  778. public virtual void OnRefreshLinkedPortsComplete() { }
  779. public virtual void ReleaseResources() { }
  780. public override void Destroy()
  781. {
  782. base.Destroy();
  783. OnMaterialUpdatedEvent = null;
  784. OnShaderUpdatedEvent = null;
  785. m_masterNodeOnTex = null;
  786. m_masterNodeOffTex = null;
  787. m_gpuInstanceOnTex = null;
  788. m_gpuInstanceOffTex = null;
  789. m_addShaderKeywordStyle = null;
  790. m_removeShaderKeywordStyle = null;
  791. m_smallAddShaderKeywordItemStyle = null;
  792. m_smallRemoveShaderKeywordStyle = null;
  793. m_shaderKeywords.Clear();
  794. m_shaderKeywords = null;
  795. m_propertyReordableList = null;
  796. m_propertyAdjustment = null;
  797. if( m_currentDataCollector != null )
  798. {
  799. m_currentDataCollector.Destroy();
  800. m_currentDataCollector = null;
  801. }
  802. }
  803. public static void OpenShaderBody( ref string result, string name )
  804. {
  805. result += string.Format( "Shader \"{0}\"\n", name ) + "{\n";
  806. }
  807. public static void CloseShaderBody( ref string result )
  808. {
  809. result += "}\n";
  810. }
  811. public static void OpenSubShaderBody( ref string result )
  812. {
  813. result += "\n\tSubShader\n\t{\n";
  814. }
  815. public static void CloseSubShaderBody( ref string result )
  816. {
  817. result += "\t}\n";
  818. }
  819. public static void AddShaderProperty( ref string result, string name, string value )
  820. {
  821. result += string.Format( "\t{0} \"{1}\"\n", name, value );
  822. }
  823. public static void AddShaderPragma( ref string result, string value )
  824. {
  825. result += string.Format( "\t\t#pragma {0}\n", value );
  826. }
  827. public static void AddRenderState( ref string result, string state, string stateParams )
  828. {
  829. result += string.Format( "\t\t{0} {1}\n", state, stateParams );
  830. }
  831. public static void AddRenderTags( ref string result, string tags )
  832. {
  833. result += string.Format( IndentationHelper, tags ); ;
  834. }
  835. public static void AddShaderLOD( ref string result, int shaderLOD )
  836. {
  837. if( shaderLOD > 0 )
  838. {
  839. result += string.Format( ShaderLODFormat, shaderLOD );
  840. }
  841. }
  842. public static void AddMultilineBody( ref string result, string[] lines )
  843. {
  844. for( int i = 0; i < lines.Length; i++ )
  845. {
  846. result += string.Format( IndentationHelper, lines[ i ] );
  847. }
  848. }
  849. public static void OpenCGInclude( ref string result )
  850. {
  851. result += "\t\tCGINCLUDE\n";
  852. }
  853. public static void OpenCGProgram( ref string result )
  854. {
  855. result += "\t\tCGPROGRAM\n";
  856. }
  857. public static void CloseCGProgram( ref string result )
  858. {
  859. result += "\n\t\tENDCG\n";
  860. }
  861. public string ShaderName
  862. {
  863. //get { return ( ( _isHidden ? "Hidden/" : string.Empty ) + ( String.IsNullOrEmpty( _shaderCategory ) ? "" : ( _shaderCategory + "/" ) ) + _shaderName ); }
  864. get { return m_shaderName; }
  865. set
  866. {
  867. m_shaderName = value;
  868. string[] shaderNameArr = m_shaderName.Split( '/' );
  869. m_croppedShaderName = shaderNameArr[ shaderNameArr.Length - 1 ];
  870. if( m_shaderNameIsTitle )
  871. m_content.text = GenerateClippedTitle( m_croppedShaderName );
  872. m_sizeIsDirty = true;
  873. }
  874. }
  875. public string CurrentInspector { get { return m_customInspectorName; } }
  876. public string CustomInspectorFormatted { get { return string.Format( CustomInspectorFormat, m_customInspectorName ); } }
  877. public string CroppedShaderName { get { return m_croppedShaderName; } }
  878. public virtual AvailableShaderTypes CurrentMasterNodeCategory { get { return ( m_masterNodeCategory == 0 ) ? AvailableShaderTypes.SurfaceShader : AvailableShaderTypes.Template; } }
  879. public int CurrentMasterNodeCategoryIdx { get { return m_masterNodeCategory; } }
  880. public MasterNodeDataCollector CurrentDataCollector { get { return m_currentDataCollector; } set { m_currentDataCollector = value; } }
  881. public List<PropertyNode> PropertyNodesVisibleList { get { return m_propertyNodesVisibleList; } }
  882. public ReorderableList PropertyReordableList { get { return m_propertyReordableList; } }
  883. public int ReordableListLastCount { get { return m_lastCount; } }
  884. public MasterNodeCategoriesData CurrentCategoriesData { get { return m_availableCategories[ m_masterNodeCategory ]; } }
  885. public int ShaderLOD
  886. {
  887. get { return m_shaderLOD; }
  888. set
  889. {
  890. m_shaderLOD = Mathf.Max( 0, value );
  891. }
  892. }
  893. public bool SamplingMacros
  894. {
  895. get { return m_samplingMacros; }
  896. set
  897. {
  898. m_samplingMacros = value;
  899. if( IsLODMainMasterNode )
  900. ContainerGraph.SamplingMacros = value;
  901. }
  902. }
  903. }
  904. }