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.

484 lines
15 KiB

  1. using System;
  2. using UnityEngine;
  3. namespace AmplifyShaderEditor
  4. {
  5. [Serializable]
  6. [NodeAttributes( "Wire Node", "Miscellaneous", "Wire Node", null, KeyCode.None, false )]
  7. public sealed class WireNode : ParentNode
  8. {
  9. private bool m_markedToDelete = false;
  10. [SerializeField]
  11. private WirePortDataType m_visualDataType = WirePortDataType.FLOAT;
  12. bool m_forceVisualDataUpdate = false;
  13. protected override void CommonInit( int uniqueId )
  14. {
  15. base.CommonInit( uniqueId );
  16. AddInputPort( WirePortDataType.OBJECT, false, string.Empty );
  17. AddOutputPort( WirePortDataType.OBJECT, Constants.EmptyPortValue );
  18. m_tooltipText = string.Empty;
  19. m_drawPreview = false;
  20. m_drawPreviewExpander = false;
  21. m_canExpand = false;
  22. m_previewShaderGUID = "fa1e3e404e6b3c243b5527b82739d682";
  23. }
  24. public WirePortDataType GetLastInputDataTypeRecursively()
  25. {
  26. if( m_outputPorts[ 0 ].ExternalReferences.Count > 0 )
  27. {
  28. WireNode rightWire = m_outputPorts[ 0 ].GetInputNode( 0 ) as WireNode;
  29. if( rightWire != null )
  30. return rightWire.GetLastInputDataTypeRecursively();
  31. else
  32. {
  33. return m_outputPorts[ 0 ].GetInputConnection( 0 ).DataType;
  34. }
  35. }
  36. if( m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid )
  37. return m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.DataType;
  38. else
  39. return m_visualDataType;
  40. }
  41. public override WirePortDataType GetInputPortVisualDataTypeByArrayIdx( int portArrayIdx )
  42. {
  43. return m_visualDataType;
  44. }
  45. public override WirePortDataType GetOutputPortVisualDataTypeById( int portId )
  46. {
  47. return m_visualDataType;
  48. }
  49. public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
  50. {
  51. base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
  52. m_inputPorts[ 0 ].MatchPortToConnection();
  53. m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false );
  54. m_forceVisualDataUpdate = true;
  55. }
  56. public override void OnOutputPortConnected( int portId, int otherNodeId, int otherPortId )
  57. {
  58. base.OnOutputPortConnected( portId, otherNodeId, otherPortId );
  59. if( m_outputPorts[ portId ].ConnectionCount > 1 )
  60. {
  61. for( int i = 0; i < m_outputPorts[ portId ].ExternalReferences.Count; i++ )
  62. {
  63. if( m_outputPorts[ portId ].ExternalReferences[ i ].PortId != otherPortId )
  64. {
  65. UIUtils.DeleteConnection( true, m_outputPorts[ portId ].ExternalReferences[ i ].NodeId, m_outputPorts[ portId ].ExternalReferences[ i ].PortId, false, true );
  66. }
  67. }
  68. }
  69. m_inputPorts[ 0 ].NotifyExternalRefencesOnChange();
  70. m_forceVisualDataUpdate = true;
  71. }
  72. public override void OnConnectedInputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type )
  73. {
  74. base.OnConnectedInputNodeChanges( portId, otherNodeId, otherPortId, name, type );
  75. m_inputPorts[ 0 ].NotifyExternalRefencesOnChange();
  76. m_forceVisualDataUpdate = true;
  77. }
  78. public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type )
  79. {
  80. base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type );
  81. m_inputPorts[ 0 ].MatchPortToConnection();
  82. m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false );
  83. m_forceVisualDataUpdate = true;
  84. }
  85. public override void OnInputPortDisconnected( int portId )
  86. {
  87. base.OnInputPortDisconnected( portId );
  88. TestIfValid();
  89. m_forceVisualDataUpdate = true;
  90. m_outputPorts[ 0 ].NotifyExternalRefencesOnChange();
  91. }
  92. public override void OnOutputPortDisconnected( int portId )
  93. {
  94. base.OnOutputPortDisconnected( portId );
  95. TestIfValid();
  96. m_forceVisualDataUpdate = true;
  97. m_inputPorts[ 0 ].NotifyExternalRefencesOnChange();
  98. }
  99. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  100. {
  101. base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
  102. return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector );
  103. }
  104. public override void DrawProperties()
  105. {
  106. if( m_markedToDelete )
  107. return;
  108. base.DrawProperties();
  109. }
  110. public override void OnNodeLayout( DrawInfo drawInfo )
  111. {
  112. if( m_firstDraw )
  113. {
  114. m_firstDraw = false;
  115. AfterCommonInit();
  116. OnNodeChange();
  117. }
  118. if( m_forceVisualDataUpdate )
  119. {
  120. m_forceVisualDataUpdate = false;
  121. m_visualDataType = GetLastInputDataTypeRecursively();
  122. }
  123. if( m_repopulateDictionaries )
  124. {
  125. m_repopulateDictionaries = false;
  126. m_inputPortsDict.Clear();
  127. int inputCount = m_inputPorts.Count;
  128. for( int i = 0; i < inputCount; i++ )
  129. {
  130. m_inputPortsDict.Add( m_inputPorts[ i ].PortId, m_inputPorts[ i ] );
  131. }
  132. m_outputPortsDict.Clear();
  133. int outputCount = m_outputPorts.Count;
  134. for( int i = 0; i < outputCount; i++ )
  135. {
  136. m_outputPortsDict.Add( m_outputPorts[ i ].PortId, m_outputPorts[ i ] );
  137. }
  138. }
  139. if( m_sizeIsDirty )
  140. {
  141. m_sizeIsDirty = false;
  142. m_extraSize.Set( 20f, 20f );
  143. m_position.width = m_extraSize.x + UIUtils.PortsSize.x;
  144. m_position.height = m_extraSize.y + UIUtils.PortsSize.y;
  145. Vec2Position -= Position.size * 0.5f;
  146. if( OnNodeChangeSizeEvent != null )
  147. {
  148. OnNodeChangeSizeEvent( this );
  149. }
  150. ChangeSizeFinished();
  151. //ChangeSize();
  152. }
  153. CalculatePositionAndVisibility( drawInfo );
  154. // Input Ports
  155. {
  156. m_currInputPortPos = m_globalPosition;
  157. m_currInputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x;
  158. m_currInputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y;
  159. m_currInputPortPos.position = m_globalPosition.center - m_currInputPortPos.size * 0.5f;
  160. int inputCount = m_inputPorts.Count;
  161. for( int i = 0; i < inputCount; i++ )
  162. {
  163. if( m_inputPorts[ i ].Visible )
  164. {
  165. // Button
  166. m_inputPorts[ i ].Position = m_currInputPortPos;
  167. if( !m_inputPorts[ i ].Locked )
  168. {
  169. float overflow = 2;
  170. float scaledOverflow = 3 * drawInfo.InvertedZoom;
  171. m_auxRect = m_currInputPortPos;
  172. m_auxRect.yMin -= scaledOverflow + overflow;
  173. m_auxRect.yMax += scaledOverflow + overflow;
  174. m_auxRect.xMin -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
  175. m_auxRect.xMax += m_inputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
  176. m_inputPorts[ i ].ActivePortArea = m_auxRect;
  177. }
  178. m_currInputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y );
  179. }
  180. }
  181. }
  182. // Output Ports
  183. {
  184. m_currOutputPortPos = m_globalPosition;
  185. m_currOutputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x;
  186. m_currOutputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y;
  187. m_currOutputPortPos.position = m_globalPosition.center - m_currOutputPortPos.size * 0.5f;
  188. //m_currOutputPortPos.x += ( m_globalPosition.width - drawInfo.InvertedZoom * ( Constants.PORT_INITIAL_X + m_anchorAdjust ) );
  189. //m_currOutputPortPos.y += drawInfo.InvertedZoom * Constants.PORT_INITIAL_Y;// + m_extraHeaderHeight * drawInfo.InvertedZoom;
  190. int outputCount = m_outputPorts.Count;
  191. for( int i = 0; i < outputCount; i++ )
  192. {
  193. if( m_outputPorts[ i ].Visible )
  194. {
  195. //Button
  196. m_outputPorts[ i ].Position = m_currOutputPortPos;
  197. if( !m_outputPorts[ i ].Locked )
  198. {
  199. float overflow = 2;
  200. float scaledOverflow = 3 * drawInfo.InvertedZoom;
  201. m_auxRect = m_currOutputPortPos;
  202. m_auxRect.yMin -= scaledOverflow + overflow;
  203. m_auxRect.yMax += scaledOverflow + overflow;
  204. m_auxRect.xMin -= m_outputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
  205. m_auxRect.xMax += Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
  206. m_outputPorts[ i ].ActivePortArea = m_auxRect;
  207. }
  208. m_currOutputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y );
  209. }
  210. }
  211. }
  212. }
  213. public override void OnNodeRepaint( DrawInfo drawInfo )
  214. {
  215. //base.OnRepaint( drawInfo );
  216. //return;
  217. if( !m_isVisible )
  218. return;
  219. m_colorBuffer = GUI.color;
  220. // Output Ports
  221. int outputCount = m_outputPorts.Count;
  222. for( int i = 0; i < outputCount; i++ )
  223. {
  224. if( m_outputPorts[ i ].Visible )
  225. {
  226. // Output Port Icon
  227. if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
  228. {
  229. if( m_outputPorts[ i ].Locked )
  230. GUI.color = Constants.LockedPortColor;
  231. else if( ContainerGraph.ParentWindow.Options.ColoredPorts )
  232. GUI.color = UIUtils.GetColorForDataType( m_visualDataType, false, false );
  233. else
  234. GUI.color = m_outputPorts[ i ].HasCustomColor ? m_outputPorts[ i ].CustomColor : UIUtils.GetColorForDataType( m_visualDataType, true, false );
  235. GUIStyle style = m_outputPorts[ i ].IsConnected ? UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) : UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon );
  236. GUI.Label( m_outputPorts[ i ].Position, string.Empty, style );
  237. GUI.color = m_colorBuffer;
  238. }
  239. // Output Port Label
  240. if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
  241. {
  242. if( m_outputPorts[ i ].Locked )
  243. {
  244. GUI.color = Constants.PortLockedTextColor;
  245. GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel );
  246. GUI.color = m_colorBuffer;
  247. }
  248. else
  249. {
  250. GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel );
  251. }
  252. }
  253. }
  254. }
  255. // Selection Box
  256. if( m_selected )
  257. {
  258. Rect selectionBox = m_globalPosition;
  259. selectionBox.size = Vector2.one * 16 * drawInfo.InvertedZoom + Vector2.one * 4;
  260. selectionBox.center = m_globalPosition.center;
  261. GUI.DrawTexture( selectionBox, UIUtils.WireNodeSelection );
  262. GUI.color = m_colorBuffer;
  263. }
  264. }
  265. public override void DrawGUIControls( DrawInfo drawInfo )
  266. {
  267. //base.DrawGUIControls( drawInfo );
  268. }
  269. public override void Draw( DrawInfo drawInfo )
  270. {
  271. if( m_markedToDelete )
  272. return;
  273. if( drawInfo.CurrentEventType == EventType.Repaint )
  274. OnNodeRepaint( drawInfo );
  275. //base.Draw( drawInfo );
  276. if( drawInfo.CurrentEventType == EventType.Repaint )
  277. TestIfValid();
  278. }
  279. bool TestIfValid()
  280. {
  281. if( !Alive )
  282. return false;
  283. bool result = true;
  284. if( !m_inputPorts[ 0 ].IsConnected )
  285. {
  286. if( !m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid || m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid && m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.NodeId != UniqueId )
  287. {
  288. ContainerGraph.MarkWireNodeSequence( this, true );
  289. result = false;
  290. }
  291. }
  292. if( !m_outputPorts[ 0 ].IsConnected )
  293. {
  294. if( !m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid || m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid && m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.NodeId != UniqueId )
  295. {
  296. ContainerGraph.MarkWireNodeSequence( this, false );
  297. result = false;
  298. }
  299. }
  300. return result;
  301. }
  302. public Vector3 TangentDirection
  303. {
  304. get
  305. {
  306. ParentNode otherInputNode = null;
  307. ParentNode otherOutputNode = null;
  308. //defaults to itself so it can still calculate tangents
  309. WirePort otherInputPort = m_outputPorts[ 0 ];
  310. WirePort otherOutputPort = m_inputPorts[ 0 ];
  311. if( m_outputPorts[ 0 ].ConnectionCount > 0 )
  312. {
  313. otherInputNode = m_containerGraph.GetNode( m_outputPorts[ 0 ].ExternalReferences[ 0 ].NodeId );
  314. otherInputPort = otherInputNode.GetInputPortByUniqueId( m_outputPorts[ 0 ].ExternalReferences[ 0 ].PortId );
  315. }
  316. if( m_inputPorts[ 0 ].ConnectionCount > 0 )
  317. {
  318. otherOutputNode = m_containerGraph.GetNode( m_inputPorts[ 0 ].ExternalReferences[ 0 ].NodeId );
  319. otherOutputPort = otherOutputNode.GetOutputPortByUniqueId( m_inputPorts[ 0 ].ExternalReferences[ 0 ].PortId );
  320. }
  321. //TODO: it still generates crooked lines if wire nodes get too close to non-wire nodes (the fix would be to calculate the non-wire nodes magnitude properly)
  322. float mag = Constants.HORIZONTAL_TANGENT_SIZE * ContainerGraph.ParentWindow.CameraDrawInfo.InvertedZoom;
  323. Vector2 outPos;
  324. if( otherOutputNode != null && otherOutputNode.GetType() != typeof( WireNode ) )
  325. outPos = otherOutputPort.Position.position + Vector2.right * mag * 0.66f;
  326. else
  327. outPos = otherOutputPort.Position.position;
  328. Vector2 inPos;
  329. if( otherInputNode != null && otherInputNode.GetType() != typeof( WireNode ) )
  330. inPos = otherInputPort.Position.position - Vector2.right * mag * 0.66f;
  331. else
  332. inPos = otherInputPort.Position.position;
  333. Vector2 tangent = ( outPos - inPos ).normalized;
  334. return new Vector3( tangent.x, tangent.y );
  335. }
  336. }
  337. public override void RefreshExternalReferences()
  338. {
  339. base.RefreshExternalReferences();
  340. m_extraSize.Set( 20f, 20f );
  341. m_position.width = m_extraSize.x + UIUtils.PortsSize.x;
  342. m_position.height = m_extraSize.y + UIUtils.PortsSize.y;
  343. Vec2Position += Position.size * 0.5f;
  344. }
  345. public override void OnAfterDeserialize()
  346. {
  347. base.OnAfterDeserialize();
  348. m_sizeIsDirty = false;
  349. }
  350. public WireReference FindNewValidInputNode( WireNode current )
  351. {
  352. if( current.InputPorts[ 0 ].IsConnected )
  353. {
  354. ParentNode node = m_containerGraph.GetNode( current.InputPorts[ 0 ].ExternalReferences[ 0 ].NodeId );
  355. if( node != null )
  356. {
  357. WireNode wireNode = node as WireNode;
  358. if( wireNode != null && wireNode.MarkToDelete )
  359. {
  360. return FindNewValidInputNode( wireNode );
  361. }
  362. else
  363. {
  364. return current.InputPorts[ 0 ].ExternalReferences[ 0 ];
  365. }
  366. }
  367. }
  368. return null;
  369. }
  370. public WireReference FindNewValidOutputNode( WireNode current )
  371. {
  372. if( current.OutputPorts[ 0 ].IsConnected )
  373. {
  374. ParentNode node = m_containerGraph.GetNode( current.OutputPorts[ 0 ].ExternalReferences[ 0 ].NodeId );
  375. if( node != null )
  376. {
  377. WireNode wireNode = node as WireNode;
  378. if( wireNode != null && wireNode.MarkToDelete )
  379. {
  380. return FindNewValidOutputNode( wireNode );
  381. }
  382. else
  383. {
  384. return current.OutputPorts[ 0 ].ExternalReferences[ 0 ];
  385. }
  386. }
  387. }
  388. return null;
  389. }
  390. public override void Rewire()
  391. {
  392. //if ( m_inputPorts[ 0 ].ExternalReferences != null && m_inputPorts[ 0 ].ExternalReferences.Count > 0 )
  393. //{
  394. //WireReference backPort = m_inputPorts[ 0 ].ExternalReferences[ 0 ];
  395. //for ( int i = 0; i < m_outputPorts[ 0 ].ExternalReferences.Count; i++ )
  396. //{
  397. // UIUtils.CurrentWindow.ConnectInputToOutput( m_outputPorts[ 0 ].ExternalReferences[ i ].NodeId, m_outputPorts[ 0 ].ExternalReferences[ i ].PortId, backPort.NodeId, backPort.PortId );
  398. //}
  399. //}
  400. MarkToDelete = true;
  401. WireReference outputReference = FindNewValidInputNode( this );
  402. WireReference inputReference = FindNewValidOutputNode( this );
  403. if( outputReference != null && inputReference != null )
  404. {
  405. ContainerGraph.ParentWindow.ConnectInputToOutput( inputReference.NodeId, inputReference.PortId, outputReference.NodeId, outputReference.PortId );
  406. }
  407. }
  408. public bool MarkToDelete
  409. {
  410. get { return m_markedToDelete; }
  411. set { m_markedToDelete = value; }
  412. }
  413. }
  414. }