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.

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