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.

318 lines
9.0 KiB

  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System.Collections.Generic;
  6. using System;
  7. namespace AmplifyShaderEditor
  8. {
  9. [Serializable]
  10. [NodeAttributes( "Function Output", "Functions", "Function Output adds an output port to the shader function, it's port type is determined automatically.", NodeAvailabilityFlags = (int)NodeAvailability.ShaderFunction )]
  11. public sealed class FunctionOutput : OutputNode
  12. {
  13. public FunctionOutput() : base() { CommonInit(); }
  14. public FunctionOutput( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { CommonInit(); }
  15. [SerializeField]
  16. private bool m_previewNode = false;
  17. [SerializeField]
  18. private string m_outputName = "Output";
  19. [SerializeField]
  20. private int m_orderIndex = -1;
  21. [SerializeField]
  22. private AmplifyShaderFunction m_function;
  23. //Title editing
  24. [SerializeField]
  25. private string m_uniqueName;
  26. private bool m_isEditing;
  27. private bool m_stopEditing;
  28. private bool m_startEditing;
  29. private double m_clickTime;
  30. private double m_doubleClickTime = 0.3;
  31. private Rect m_titleClickArea;
  32. private bool m_showTitleWhenNotEditing = true;
  33. [SerializeField]
  34. private string m_subTitle = string.Empty;
  35. void CommonInit()
  36. {
  37. m_isMainOutputNode = false;
  38. m_connStatus = NodeConnectionStatus.Connected;
  39. m_activeType = GetType();
  40. m_currentPrecisionType = PrecisionType.Float;
  41. m_textLabelWidth = 100;
  42. m_autoWrapProperties = true;
  43. AddInputPort( WirePortDataType.FLOAT, false, " " );
  44. AddOutputPort( WirePortDataType.FLOAT, " " );
  45. m_outputPorts[ 0 ].Visible = false;
  46. SetTitleText( m_outputName );
  47. m_previewShaderGUID = "e6d5f64114b18e24f99dc65290c0fe98";
  48. }
  49. public override void SetupNodeCategories()
  50. {
  51. //base.SetupNodeCategories();
  52. ContainerGraph.ResetNodesData();
  53. MasterNode masterNode = ContainerGraph.ParentWindow.CurrentGraph.CurrentMasterNode;
  54. if( masterNode != null )
  55. {
  56. int count = m_inputPorts.Count;
  57. for( int i = 0; i < count; i++ )
  58. {
  59. if( m_inputPorts[ i ].IsConnected )
  60. {
  61. NodeData nodeData = new NodeData( m_inputPorts[ i ].Category );
  62. ParentNode node = m_inputPorts[ i ].GetOutputNode();
  63. MasterNodeDataCollector temp = masterNode.CurrentDataCollector;
  64. node.PropagateNodeData( nodeData, ref temp );
  65. temp = null;
  66. }
  67. }
  68. }
  69. }
  70. protected override void OnUniqueIDAssigned()
  71. {
  72. base.OnUniqueIDAssigned();
  73. UIUtils.RegisterFunctionOutputNode( this );
  74. if( m_nodeAttribs != null )
  75. m_uniqueName = m_nodeAttribs.Name + UniqueId;
  76. }
  77. public override void Destroy()
  78. {
  79. base.Destroy();
  80. UIUtils.UnregisterFunctionOutputNode( this );
  81. }
  82. public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
  83. {
  84. base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
  85. m_inputPorts[ 0 ].MatchPortToConnection();
  86. m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false );
  87. }
  88. public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type )
  89. {
  90. base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type );
  91. m_inputPorts[ 0 ].MatchPortToConnection();
  92. m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false );
  93. }
  94. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  95. {
  96. return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector );
  97. }
  98. public override void DrawProperties()
  99. {
  100. base.DrawProperties();
  101. EditorGUI.BeginChangeCheck();
  102. m_outputName = EditorGUILayoutTextField( "Name", m_outputName );
  103. if( EditorGUI.EndChangeCheck() )
  104. {
  105. SetTitleText( m_outputName );
  106. UIUtils.UpdateFunctionOutputData( UniqueId, m_outputName );
  107. }
  108. EditorGUI.BeginDisabledGroup( m_previewNode );
  109. if( GUILayout.Button( "Set as Preview" ) )
  110. {
  111. List<FunctionOutput> allOutputs = UIUtils.FunctionOutputList();
  112. foreach( FunctionOutput item in allOutputs )
  113. item.PreviewNode = false;
  114. m_previewNode = true;
  115. }
  116. EditorGUI.EndDisabledGroup();
  117. }
  118. [SerializeField]
  119. private string m_currentTitle = string.Empty;
  120. public override void Draw( DrawInfo drawInfo )
  121. {
  122. base.Draw( drawInfo );
  123. if( m_previewNode )
  124. m_currentTitle = "Preview";
  125. else
  126. m_currentTitle = string.Empty;
  127. SetAdditonalTitleTextOnCallback( m_currentTitle, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = newSubTitle );
  128. if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
  129. {
  130. if( !m_isEditing && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_titleClickArea.Contains( drawInfo.MousePosition ) ) ) )
  131. {
  132. if( ( EditorApplication.timeSinceStartup - m_clickTime ) < m_doubleClickTime )
  133. m_startEditing = true;
  134. else
  135. GUI.FocusControl( null );
  136. m_clickTime = EditorApplication.timeSinceStartup;
  137. }
  138. else if( m_isEditing && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_titleClickArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) )
  139. {
  140. m_stopEditing = true;
  141. }
  142. if( m_isEditing || m_startEditing )
  143. {
  144. EditorGUI.BeginChangeCheck();
  145. GUI.SetNextControlName( m_uniqueName );
  146. m_outputName = EditorGUITextField( m_titleClickArea, string.Empty, m_outputName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) );
  147. if( EditorGUI.EndChangeCheck() )
  148. {
  149. SetTitleText( m_outputName );
  150. UIUtils.UpdateFunctionInputData( UniqueId, m_outputName );
  151. }
  152. if( m_startEditing )
  153. EditorGUI.FocusTextInControl( m_uniqueName );
  154. }
  155. if( drawInfo.CurrentEventType == EventType.Repaint )
  156. {
  157. if( m_startEditing )
  158. {
  159. m_startEditing = false;
  160. m_isEditing = true;
  161. }
  162. if( m_stopEditing )
  163. {
  164. m_stopEditing = false;
  165. m_isEditing = false;
  166. GUI.FocusControl( null );
  167. }
  168. }
  169. }
  170. }
  171. public override void OnNodeLayout( DrawInfo drawInfo )
  172. {
  173. // RUN LAYOUT CHANGES AFTER TITLES CHANGE
  174. base.OnNodeLayout( drawInfo );
  175. m_titleClickArea = m_titlePos;
  176. m_titleClickArea.height = Constants.NODE_HEADER_HEIGHT;
  177. }
  178. public override void OnNodeRepaint( DrawInfo drawInfo )
  179. {
  180. base.OnNodeRepaint( drawInfo );
  181. if( !m_isVisible )
  182. return;
  183. // Fixed Title ( only renders when not editing )
  184. if( m_showTitleWhenNotEditing && !m_isEditing && !m_startEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
  185. {
  186. GUI.Label( m_titleClickArea, m_content, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) );
  187. }
  188. }
  189. public override void OnNodeDoubleClicked( Vector2 currentMousePos2D )
  190. {
  191. if( currentMousePos2D.y - m_globalPosition.y > ( Constants.NODE_HEADER_HEIGHT + Constants.NODE_HEADER_EXTRA_HEIGHT ) * ContainerGraph.ParentWindow.CameraDrawInfo.InvertedZoom )
  192. {
  193. ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized;
  194. }
  195. }
  196. public WirePortDataType AutoOutputType
  197. {
  198. get { return m_inputPorts[ 0 ].DataType; }
  199. }
  200. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  201. {
  202. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  203. IOUtils.AddFieldValueToString( ref nodeInfo, m_outputName );
  204. IOUtils.AddFieldValueToString( ref nodeInfo, m_orderIndex );
  205. IOUtils.AddFieldValueToString( ref nodeInfo, m_previewNode );
  206. }
  207. public override void ReadFromString( ref string[] nodeParams )
  208. {
  209. base.ReadFromString( ref nodeParams );
  210. m_outputName = GetCurrentParam( ref nodeParams );
  211. m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  212. if( UIUtils.CurrentShaderVersion() > 13706 )
  213. m_previewNode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
  214. if( IsNodeBeingCopied )
  215. PreviewNode = false;
  216. if( m_function == null )
  217. m_function = UIUtils.CurrentWindow.OpenedShaderFunction;
  218. if( m_isMainOutputNode && m_function != null )
  219. {
  220. m_function.UpdateDirectivesList();
  221. }
  222. SetTitleText( m_outputName );
  223. UIUtils.UpdateFunctionOutputData( UniqueId, m_outputName );
  224. }
  225. public AmplifyShaderFunction Function
  226. {
  227. get { return m_function; }
  228. set
  229. {
  230. m_function = value;
  231. if( m_isMainOutputNode && m_function != null )
  232. {
  233. m_function.UpdateDirectivesList();
  234. }
  235. }
  236. }
  237. public string OutputName
  238. {
  239. get { return m_outputName; }
  240. }
  241. public int OrderIndex
  242. {
  243. get { return m_orderIndex; }
  244. set { m_orderIndex = value; }
  245. }
  246. public string SubTitle
  247. {
  248. get { return m_subTitle; }
  249. set { m_subTitle = value; }
  250. }
  251. public bool PreviewNode
  252. {
  253. get { return m_previewNode; }
  254. set
  255. {
  256. m_previewNode = value;
  257. m_sizeIsDirty = true;
  258. if( m_previewNode )
  259. {
  260. m_currentTitle = "Preview";
  261. }
  262. else
  263. {
  264. m_currentTitle = "";
  265. }
  266. }
  267. }
  268. }
  269. }