WirePort.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  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. namespace AmplifyShaderEditor
  7. {
  8. public enum WirePortDataType
  9. {
  10. OBJECT = 1 << 1,
  11. FLOAT = 1 << 2,
  12. FLOAT2 = 1 << 3,
  13. FLOAT3 = 1 << 4,
  14. FLOAT4 = 1 << 5,
  15. FLOAT3x3 = 1 << 6,
  16. FLOAT4x4 = 1 << 7,
  17. COLOR = 1 << 8,
  18. INT = 1 << 9,
  19. SAMPLER1D = 1 << 10,
  20. SAMPLER2D = 1 << 11,
  21. SAMPLER3D = 1 << 12,
  22. SAMPLERCUBE = 1 << 13,
  23. UINT = 1 << 14,
  24. SAMPLER2DARRAY = 1 << 15,
  25. SAMPLERSTATE = 1 << 16,
  26. UINT4 = 1 << 17
  27. }
  28. public enum VariableQualifiers
  29. {
  30. In = 0,
  31. Out,
  32. InOut
  33. }
  34. public struct WirePortDataTypeComparer : IEqualityComparer<WirePortDataType>
  35. {
  36. public bool Equals( WirePortDataType x, WirePortDataType y )
  37. {
  38. return x == y;
  39. }
  40. public int GetHashCode( WirePortDataType obj )
  41. {
  42. // you need to do some thinking here,
  43. return (int)obj;
  44. }
  45. }
  46. [System.Serializable]
  47. public class WirePort
  48. {
  49. private const double PortClickTime = 0.2;
  50. private double m_lastTimeClicked = -1;
  51. private Vector2 m_labelSize;
  52. private Vector2 m_unscaledLabelSize;
  53. protected bool m_dirtyLabelSize = true;
  54. private bool m_isEditable = false;
  55. private bool m_editingName = false;
  56. protected int m_portRestrictions = 0;
  57. private bool m_repeatButtonState = false;
  58. [SerializeField]
  59. private Rect m_position;
  60. [SerializeField]
  61. private Rect m_labelPosition;
  62. [SerializeField]
  63. protected int m_nodeId = -1;
  64. [SerializeField]
  65. protected int m_portId = -1;
  66. [SerializeField]
  67. protected int m_orderId = -1;
  68. [SerializeField]
  69. protected WirePortDataType m_dataType = WirePortDataType.FLOAT;
  70. [SerializeField]
  71. protected string m_name;
  72. [SerializeField]
  73. protected List<WireReference> m_externalReferences;
  74. [SerializeField]
  75. protected bool m_locked = false;
  76. [SerializeField]
  77. protected bool m_visible = true;
  78. [SerializeField]
  79. protected bool m_isDummy = false;
  80. [SerializeField]
  81. protected bool m_hasCustomColor = false;
  82. [SerializeField]
  83. protected Color m_customColor = Color.white;
  84. [SerializeField]
  85. protected Rect m_activePortArea;
  86. public WirePort( int nodeId, int portId, WirePortDataType dataType, string name, int orderId = -1 )
  87. {
  88. m_nodeId = nodeId;
  89. m_portId = portId;
  90. m_orderId = orderId;
  91. m_dataType = dataType;
  92. m_name = name;
  93. m_externalReferences = new List<WireReference>();
  94. }
  95. public virtual void Destroy()
  96. {
  97. m_externalReferences.Clear();
  98. m_externalReferences = null;
  99. }
  100. public void SetFreeForAll()
  101. {
  102. m_portRestrictions = -1;
  103. }
  104. public void AddPortForbiddenTypes( params WirePortDataType[] forbiddenTypes )
  105. {
  106. if( forbiddenTypes != null )
  107. {
  108. if( m_portRestrictions == 0 )
  109. {
  110. //if no previous restrictions are detected then we set up the bit array so we can set is bit correctly
  111. m_portRestrictions = int.MaxValue;
  112. }
  113. for( int i = 0; i < forbiddenTypes.Length; i++ )
  114. {
  115. m_portRestrictions = m_portRestrictions & ( int.MaxValue - (int)forbiddenTypes[ i ] );
  116. }
  117. }
  118. }
  119. public void AddPortRestrictions( params WirePortDataType[] validTypes )
  120. {
  121. if( validTypes != null )
  122. {
  123. for( int i = 0; i < validTypes.Length; i++ )
  124. {
  125. m_portRestrictions = m_portRestrictions | (int)validTypes[ i ];
  126. }
  127. }
  128. }
  129. public void CreatePortRestrictions( params WirePortDataType[] validTypes )
  130. {
  131. m_portRestrictions = 0;
  132. if( validTypes != null )
  133. {
  134. for( int i = 0; i < validTypes.Length; i++ )
  135. {
  136. m_portRestrictions = m_portRestrictions | (int)validTypes[ i ];
  137. }
  138. }
  139. }
  140. public virtual bool CheckValidType( WirePortDataType dataType )
  141. {
  142. if( m_portRestrictions == 0 )
  143. {
  144. return true;
  145. }
  146. return ( m_portRestrictions & (int)dataType ) != 0;
  147. }
  148. public bool ConnectTo( WireReference port )
  149. {
  150. if( m_locked )
  151. return false;
  152. if( m_externalReferences.Contains( port ) )
  153. return false;
  154. m_externalReferences.Add( port );
  155. return true;
  156. }
  157. public bool ConnectTo( int nodeId, int portId )
  158. {
  159. if( m_locked )
  160. return false;
  161. foreach( WireReference reference in m_externalReferences )
  162. {
  163. if( reference.NodeId == nodeId && reference.PortId == portId )
  164. {
  165. return false;
  166. }
  167. }
  168. m_externalReferences.Add( new WireReference( nodeId, portId, m_dataType, false ) );
  169. return true;
  170. }
  171. public bool ConnectTo( int nodeId, int portId, WirePortDataType dataType, bool typeLocked )
  172. {
  173. if( m_locked )
  174. return false;
  175. foreach( WireReference reference in m_externalReferences )
  176. {
  177. if( reference.NodeId == nodeId && reference.PortId == portId )
  178. {
  179. return false;
  180. }
  181. }
  182. m_externalReferences.Add( new WireReference( nodeId, portId, dataType, typeLocked ) );
  183. return true;
  184. }
  185. public void DummyAdd( int nodeId, int portId )
  186. {
  187. m_externalReferences.Insert( 0, new WireReference( nodeId, portId, WirePortDataType.OBJECT, false ) );
  188. m_isDummy = true;
  189. }
  190. public void DummyRemove()
  191. {
  192. m_externalReferences.RemoveAt( 0 );
  193. m_isDummy = false;
  194. }
  195. public void DummyClear()
  196. {
  197. m_externalReferences.Clear();
  198. m_isDummy = false;
  199. }
  200. public WireReference GetConnection( int connID = 0 )
  201. {
  202. if( connID < m_externalReferences.Count )
  203. return m_externalReferences[ connID ];
  204. return null;
  205. }
  206. public void ChangeProperties( string newName, WirePortDataType newType, bool invalidateConnections )
  207. {
  208. Name = newName;
  209. ChangeType( newType, invalidateConnections );
  210. //if ( m_dataType != newType )
  211. //{
  212. // DataType = newType;
  213. // if ( invalidateConnections )
  214. // {
  215. // InvalidateAllConnections();
  216. // }
  217. // else
  218. // {
  219. // NotifyExternalRefencesOnChange();
  220. // }
  221. //}
  222. }
  223. public void ChangeType( WirePortDataType newType, bool invalidateConnections )
  224. {
  225. if( m_dataType != newType )
  226. {
  227. //ParentNode node = UIUtils.GetNode( m_nodeId );
  228. //if ( node )
  229. //{
  230. // UndoUtils.RegisterCompleteObjectUndo( node.ContainerGraph.ParentWindow, Constants.UndoChangeTypeNodesId );
  231. // UndoUtils.RecordObject( node, Constants.UndoChangeTypeNodesId );
  232. //}
  233. DataType = newType;
  234. if( invalidateConnections )
  235. {
  236. InvalidateAllConnections();
  237. }
  238. else
  239. {
  240. NotifyExternalRefencesOnChange();
  241. }
  242. }
  243. }
  244. public virtual void ChangePortId( int newId ) { }
  245. public virtual void NotifyExternalRefencesOnChange() { }
  246. public void UpdateInfoOnExternalConn( int nodeId, int portId, WirePortDataType type )
  247. {
  248. for( int i = 0; i < m_externalReferences.Count; i++ )
  249. {
  250. if( m_externalReferences[ i ].NodeId == nodeId && m_externalReferences[ i ].PortId == portId )
  251. {
  252. m_externalReferences[ i ].DataType = type;
  253. }
  254. }
  255. }
  256. public void InvalidateConnection( int nodeId, int portId )
  257. {
  258. int id = -1;
  259. for( int i = 0; i < m_externalReferences.Count; i++ )
  260. {
  261. if( m_externalReferences[ i ].NodeId == nodeId && m_externalReferences[ i ].PortId == portId )
  262. {
  263. id = i;
  264. break;
  265. }
  266. }
  267. if( id > -1 )
  268. m_externalReferences.RemoveAt( id );
  269. }
  270. public void RemoveInvalidConnections()
  271. {
  272. Debug.Log( "Cleaning invalid connections" );
  273. List<WireReference> validConnections = new List<WireReference>();
  274. for( int i = 0; i < m_externalReferences.Count; i++ )
  275. {
  276. if( m_externalReferences[ i ].IsValid )
  277. {
  278. validConnections.Add( m_externalReferences[ i ] );
  279. }
  280. else
  281. {
  282. Debug.Log( "Detected invalid connection on node " + m_nodeId + " port " + m_portId );
  283. }
  284. }
  285. m_externalReferences.Clear();
  286. m_externalReferences = validConnections;
  287. }
  288. public void InvalidateAllConnections()
  289. {
  290. m_externalReferences.Clear();
  291. }
  292. public virtual void FullDeleteConnections() { }
  293. public bool IsConnectedTo( int nodeId, int portId )
  294. {
  295. if( m_locked )
  296. return false;
  297. for( int i = 0; i < m_externalReferences.Count; i++ )
  298. {
  299. if( m_externalReferences[ i ].NodeId == nodeId && m_externalReferences[ i ].PortId == portId )
  300. return true;
  301. }
  302. return false;
  303. }
  304. public WirePortDataType ConnectionType( int id = 0 )
  305. {
  306. return ( id < m_externalReferences.Count ) ? m_externalReferences[ id ].DataType : DataType;
  307. }
  308. public bool CheckMatchConnectionType( int id = 0 )
  309. {
  310. if( id < m_externalReferences.Count )
  311. return m_externalReferences[ id ].DataType == DataType;
  312. return false;
  313. }
  314. public void MatchPortToConnection( int id = 0 )
  315. {
  316. if( id < m_externalReferences.Count )
  317. {
  318. DataType = m_externalReferences[ id ].DataType;
  319. }
  320. }
  321. public void ResetWireReferenceStatus()
  322. {
  323. for( int i = 0; i < m_externalReferences.Count; i++ )
  324. {
  325. m_externalReferences[ i ].WireStatus = WireStatus.Default;
  326. }
  327. }
  328. public bool InsideActiveArea( Vector2 pos )
  329. {
  330. return m_activePortArea.Contains( pos );
  331. }
  332. public void Click()
  333. {
  334. if( m_isEditable )
  335. {
  336. if( ( EditorApplication.timeSinceStartup - m_lastTimeClicked ) < PortClickTime )
  337. {
  338. m_editingName = true;
  339. GUI.FocusControl( "port" + m_nodeId.ToString() + m_portId.ToString() );
  340. TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl );
  341. if( te != null )
  342. {
  343. te.SelectAll();
  344. }
  345. }
  346. m_lastTimeClicked = EditorApplication.timeSinceStartup;
  347. }
  348. }
  349. public bool Draw( Rect textPos, GUIStyle style )
  350. {
  351. bool changeFlag = false;
  352. if( m_isEditable && m_editingName )
  353. {
  354. textPos.width = m_labelSize.x;
  355. EditorGUI.BeginChangeCheck();
  356. GUI.SetNextControlName( "port" + m_nodeId.ToString() + m_portId.ToString() );
  357. m_name = GUI.TextField( textPos, m_name, style );
  358. if( EditorGUI.EndChangeCheck() )
  359. {
  360. m_dirtyLabelSize = true;
  361. changeFlag = true;
  362. }
  363. if( Event.current.isKey && ( Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter ) )
  364. {
  365. m_editingName = false;
  366. GUIUtility.keyboardControl = 0;
  367. }
  368. }
  369. else
  370. {
  371. GUI.Label( textPos, m_name, style );
  372. }
  373. //GUI.Label( textPos, string.Empty );
  374. return changeFlag;
  375. }
  376. public void ResetEditing()
  377. {
  378. m_editingName = false;
  379. }
  380. public virtual void ForceClearConnection() { }
  381. public bool IsConnected
  382. {
  383. get { return ( m_externalReferences.Count > 0 && !m_locked ); }
  384. }
  385. public List<WireReference> ExternalReferences
  386. {
  387. get { return m_externalReferences; }
  388. }
  389. public int ConnectionCount
  390. {
  391. get { return m_externalReferences.Count; }
  392. }
  393. public Rect Position
  394. {
  395. get { return m_position; }
  396. set { m_position = value; }
  397. }
  398. public Rect LabelPosition
  399. {
  400. get { return m_labelPosition; }
  401. set { m_labelPosition = value; }
  402. }
  403. public int PortId
  404. {
  405. get { return m_portId; }
  406. set { m_portId = value; }
  407. }
  408. public int OrderId
  409. {
  410. get { return m_orderId; }
  411. set { m_orderId = value; }
  412. }
  413. public int NodeId
  414. {
  415. get { return m_nodeId; }
  416. set { m_nodeId = value; }
  417. }
  418. public virtual WirePortDataType DataType
  419. {
  420. get { return m_dataType; }
  421. set { m_dataType = value; }
  422. }
  423. public bool Visible
  424. {
  425. get { return m_visible; }
  426. set
  427. {
  428. m_visible = value;
  429. if( !m_visible && IsConnected )
  430. {
  431. ForceClearConnection();
  432. }
  433. }
  434. }
  435. public bool Locked
  436. {
  437. get { return m_locked; }
  438. set
  439. {
  440. //if ( m_locked && IsConnected )
  441. //{
  442. // ForceClearConnection();
  443. //}
  444. m_locked = value;
  445. }
  446. }
  447. public virtual string Name
  448. {
  449. get { return m_name; }
  450. set { m_name = value; m_dirtyLabelSize = true; }
  451. }
  452. public bool DirtyLabelSize
  453. {
  454. get { return m_dirtyLabelSize; }
  455. set { m_dirtyLabelSize = value; }
  456. }
  457. public bool HasCustomColor
  458. {
  459. get { return m_hasCustomColor; }
  460. }
  461. public Color CustomColor
  462. {
  463. get { return m_customColor; }
  464. set
  465. {
  466. m_hasCustomColor = true;
  467. m_customColor = value;
  468. }
  469. }
  470. public Rect ActivePortArea
  471. {
  472. get { return m_activePortArea; }
  473. set { m_activePortArea = value; }
  474. }
  475. public Vector2 LabelSize
  476. {
  477. get { return m_labelSize; }
  478. set { m_labelSize = value; }
  479. }
  480. public Vector2 UnscaledLabelSize
  481. {
  482. get { return m_unscaledLabelSize; }
  483. set { m_unscaledLabelSize = value; }
  484. }
  485. public bool IsEditable
  486. {
  487. get { return m_isEditable; }
  488. set { m_isEditable = value; }
  489. }
  490. public bool Available { get { return m_visible && !m_locked; } }
  491. public override string ToString()
  492. {
  493. string dump = "";
  494. dump += "Order: " + m_orderId + "\n";
  495. dump += "Name: " + m_name + "\n";
  496. dump += " Type: " + m_dataType;
  497. dump += " NodeId : " + m_nodeId;
  498. dump += " PortId : " + m_portId;
  499. dump += "\nConnections:\n";
  500. foreach( WireReference wirePort in m_externalReferences )
  501. {
  502. dump += wirePort + "\n";
  503. }
  504. return dump;
  505. }
  506. public bool RepeatButtonState
  507. {
  508. get { return m_repeatButtonState; }
  509. set { m_repeatButtonState = value; }
  510. }
  511. public bool IsDummy { get { return m_isDummy; } }
  512. public bool NotFreeForAllTypes { get { return m_portRestrictions != -1; } }
  513. }
  514. }