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.

875 lines
26 KiB

  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. Fixed
  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 = 2;
  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 string m_currentShaderData = string.Empty;
  68. private Texture2D m_masterNodeOnTex;
  69. private Texture2D m_masterNodeOffTex;
  70. private Texture2D m_gpuInstanceOnTex;
  71. private Texture2D m_gpuInstanceOffTex;
  72. // Shader Keywords
  73. [SerializeField]
  74. private List<string> m_shaderKeywords = new List<string>();
  75. [SerializeField]
  76. private bool m_shaderKeywordsFoldout = true;
  77. private GUIStyle m_addShaderKeywordStyle;
  78. private GUIStyle m_removeShaderKeywordStyle;
  79. private GUIStyle m_smallAddShaderKeywordItemStyle;
  80. private GUIStyle m_smallRemoveShaderKeywordStyle;
  81. private const float ShaderKeywordButtonLayoutWidth = 15;
  82. public MasterNode() : base() { CommonInit(); }
  83. public MasterNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { CommonInit(); }
  84. protected GUIContent m_categoryLabel = new GUIContent( "Shader Type ", "Specify the shader type you want to be working on" );
  85. protected GUIContent[] m_availableCategoryLabels;
  86. protected MasterNodeCategoriesData[] m_availableCategories;
  87. [SerializeField]
  88. private List<PropertyNode> m_propertyNodesVisibleList = new List<PropertyNode>();
  89. private ReorderableList m_propertyReordableList;
  90. protected bool m_propertyOrderChanged = false;
  91. //private int m_availableCount = 0;
  92. private int m_lastCount = 0;
  93. private GUIStyle m_propertyAdjustment;
  94. protected bool m_shaderNameIsTitle = true;
  95. void CommonInit()
  96. {
  97. m_currentMaterial = null;
  98. m_masterNodeIconCoords = new Rect( 0, 0, 64, 64 );
  99. m_isMainOutputNode = false;
  100. m_connStatus = NodeConnectionStatus.Connected;
  101. m_activeType = GetType();
  102. m_currentPrecisionType = PrecisionType.Float;
  103. m_textLabelWidth = 120;
  104. m_shaderNameContent = new GUIContent( ShaderNameStr, string.Empty );
  105. AddMasterPorts();
  106. }
  107. void InitAvailableCategories()
  108. {
  109. int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount;
  110. m_availableCategories = new MasterNodeCategoriesData[ templateCount + 1 ];
  111. m_availableCategoryLabels = new GUIContent[ templateCount + 1 ];
  112. m_availableCategories[ 0 ] = new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, string.Empty );
  113. m_availableCategoryLabels[ 0 ] = new GUIContent( "Surface" );
  114. for( int i = 0; i < templateCount; i++ )
  115. {
  116. int idx = i + 1;
  117. TemplateDataParent templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i );
  118. m_availableCategories[ idx ] = new MasterNodeCategoriesData( AvailableShaderTypes.Template, templateData.GUID );
  119. m_availableCategoryLabels[ idx ] = new GUIContent( templateData.Name );
  120. }
  121. }
  122. public override void SetupNodeCategories()
  123. {
  124. //base.SetupNodeCategories();
  125. ContainerGraph.ResetNodesData();
  126. int count = m_inputPorts.Count;
  127. for( int i = 0; i < count; i++ )
  128. {
  129. if( m_inputPorts[ i ].IsConnected )
  130. {
  131. NodeData nodeData = new NodeData( m_inputPorts[ i ].Category );
  132. ParentNode node = m_inputPorts[ i ].GetOutputNode();
  133. node.PropagateNodeData( nodeData, ref m_currentDataCollector );
  134. }
  135. else if( m_inputPorts[ i ].HasExternalLink )
  136. {
  137. InputPort linkedPort = m_inputPorts[ i ].ExternalLink;
  138. if( linkedPort != null && linkedPort.IsConnected )
  139. {
  140. NodeData nodeData = new NodeData( linkedPort.Category );
  141. ParentNode node = linkedPort.GetOutputNode();
  142. node.PropagateNodeData( nodeData, ref m_currentDataCollector );
  143. }
  144. }
  145. }
  146. }
  147. public virtual void RefreshAvailableCategories()
  148. {
  149. InitAvailableCategories();
  150. }
  151. public virtual void AddMasterPorts() { }
  152. public virtual void ForcePortType() { }
  153. public virtual void UpdateMasterNodeMaterial( Material material ) { }
  154. public virtual void SetName( string name ) { }
  155. public void CopyFrom( MasterNode other )
  156. {
  157. Vec2Position = other.Vec2Position;
  158. CurrentShader = other.CurrentShader;
  159. CurrentMaterial = other.CurrentMaterial;
  160. ShaderName = other.ShaderName;
  161. m_masterNodeCategory = other.CurrentMasterNodeCategoryIdx;
  162. }
  163. protected void DrawCurrentShaderType()
  164. {
  165. if( m_availableCategories == null )
  166. InitAvailableCategories();
  167. int oldType = m_masterNodeCategory;
  168. m_masterNodeCategory = EditorGUILayoutPopup( m_categoryLabel, m_masterNodeCategory, m_availableCategoryLabels );
  169. if( oldType != m_masterNodeCategory )
  170. {
  171. m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ] , false );
  172. }
  173. }
  174. protected void DrawCustomInspector( )
  175. {
  176. EditorGUILayout.BeginHorizontal();
  177. m_customInspectorName = EditorGUILayoutTextField( CustomInspectorStr, m_customInspectorName );
  178. if( GUILayoutButton( string.Empty, UIUtils.GetCustomStyle( CustomStyle.ResetToDefaultInspectorButton ), GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) )
  179. {
  180. GUIUtility.keyboardControl = 0;
  181. m_customInspectorName = Constants.DefaultCustomInspector;
  182. }
  183. EditorGUILayout.EndHorizontal();
  184. }
  185. protected void DrawShaderName()
  186. {
  187. EditorGUI.BeginChangeCheck();
  188. string newShaderName = EditorGUILayoutTextField( m_shaderNameContent, m_shaderName );
  189. if( EditorGUI.EndChangeCheck() )
  190. {
  191. if( newShaderName.Length > 0 )
  192. {
  193. newShaderName = UIUtils.RemoveShaderInvalidCharacters( newShaderName );
  194. }
  195. else
  196. {
  197. newShaderName = Constants.DefaultShaderName;
  198. }
  199. ShaderName = newShaderName;
  200. ContainerGraph.ParentWindow.UpdateTabTitle( ShaderName, true );
  201. }
  202. m_shaderNameContent.tooltip = m_shaderName;
  203. }
  204. public void DrawShaderKeywords()
  205. {
  206. if( m_addShaderKeywordStyle == null )
  207. m_addShaderKeywordStyle = UIUtils.PlusStyle;
  208. if( m_removeShaderKeywordStyle == null )
  209. m_removeShaderKeywordStyle = UIUtils.MinusStyle;
  210. if( m_smallAddShaderKeywordItemStyle == null )
  211. m_smallAddShaderKeywordItemStyle = UIUtils.PlusStyle;
  212. if( m_smallRemoveShaderKeywordStyle == null )
  213. m_smallRemoveShaderKeywordStyle = UIUtils.MinusStyle;
  214. EditorGUILayout.BeginHorizontal();
  215. {
  216. m_shaderKeywordsFoldout = EditorGUILayout.Foldout( m_shaderKeywordsFoldout, ShaderKeywordsStr );
  217. // Add keyword
  218. if( GUILayout.Button( string.Empty, m_addShaderKeywordStyle ) )
  219. {
  220. m_shaderKeywords.Insert( 0, "" );
  221. }
  222. //Remove keyword
  223. if( GUILayout.Button( string.Empty, m_removeShaderKeywordStyle ) )
  224. {
  225. m_shaderKeywords.RemoveAt( m_shaderKeywords.Count - 1 );
  226. }
  227. }
  228. EditorGUILayout.EndHorizontal();
  229. if( m_shaderKeywordsFoldout )
  230. {
  231. EditorGUI.indentLevel += 1;
  232. int itemCount = m_shaderKeywords.Count;
  233. int markedToDelete = -1;
  234. for( int i = 0; i < itemCount; i++ )
  235. {
  236. EditorGUILayout.BeginHorizontal();
  237. {
  238. GUILayout.Label( " " );
  239. // Add new port
  240. if( GUILayoutButton( string.Empty, m_smallAddShaderKeywordItemStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  241. {
  242. m_shaderKeywords.Insert( i, "" );
  243. }
  244. //Remove port
  245. if( GUILayoutButton( string.Empty, m_smallRemoveShaderKeywordStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
  246. {
  247. markedToDelete = i;
  248. }
  249. }
  250. EditorGUILayout.EndHorizontal();
  251. }
  252. if( markedToDelete > -1 )
  253. {
  254. m_shaderKeywords.RemoveAt( markedToDelete );
  255. }
  256. EditorGUI.indentLevel -= 1;
  257. }
  258. }
  259. public override void Draw( DrawInfo drawInfo )
  260. {
  261. if( m_availableCategories == null )
  262. InitAvailableCategories();
  263. base.Draw( drawInfo );
  264. }
  265. public override void OnNodeRepaint( DrawInfo drawInfo )
  266. {
  267. base.OnNodeRepaint( drawInfo );
  268. if( m_isMainOutputNode )
  269. {
  270. if( m_masterNodeOnTex == null )
  271. {
  272. m_masterNodeOnTex = UIUtils.MasterNodeOnTexture;
  273. }
  274. if( m_masterNodeOffTex == null )
  275. {
  276. m_masterNodeOffTex = UIUtils.MasterNodeOffTexture;
  277. }
  278. if( m_gpuInstanceOnTex == null )
  279. {
  280. m_gpuInstanceOnTex = UIUtils.GPUInstancedOnTexture;
  281. }
  282. if( m_gpuInstanceOffTex == null )
  283. {
  284. m_gpuInstanceOffTex = UIUtils.GPUInstancedOffTexture;
  285. }
  286. m_masterNodeIconCoords = m_globalPosition;
  287. m_masterNodeIconCoords.x += m_globalPosition.width - m_masterNodeOffTex.width * drawInfo.InvertedZoom;
  288. m_masterNodeIconCoords.y += m_globalPosition.height - m_masterNodeOffTex.height * drawInfo.InvertedZoom;
  289. m_masterNodeIconCoords.width = m_masterNodeOffTex.width * drawInfo.InvertedZoom;
  290. m_masterNodeIconCoords.height = m_masterNodeOffTex.height * drawInfo.InvertedZoom;
  291. GUI.DrawTexture( m_masterNodeIconCoords, m_masterNodeOffTex );
  292. if( m_gpuInstanceOnTex == null )
  293. {
  294. m_gpuInstanceOnTex = UIUtils.GPUInstancedOnTexture;
  295. }
  296. }
  297. }
  298. protected void DrawInstancedIcon( DrawInfo drawInfo )
  299. {
  300. if( m_gpuInstanceOffTex == null || drawInfo.CurrentEventType != EventType.Repaint )
  301. return;
  302. m_masterNodeIconCoords = m_globalPosition;
  303. m_masterNodeIconCoords.x += m_globalPosition.width - 5 - m_gpuInstanceOffTex.width * drawInfo.InvertedZoom;
  304. m_masterNodeIconCoords.y += m_headerPosition.height;
  305. m_masterNodeIconCoords.width = m_gpuInstanceOffTex.width * drawInfo.InvertedZoom;
  306. m_masterNodeIconCoords.height = m_gpuInstanceOffTex.height * drawInfo.InvertedZoom;
  307. GUI.DrawTexture( m_masterNodeIconCoords, m_gpuInstanceOffTex );
  308. }
  309. //public override void DrawProperties()
  310. //{
  311. // base.DrawProperties();
  312. // //EditorGUILayout.LabelField( _shaderTypeLabel );
  313. //}
  314. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  315. {
  316. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  317. //IOUtils.AddFieldValueToString( ref nodeInfo, m_isMainMasterNode );
  318. IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderModelIdx );
  319. IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPrecisionType );
  320. IOUtils.AddFieldValueToString( ref nodeInfo, m_customInspectorName );
  321. IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderLOD );
  322. IOUtils.AddFieldValueToString( ref nodeInfo, m_masterNodeCategory );
  323. }
  324. public override void ReadFromString( ref string[] nodeParams )
  325. {
  326. base.ReadFromString( ref nodeParams );
  327. if( UIUtils.CurrentShaderVersion() > 21 )
  328. {
  329. m_shaderModelIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  330. m_currentPrecisionType = (PrecisionType)Enum.Parse( typeof( PrecisionType ), GetCurrentParam( ref nodeParams ) );
  331. if( m_currentPrecisionType == PrecisionType.Fixed )
  332. {
  333. m_currentPrecisionType = PrecisionType.Half;
  334. }
  335. }
  336. if( UIUtils.CurrentShaderVersion() > 2404 )
  337. {
  338. m_customInspectorName = GetCurrentParam( ref nodeParams );
  339. }
  340. if( UIUtils.CurrentShaderVersion() > 6101 )
  341. {
  342. m_shaderLOD = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  343. }
  344. if( UIUtils.CurrentShaderVersion() >= 13001 )
  345. {
  346. //Debug.LogWarning( "Add correct version as soon as it is merged into master" );
  347. m_masterNodeCategory = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  348. }
  349. }
  350. public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
  351. {
  352. if( activateNode )
  353. {
  354. InputPort port = GetInputPortByUniqueId( portId );
  355. port.GetOutputNode().ActivateNode( UniqueId, portId, m_activeType );
  356. }
  357. }
  358. public void FireMaterialChangedEvt()
  359. {
  360. if( OnMaterialUpdatedEvent != null )
  361. {
  362. OnMaterialUpdatedEvent( this );
  363. }
  364. }
  365. public void FireShaderChangedEvt()
  366. {
  367. if( OnShaderUpdatedEvent != null )
  368. OnShaderUpdatedEvent( this );
  369. }
  370. public void RegisterStandaloneFuntions()
  371. {
  372. List<CustomExpressionNode> nodes = m_containerGraph.CustomExpressionOnFunctionMode.NodesList;
  373. int count = nodes.Count;
  374. Dictionary<int, CustomExpressionNode> examinedNodes = new Dictionary<int, CustomExpressionNode>();
  375. for( int i = 0; i < count; i++ )
  376. {
  377. if( nodes[ i ].AutoRegisterMode )
  378. {
  379. nodes[ i ].CheckDependencies( ref m_currentDataCollector, ref examinedNodes);
  380. }
  381. }
  382. examinedNodes.Clear();
  383. examinedNodes = null;
  384. }
  385. // What operation this node does
  386. public virtual void Execute( Shader selectedShader )
  387. {
  388. Execute( AssetDatabase.GetAssetPath( selectedShader ), false );
  389. }
  390. public virtual Shader Execute( string pathname, bool isFullPath )
  391. {
  392. ContainerGraph.ResetNodesLocalVariables();
  393. m_currentDataCollector = new MasterNodeDataCollector( this );
  394. return null;
  395. }
  396. protected void SortInputPorts( ref List<InputPort> vertexPorts, ref List<InputPort> fragmentPorts )
  397. {
  398. for( int i = 0; i < m_inputPorts.Count; i++ )
  399. {
  400. if( m_inputPorts[ i ].Category == MasterNodePortCategory.Fragment || m_inputPorts[ i ].Category == MasterNodePortCategory.Debug )
  401. {
  402. if( fragmentPorts != null )
  403. fragmentPorts.Add( m_inputPorts[ i ] );
  404. }
  405. else
  406. {
  407. if( vertexPorts != null )
  408. vertexPorts.Add( m_inputPorts[ i ] );
  409. }
  410. }
  411. if( fragmentPorts.Count > 0 )
  412. {
  413. fragmentPorts.Sort( ( x, y ) => x.OrderId.CompareTo( y.OrderId ) );
  414. }
  415. if( vertexPorts.Count > 0 )
  416. {
  417. vertexPorts.Sort( ( x, y ) => x.OrderId.CompareTo( y.OrderId ) );
  418. }
  419. }
  420. protected void UpdateShaderAsset( ref string pathname, ref string shaderBody, bool isFullPath )
  421. {
  422. // Generate Graph info
  423. shaderBody += ContainerGraph.ParentWindow.GenerateGraphInfo();
  424. //TODO: Remove current SaveDebugShader and uncomment SaveToDisk as soon as pathname is editable
  425. if( !String.IsNullOrEmpty( pathname ) )
  426. {
  427. IOUtils.StartSaveThread( shaderBody, ( isFullPath ? pathname : ( IOUtils.dataPath + pathname ) ) );
  428. }
  429. else
  430. {
  431. IOUtils.StartSaveThread( shaderBody, Application.dataPath + "/AmplifyShaderEditor/Samples/Shaders/" + m_shaderName + ".shader" );
  432. }
  433. if( CurrentShader == null )
  434. {
  435. AssetDatabase.Refresh( ImportAssetOptions.ForceUpdate );
  436. CurrentShader = Shader.Find( ShaderName );
  437. }
  438. //else
  439. //{
  440. // // need to always get asset datapath because a user can change and asset location from the project window
  441. // AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentShader ) );
  442. // //ShaderUtil.UpdateShaderAsset( m_currentShader, ShaderBody );
  443. // //ShaderImporter importer = (ShaderImporter)ShaderImporter.GetAtPath( AssetDatabase.GetAssetPath( CurrentShader ) );
  444. // //importer.SaveAndReimport();
  445. //}
  446. if( m_currentShader != null )
  447. {
  448. m_currentDataCollector.UpdateShaderImporter( ref m_currentShader );
  449. if( m_currentMaterial != null )
  450. {
  451. if( m_currentMaterial.shader != m_currentShader )
  452. m_currentMaterial.shader = m_currentShader;
  453. m_currentDataCollector.UpdateMaterialOnPropertyNodes( m_currentMaterial );
  454. FireMaterialChangedEvt();
  455. // need to always get asset datapath because a user can change and asset location from the project window
  456. //AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentMaterial ) );
  457. }
  458. }
  459. m_currentDataCollector.Destroy();
  460. m_currentDataCollector = null;
  461. }
  462. public void InvalidateMaterialPropertyCount()
  463. {
  464. m_lastCount = -1;
  465. }
  466. private void RefreshVisibleList( ref List<PropertyNode> allNodes )
  467. {
  468. // temp reference for lambda expression
  469. List<PropertyNode> nodes = allNodes;
  470. m_propertyNodesVisibleList.Clear();
  471. for( int i = 0; i < nodes.Count; i++ )
  472. {
  473. ReordenatorNode rnode = nodes[ i ] as ReordenatorNode;
  474. if( ( rnode == null || !rnode.IsInside ) && ( !m_propertyNodesVisibleList.Exists( x => x.PropertyName.Equals( nodes[ i ].PropertyName ) ) ) )
  475. m_propertyNodesVisibleList.Add( nodes[ i ] );
  476. }
  477. m_propertyNodesVisibleList.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  478. }
  479. public void DrawMaterialInputs( GUIStyle toolbarstyle , bool style = true)
  480. {
  481. m_propertyOrderChanged = false;
  482. Color cachedColor = GUI.color;
  483. GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f );
  484. EditorGUILayout.BeginHorizontal( toolbarstyle );
  485. GUI.color = cachedColor;
  486. EditorGUI.BeginChangeCheck();
  487. if( style )
  488. {
  489. ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties = GUILayoutToggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties, PropertyOrderFoldoutStr, UIUtils.MenuItemToggleStyle );
  490. }
  491. else
  492. {
  493. ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties = GUILayoutToggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties, PropertyOrderTemplateFoldoutStr, UIUtils.MenuItemToggleStyle );
  494. }
  495. if( EditorGUI.EndChangeCheck() )
  496. {
  497. EditorPrefs.SetBool( "ExpandedProperties", ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties );
  498. }
  499. EditorGUILayout.EndHorizontal();
  500. if( !ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties )
  501. return;
  502. cachedColor = GUI.color;
  503. GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) );
  504. EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle );
  505. GUI.color = cachedColor;
  506. List<PropertyNode> nodes = UIUtils.PropertyNodesList();
  507. if( nodes.Count != m_lastCount )
  508. {
  509. RefreshVisibleList( ref nodes );
  510. m_lastCount = nodes.Count;
  511. }
  512. if( m_propertyReordableList == null )
  513. {
  514. m_propertyReordableList = new ReorderableList( m_propertyNodesVisibleList, typeof( PropertyNode ), true, false, false, false )
  515. {
  516. headerHeight = 0,
  517. footerHeight = 0,
  518. showDefaultBackground = false,
  519. drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) =>
  520. {
  521. EditorGUI.LabelField( rect, m_propertyNodesVisibleList[ index ].PropertyInspectorName );
  522. },
  523. onReorderCallback = ( list ) =>
  524. {
  525. ReorderList( ref nodes );
  526. m_propertyOrderChanged = true;
  527. //RecursiveLog();
  528. }
  529. };
  530. ReorderList( ref nodes );
  531. }
  532. if( m_propertyReordableList != null )
  533. {
  534. if( m_propertyAdjustment == null )
  535. {
  536. m_propertyAdjustment = new GUIStyle();
  537. m_propertyAdjustment.padding.left = 17;
  538. }
  539. EditorGUILayout.BeginVertical( m_propertyAdjustment );
  540. m_propertyReordableList.DoLayoutList();
  541. EditorGUILayout.EndVertical();
  542. }
  543. EditorGUILayout.EndVertical();
  544. }
  545. public void ForceReordering()
  546. {
  547. List<PropertyNode> nodes = UIUtils.PropertyNodesList();
  548. if( nodes.Count != m_lastCount )
  549. {
  550. RefreshVisibleList( ref nodes );
  551. m_lastCount = nodes.Count;
  552. }
  553. ReorderList( ref nodes );
  554. //RecursiveLog();
  555. }
  556. private void ReorderList( ref List<PropertyNode> nodes )
  557. {
  558. // clear lock list before reordering because of multiple sf being used
  559. for( int i = 0; i < nodes.Count; i++ )
  560. {
  561. ReordenatorNode rnode = nodes[ i ] as ReordenatorNode;
  562. if( rnode != null )
  563. rnode.RecursiveClear();
  564. }
  565. int propoffset = 0;
  566. int count = 0;
  567. for( int i = 0; i < m_propertyNodesVisibleList.Count; i++ )
  568. {
  569. ReordenatorNode renode = m_propertyNodesVisibleList[ i ] as ReordenatorNode;
  570. if( renode != null )
  571. {
  572. if( !renode.IsInside )
  573. {
  574. m_propertyNodesVisibleList[ i ].OrderIndex = count + propoffset;
  575. if( renode.PropertyListCount > 0 )
  576. {
  577. propoffset += renode.RecursiveCount();
  578. // the same reordenator can exist multiple times, apply ordering to all of them
  579. for( int j = 0; j < nodes.Count; j++ )
  580. {
  581. ReordenatorNode pnode = ( nodes[ j ] as ReordenatorNode );
  582. if( pnode != null && pnode.PropertyName.Equals( renode.PropertyName ) )
  583. {
  584. pnode.OrderIndex = renode.RawOrderIndex;
  585. pnode.RecursiveSetOrderOffset( renode.RawOrderIndex, true );
  586. }
  587. }
  588. }
  589. else
  590. {
  591. count++;
  592. }
  593. }
  594. else
  595. {
  596. m_propertyNodesVisibleList[ i ].OrderIndex = 0;
  597. }
  598. }
  599. else
  600. {
  601. m_propertyNodesVisibleList[ i ].OrderIndex = count + propoffset;
  602. count++;
  603. }
  604. }
  605. }
  606. public void CopyPropertyListFrom( MasterNode masterNode )
  607. {
  608. m_lastCount = masterNode.ReordableListLastCount;
  609. m_propertyNodesVisibleList.Clear();
  610. m_propertyNodesVisibleList.AddRange( masterNode.PropertyNodesVisibleList );
  611. }
  612. public virtual void UpdateFromShader( Shader newShader ) { }
  613. public void ClearUpdateEvents()
  614. {
  615. OnShaderUpdatedEvent = null;
  616. OnMaterialUpdatedEvent = null;
  617. }
  618. public Material CurrentMaterial { get { return m_currentMaterial; } set { m_currentMaterial = value; } }
  619. public Shader CurrentShader
  620. {
  621. set
  622. {
  623. if( value != null )
  624. {
  625. SetName( value.name );
  626. }
  627. m_currentShader = value;
  628. FireShaderChangedEvt();
  629. }
  630. get { return m_currentShader; }
  631. }
  632. public virtual void OnRefreshLinkedPortsComplete() { }
  633. public virtual void ReleaseResources() { }
  634. public override void Destroy()
  635. {
  636. base.Destroy();
  637. OnMaterialUpdatedEvent = null;
  638. OnShaderUpdatedEvent = null;
  639. m_masterNodeOnTex = null;
  640. m_masterNodeOffTex = null;
  641. m_gpuInstanceOnTex = null;
  642. m_gpuInstanceOffTex = null;
  643. m_addShaderKeywordStyle = null;
  644. m_removeShaderKeywordStyle = null;
  645. m_smallAddShaderKeywordItemStyle = null;
  646. m_smallRemoveShaderKeywordStyle = null;
  647. m_shaderKeywords.Clear();
  648. m_shaderKeywords = null;
  649. m_propertyReordableList = null;
  650. m_propertyAdjustment = null;
  651. if( m_currentDataCollector != null )
  652. {
  653. m_currentDataCollector.Destroy();
  654. m_currentDataCollector = null;
  655. }
  656. }
  657. public static void OpenShaderBody( ref string result, string name )
  658. {
  659. result += string.Format( "Shader \"{0}\"\n", name ) + "{\n";
  660. }
  661. public static void CloseShaderBody( ref string result )
  662. {
  663. result += "}\n";
  664. }
  665. public static void OpenSubShaderBody( ref string result )
  666. {
  667. result += "\n\tSubShader\n\t{\n";
  668. }
  669. public static void CloseSubShaderBody( ref string result )
  670. {
  671. result += "\t}\n";
  672. }
  673. public static void AddShaderProperty( ref string result, string name, string value )
  674. {
  675. result += string.Format( "\t{0} \"{1}\"\n", name, value );
  676. }
  677. public static void AddShaderPragma( ref string result, string value )
  678. {
  679. result += string.Format( "\t\t#pragma {0}\n", value );
  680. }
  681. public static void AddRenderState( ref string result, string state, string stateParams )
  682. {
  683. result += string.Format( "\t\t{0} {1}\n", state, stateParams );
  684. }
  685. public static void AddRenderTags( ref string result, string tags )
  686. {
  687. result += string.Format( IndentationHelper, tags ); ;
  688. }
  689. public static void AddShaderLOD( ref string result, int shaderLOD )
  690. {
  691. if( shaderLOD > 0 )
  692. {
  693. result += string.Format( ShaderLODFormat, shaderLOD );
  694. }
  695. }
  696. public static void AddMultilineBody( ref string result, string[] lines )
  697. {
  698. for( int i = 0; i < lines.Length; i++ )
  699. {
  700. result += string.Format( IndentationHelper, lines[ i ] );
  701. }
  702. }
  703. public static void OpenCGInclude( ref string result )
  704. {
  705. result += "\t\tCGINCLUDE\n";
  706. }
  707. public static void OpenCGProgram( ref string result )
  708. {
  709. result += "\t\tCGPROGRAM\n";
  710. }
  711. public static void CloseCGProgram( ref string result )
  712. {
  713. result += "\n\t\tENDCG\n";
  714. }
  715. public string ShaderName
  716. {
  717. //get { return ( ( _isHidden ? "Hidden/" : string.Empty ) + ( String.IsNullOrEmpty( _shaderCategory ) ? "" : ( _shaderCategory + "/" ) ) + _shaderName ); }
  718. get { return m_shaderName; }
  719. set
  720. {
  721. m_shaderName = value;
  722. string[] shaderNameArr = m_shaderName.Split( '/' );
  723. m_croppedShaderName = shaderNameArr[ shaderNameArr.Length - 1 ];
  724. if( m_shaderNameIsTitle )
  725. m_content.text = GenerateClippedTitle( m_croppedShaderName );
  726. m_sizeIsDirty = true;
  727. }
  728. }
  729. public string CustomInspectorFormatted { get { return string.Format( CustomInspectorFormat, m_customInspectorName ); } }
  730. public string CroppedShaderName { get { return m_croppedShaderName; } }
  731. public AvailableShaderTypes CurrentMasterNodeCategory { get { return ( m_masterNodeCategory == 0 ) ? AvailableShaderTypes.SurfaceShader : AvailableShaderTypes.Template; } }
  732. public int CurrentMasterNodeCategoryIdx { get { return m_masterNodeCategory; } }
  733. public MasterNodeDataCollector CurrentDataCollector { get { return m_currentDataCollector; } set { m_currentDataCollector = value; } }
  734. public List<PropertyNode> PropertyNodesVisibleList { get { return m_propertyNodesVisibleList; } }
  735. public ReorderableList PropertyReordableList { get { return m_propertyReordableList; } }
  736. public int ReordableListLastCount { get { return m_lastCount; } }
  737. }
  738. }