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.

5213 lines
165 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 UnityEditor.Callbacks;
  6. using System;
  7. using System.Threading;
  8. using System.Globalization;
  9. using System.Collections.Generic;
  10. namespace AmplifyShaderEditor
  11. {
  12. // Disabling Substance Deprecated warning
  13. public class AmplifyShaderEditorWindow : SearchableEditorWindow, ISerializationCallbackReceiver
  14. {
  15. public const double InactivitySaveTime = 1.0;
  16. public const string CopyCommand = "Copy";
  17. public const string PasteCommand = "Paste";
  18. public const string SelectAll = "SelectAll";
  19. public const string Duplicate = "Duplicate";
  20. public const string ObjectSelectorClosed = "ObjectSelectorClosed";
  21. public const string LiveShaderError = "Live Shader only works with an assigned Master Node on the graph";
  22. //public Texture2D MasterNodeOnTexture = null;
  23. //public Texture2D MasterNodeOffTexture = null;
  24. //public Texture2D GPUInstancedOnTexture = null;
  25. //public Texture2D GPUInstancedOffTexture = null;
  26. private bool m_initialized = false;
  27. private bool m_checkInvalidConnections = false;
  28. private bool m_afterDeserializeFlag = true;
  29. [SerializeField]
  30. private ParentGraph m_customGraph = null;
  31. // UI
  32. private Rect m_graphArea;
  33. private Texture2D m_graphBgTexture;
  34. private Texture2D m_graphFgTexture;
  35. private GUIStyle m_graphFontStyle;
  36. //private GUIStyle _borderStyle;
  37. private Texture2D m_wireTexture;
  38. [SerializeField]
  39. TemplatesManager m_templatesManager;
  40. [SerializeField]
  41. private InnerWindowEditorVariables m_innerEditorVariables;
  42. [ SerializeField]
  43. private string m_lastpath;
  44. [SerializeField]
  45. private ASESelectionMode m_selectionMode = ASESelectionMode.Shader;
  46. [SerializeField]
  47. private DuplicatePreventionBuffer m_duplicatePreventionBuffer;
  48. [SerializeField]
  49. private double m_inactivityTime = 0;
  50. // Prevent save ops every tick when on live mode
  51. [SerializeField]
  52. private double m_lastTimeSaved = 0;
  53. [SerializeField]
  54. private bool m_cacheSaveOp = false;
  55. private const double SaveTime = 1;
  56. private bool m_markedToSave = false;
  57. // Graph logic
  58. [SerializeField]
  59. private ParentGraph m_mainGraphInstance;
  60. // Camera control
  61. [SerializeField]
  62. private Vector2 m_cameraOffset;
  63. private float m_cameraSpeed = 1;
  64. private Rect m_cameraInfo;
  65. [SerializeField]
  66. private float m_cameraZoom;
  67. [SerializeField]
  68. private Vector2 m_minNodePos;
  69. [SerializeField]
  70. private Vector2 m_maxNodePos;
  71. [SerializeField]
  72. private bool m_isDirty;
  73. [SerializeField]
  74. private bool m_saveIsDirty;
  75. [SerializeField]
  76. private bool m_repaintIsDirty;
  77. [SerializeField]
  78. private bool m_liveShaderEditing = false;
  79. [SerializeField]
  80. private bool m_shaderIsModified = false;
  81. [SerializeField]
  82. private string m_lastOpenedLocation = string.Empty;
  83. [SerializeField]
  84. private bool m_zoomChanged = true;
  85. [SerializeField]
  86. private float m_lastWindowWidth = 0;
  87. [SerializeField]
  88. private int m_graphCount = 0;
  89. [SerializeField]
  90. private double m_currentInactiveTime = 0;
  91. private bool m_ctrlSCallback = false;
  92. private bool m_altBoxSelection = false;
  93. private bool m_altDragStarted = false;
  94. private bool m_altPressDown = false;
  95. private bool m_altAvailable = true;
  96. // Events
  97. private Vector3 m_currentMousePos;
  98. private Vector2 m_keyEvtMousePos2D;
  99. private Vector2 m_currentMousePos2D;
  100. private Event m_currentEvent;
  101. private string m_currentCommandName = string.Empty;
  102. private bool m_insideEditorWindow;
  103. private bool m_lostFocus = false;
  104. // Selection box for multiple node selection
  105. private bool m_multipleSelectionActive = false;
  106. private bool m_lmbPressed = false;
  107. private Vector2 m_multipleSelectionStart;
  108. private Rect m_multipleSelectionArea = new Rect( 0, 0, 0, 0 );
  109. private bool m_autoPanDirActive = false;
  110. private bool m_forceAutoPanDir = false;
  111. private bool m_refreshOnUndo = false;
  112. private bool m_loadShaderOnSelection = false;
  113. private bool m_refreshAvailableNodes = false;
  114. private double m_time;
  115. //Context Menu
  116. private Vector2 m_rmbStartPos;
  117. private Vector2 m_altKeyStartPos;
  118. private GraphContextMenu m_contextMenu;
  119. private ShortcutsManager m_shortcutManager;
  120. [SerializeField]
  121. private NodeAvailability m_currentNodeAvailability = NodeAvailability.SurfaceShader;
  122. //Clipboard
  123. private Clipboard m_clipboard;
  124. //Node Parameters Window
  125. [SerializeField]
  126. private bool m_nodeParametersWindowMaximized = true;
  127. private NodeParametersWindow m_nodeParametersWindow;
  128. // Tools Window
  129. private ToolsWindow m_toolsWindow;
  130. private ConsoleLogWindow m_consoleLogWindow;
  131. //Editor Options
  132. private OptionsWindow m_optionsWindow;
  133. // Mode Window
  134. private ShaderEditorModeWindow m_modeWindow;
  135. // Tools Window
  136. private TipsWindow m_tipsWindow;
  137. //Palette Window
  138. [SerializeField]
  139. private bool m_paletteWindowMaximized = true;
  140. private PaletteWindow m_paletteWindow;
  141. private ContextPalette m_contextPalette;
  142. private PalettePopUp m_palettePopup;
  143. private System.Type m_paletteChosenType;
  144. private AmplifyShaderFunction m_paletteChosenFunction;
  145. // In-Editor Message System
  146. GenericMessageUI m_genericMessageUI;
  147. private GUIContent m_genericMessageContent;
  148. // Drag&Drop Tool
  149. private DragAndDropTool m_dragAndDropTool;
  150. //Custom Styles
  151. //private CustomStylesContainer m_customStyles;
  152. private AmplifyShaderFunction m_previousShaderFunction;
  153. private List<MenuParent> m_registeredMenus;
  154. private PreMadeShaders m_preMadeShaders;
  155. private AutoPanData[] m_autoPanArea;
  156. private DrawInfo m_drawInfo;
  157. private KeyCode m_lastKeyPressed = KeyCode.None;
  158. private System.Type m_commentaryTypeNode;
  159. private int m_onLoadDone = 0;
  160. private float m_copyPasteDeltaMul = 0;
  161. private Vector2 m_copyPasteInitialPos = Vector2.zero;
  162. private Vector2 m_copyPasteDeltaPos = Vector2.zero;
  163. private int m_repaintCount = 0;
  164. private bool m_forceUpdateFromMaterialFlag = false;
  165. private UnityEngine.Object m_delayedLoadObject = null;
  166. private double m_focusOnSelectionTimestamp;
  167. private double m_focusOnMasterNodeTimestamp;
  168. private double m_wiredDoubleTapTimestamp;
  169. private bool m_globalPreview = false;
  170. private bool m_globalShowInternalData = false;
  171. private const double AutoZoomTime = 0.25;
  172. private const double ToggleTime = 0.25;
  173. private const double WiredDoubleTapTime = 0.25;
  174. private const double DoubleClickTime = 0.25;
  175. private Material m_delayedMaterialSet = null;
  176. private bool m_mouseDownOnValidArea = false;
  177. private bool m_removedKeyboardFocus = false;
  178. private int m_lastHotControl = -1;
  179. [SerializeField]
  180. private bool m_isShaderFunctionWindow = false;
  181. private string m_currentTitle = string.Empty;
  182. private bool m_currentTitleMod = false;
  183. //private Material m_maskingMaterial = null;
  184. //private int m_cachedProjectInLinearId = -1;
  185. private int m_cachedEditorTimeId = -1;
  186. private int m_cachedEditorDeltaTimeId = -1;
  187. //private float m_repaintFrequency = 15;
  188. //private double m_repaintTimestamp = 0;
  189. // Smooth Zoom
  190. private bool m_smoothZoom = false;
  191. private float m_targetZoom;
  192. private double m_zoomTime;
  193. private Vector2 m_zoomPivot;
  194. private float m_targetZoomIncrement;
  195. private float m_zoomVelocity = 0;
  196. // Smooth Pan
  197. private bool m_smoothOffset = false;
  198. private double m_offsetTime;
  199. private Vector2 m_targetOffset;
  200. private Vector2 m_camVelocity = Vector2.zero;
  201. // Auto-Compile samples
  202. private bool m_forcingMaterialUpdateFlag = false;
  203. private bool m_forcingMaterialUpdateOp = false;
  204. private List<Material> m_materialsToUpdate = new List<Material>();
  205. private NodeExporterUtils m_nodeExporterUtils;
  206. private bool m_performFullUndoRegister = true;
  207. [SerializeField]
  208. private AmplifyShaderFunction m_openedShaderFunction;
  209. [SerializeField]
  210. private bool m_openedAssetFromNode = false;
  211. private bool m_nodesLoadedCorrectly = false;
  212. private GUIContent NodesExceptionMessage = new GUIContent( "ASE is unable to load correctly due to some faulty other classes/plugin in your project. We advise to review all your imported plugins." );
  213. private bool m_replaceMasterNode = false;
  214. private AvailableShaderTypes m_replaceMasterNodeType;
  215. private string m_replaceMasterNodeData;
  216. private bool m_replaceMasterNodeDataFromCache;
  217. private NodeWireReferencesUtils m_wireReferenceUtils = new NodeWireReferencesUtils();
  218. private ParentNode m_nodeToFocus = null;
  219. private float m_zoomToFocus = 1.0f;
  220. private bool m_selectNodeToFocus = true;
  221. public bool CheckFunctions = false;
  222. // Unity Menu item
  223. [MenuItem( "Window/Amplify Shader Editor/Open Canvas", false, 1000 )]
  224. static void OpenMainShaderGraph()
  225. {
  226. if( IOUtils.AllOpenedWindows.Count > 0 )
  227. {
  228. AmplifyShaderEditorWindow currentWindow = CreateTab( "Empty", UIUtils.ShaderIcon );
  229. UIUtils.CurrentWindow = currentWindow;
  230. currentWindow.CreateNewGraph( "Empty" );
  231. currentWindow.Show();
  232. }
  233. else
  234. {
  235. AmplifyShaderEditorWindow currentWindow = OpenWindow( "Empty", UIUtils.ShaderIcon );
  236. currentWindow.CreateNewGraph( "Empty" );
  237. //currentWindow.Show();
  238. }
  239. }
  240. public static string GenerateTabTitle( string original, bool modified = false )
  241. {
  242. GUIContent content = new GUIContent( original );
  243. GUIStyle tabStyle = new GUIStyle( (GUIStyle)"dragtabdropwindow" );// GUI.skin.FindStyle( "dragtabdropwindow" );
  244. string finalTitle = string.Empty;
  245. bool addEllipsis = false;
  246. for( int i = 1; i <= original.Length; i++ )
  247. {
  248. content.text = original.Substring( 0, i );
  249. Vector2 titleSize = tabStyle.CalcSize( content );
  250. int maxSize = modified ? 62 : 69;
  251. if( titleSize.x > maxSize )
  252. {
  253. addEllipsis = true;
  254. break;
  255. }
  256. else
  257. {
  258. finalTitle = content.text;
  259. }
  260. }
  261. if( addEllipsis )
  262. finalTitle += "..";
  263. if( modified )
  264. finalTitle += "*";
  265. return finalTitle;
  266. }
  267. public static void ConvertShaderToASE( Shader shader )
  268. {
  269. if( UIUtils.IsUnityNativeShader( shader ) )
  270. {
  271. Debug.LogWarningFormat( "Action not allowed. Attempting to load the native {0} shader into Amplify Shader Editor", shader.name );
  272. return;
  273. }
  274. if( IOUtils.AllOpenedWindows.Count > 0 )
  275. {
  276. AmplifyShaderEditorWindow openedTab = null;
  277. for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ )
  278. {
  279. if( AssetDatabase.GetAssetPath( shader ).Equals( IOUtils.AllOpenedWindows[ i ].LastOpenedLocation ) )
  280. {
  281. openedTab = IOUtils.AllOpenedWindows[ i ];
  282. break;
  283. }
  284. }
  285. if( openedTab != null )
  286. {
  287. openedTab.wantsMouseMove = true;
  288. openedTab.ShowTab();
  289. UIUtils.CurrentWindow = openedTab;
  290. }
  291. else
  292. {
  293. EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow<AmplifyShaderEditorWindow>();
  294. AmplifyShaderEditorWindow currentWindow = CreateTab();
  295. WindowHelper.AddTab( openedWindow, currentWindow );
  296. UIUtils.CurrentWindow = currentWindow;
  297. }
  298. }
  299. else
  300. {
  301. AmplifyShaderEditorWindow currentWindow = OpenWindow( shader.name, UIUtils.ShaderIcon );
  302. UIUtils.CurrentWindow = currentWindow;
  303. }
  304. if( IOUtils.IsASEShader( shader ) )
  305. {
  306. UIUtils.CurrentWindow.LoadProjectSelected( shader );
  307. }
  308. else
  309. {
  310. UIUtils.CreateEmptyFromInvalid( shader );
  311. UIUtils.ShowMessage( "Trying to open shader not created on ASE!\nBEWARE, old data will be lost if saving it here!", MessageSeverity.Warning );
  312. if( UIUtils.CurrentWindow.LiveShaderEditing )
  313. {
  314. UIUtils.ShowMessage( "Disabling Live Shader Editing. Must manually re-enable it.", MessageSeverity.Warning );
  315. UIUtils.CurrentWindow.LiveShaderEditing = false;
  316. }
  317. }
  318. }
  319. public static void LoadMaterialToASE( Material material )
  320. {
  321. if( IOUtils.AllOpenedWindows.Count > 0 )
  322. {
  323. AmplifyShaderEditorWindow openedTab = null;
  324. for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ )
  325. {
  326. if( AssetDatabase.GetAssetPath( material.shader ).Equals( IOUtils.AllOpenedWindows[ i ].LastOpenedLocation ) )
  327. {
  328. openedTab = IOUtils.AllOpenedWindows[ i ];
  329. break;
  330. }
  331. }
  332. if( openedTab != null )
  333. {
  334. openedTab.wantsMouseMove = true;
  335. openedTab.ShowTab();
  336. UIUtils.CurrentWindow = openedTab;
  337. }
  338. else
  339. {
  340. EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow<AmplifyShaderEditorWindow>();
  341. AmplifyShaderEditorWindow currentWindow = CreateTab();
  342. WindowHelper.AddTab( openedWindow, currentWindow );
  343. UIUtils.CurrentWindow = currentWindow;
  344. }
  345. }
  346. else
  347. {
  348. AmplifyShaderEditorWindow currentWindow = OpenWindow( material.name, UIUtils.MaterialIcon );
  349. UIUtils.CurrentWindow = currentWindow;
  350. }
  351. if( IOUtils.IsASEShader( material.shader ) )
  352. {
  353. UIUtils.CurrentWindow.LoadProjectSelected( material );
  354. }
  355. else
  356. {
  357. UIUtils.CreateEmptyFromInvalid( material.shader );
  358. UIUtils.SetDelayedMaterialMode( material );
  359. }
  360. }
  361. public static void LoadShaderFunctionToASE( AmplifyShaderFunction shaderFunction, bool openedAssetFromNode )
  362. {
  363. if( IOUtils.AllOpenedWindows.Count > 0 )
  364. {
  365. AmplifyShaderEditorWindow openedTab = null;
  366. for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ )
  367. {
  368. if( AssetDatabase.GetAssetPath( shaderFunction ).Equals( IOUtils.AllOpenedWindows[ i ].LastOpenedLocation ) )
  369. {
  370. openedTab = IOUtils.AllOpenedWindows[ i ];
  371. break;
  372. }
  373. }
  374. if( openedTab != null )
  375. {
  376. openedTab.wantsMouseMove = true;
  377. openedTab.ShowTab();
  378. UIUtils.CurrentWindow = openedTab;
  379. }
  380. else
  381. {
  382. EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow<AmplifyShaderEditorWindow>();
  383. AmplifyShaderEditorWindow currentWindow = CreateTab();
  384. WindowHelper.AddTab( openedWindow, currentWindow );
  385. UIUtils.CurrentWindow = currentWindow;
  386. }
  387. }
  388. else
  389. {
  390. AmplifyShaderEditorWindow currentWindow = OpenWindow( shaderFunction.FunctionName, UIUtils.ShaderFunctionIcon );
  391. UIUtils.CurrentWindow = currentWindow;
  392. }
  393. UIUtils.CurrentWindow.OpenedAssetFromNode = openedAssetFromNode;
  394. if( IOUtils.IsShaderFunction( shaderFunction.FunctionInfo ) )
  395. {
  396. UIUtils.CurrentWindow.LoadProjectSelected( shaderFunction );
  397. }
  398. else
  399. {
  400. UIUtils.CurrentWindow.titleContent.text = GenerateTabTitle( shaderFunction.FunctionName );
  401. UIUtils.CurrentWindow.titleContent.image = UIUtils.ShaderFunctionIcon;
  402. UIUtils.CreateEmptyFunction( shaderFunction );
  403. }
  404. }
  405. public static AmplifyShaderEditorWindow OpenWindow( string title = null, Texture icon = null )
  406. {
  407. AmplifyShaderEditorWindow currentWindow = (AmplifyShaderEditorWindow)AmplifyShaderEditorWindow.GetWindow( typeof( AmplifyShaderEditorWindow ), false );
  408. currentWindow.minSize = new Vector2( ( Constants.MINIMIZE_WINDOW_LOCK_SIZE - 150 ), 270 );
  409. currentWindow.wantsMouseMove = true;
  410. if( title != null )
  411. currentWindow.titleContent.text = GenerateTabTitle( title );
  412. if( icon != null )
  413. currentWindow.titleContent.image = icon;
  414. return currentWindow;
  415. }
  416. public static AmplifyShaderEditorWindow CreateTab( string title = null, Texture icon = null )
  417. {
  418. AmplifyShaderEditorWindow currentWindow = EditorWindow.CreateInstance<AmplifyShaderEditorWindow>();
  419. currentWindow.minSize = new Vector2( ( Constants.MINIMIZE_WINDOW_LOCK_SIZE - 150 ), 270 );
  420. currentWindow.wantsMouseMove = true;
  421. if( title != null )
  422. currentWindow.titleContent.text = GenerateTabTitle( title );
  423. if( icon != null )
  424. currentWindow.titleContent.image = icon;
  425. return currentWindow;
  426. }
  427. public double CalculateInactivityTime()
  428. {
  429. double currTime = EditorApplication.timeSinceStartup;
  430. switch( Event.current.type )
  431. {
  432. case EventType.MouseDown:
  433. case EventType.MouseUp:
  434. case EventType.MouseMove:
  435. case EventType.MouseDrag:
  436. case EventType.KeyDown:
  437. case EventType.KeyUp:
  438. case EventType.ScrollWheel:
  439. case EventType.DragUpdated:
  440. case EventType.DragPerform:
  441. case EventType.DragExited:
  442. case EventType.ValidateCommand:
  443. case EventType.ExecuteCommand:
  444. {
  445. m_inactivityTime = currTime;
  446. return 0;
  447. }
  448. }
  449. return currTime - m_inactivityTime;
  450. }
  451. // Shader Graph window
  452. public override void OnEnable()
  453. {
  454. base.OnEnable();
  455. if( m_templatesManager == null )
  456. {
  457. m_templatesManager = IOUtils.FirstValidTemplatesManager;
  458. if( m_templatesManager == null )
  459. {
  460. m_templatesManager = ScriptableObject.CreateInstance<TemplatesManager>();
  461. m_templatesManager.Init();
  462. if( TemplatesManager.ShowDebugMessages )
  463. Debug.Log( "Creating Manager" );
  464. }
  465. else
  466. {
  467. if( TemplatesManager.ShowDebugMessages )
  468. Debug.Log( "Assigning Manager" );
  469. }
  470. }
  471. else if( !m_templatesManager.Initialized )
  472. {
  473. if( TemplatesManager.ShowDebugMessages )
  474. Debug.Log( "Re-Initializing Manager" );
  475. m_templatesManager.Init();
  476. }
  477. if( m_innerEditorVariables == null )
  478. {
  479. m_innerEditorVariables = new InnerWindowEditorVariables();
  480. m_innerEditorVariables.Initialize();
  481. }
  482. if( m_mainGraphInstance == null )
  483. {
  484. m_mainGraphInstance = CreateInstance<ParentGraph>();
  485. m_mainGraphInstance.Init();
  486. m_mainGraphInstance.ParentWindow = this;
  487. m_mainGraphInstance.SetGraphId( 0 );
  488. }
  489. m_mainGraphInstance.ResetEvents();
  490. m_mainGraphInstance.OnNodeEvent += OnNodeStoppedMovingEvent;
  491. m_mainGraphInstance.OnMaterialUpdatedEvent += OnMaterialUpdated;
  492. m_mainGraphInstance.OnShaderUpdatedEvent += OnShaderUpdated;
  493. m_mainGraphInstance.OnEmptyGraphDetectedEvt += OnEmptyGraphDetected;
  494. m_mainGraphInstance.OnNodeRemovedEvent += m_toolsWindow.OnNodeRemovedFromGraph;
  495. GraphCount = 1;
  496. IOUtils.Init();
  497. IOUtils.AllOpenedWindows.Add( this );
  498. // Only runs once for multiple windows
  499. EditorApplication.update -= IOUtils.UpdateIO;
  500. EditorApplication.update += IOUtils.UpdateIO;
  501. EditorApplication.update -= UpdateTime;
  502. EditorApplication.update -= UpdateNodePreviewList;
  503. EditorApplication.update += UpdateTime;
  504. EditorApplication.update += UpdateNodePreviewList;
  505. if( CurrentSelection == ASESelectionMode.ShaderFunction )
  506. {
  507. IsShaderFunctionWindow = true;
  508. }
  509. else
  510. {
  511. IsShaderFunctionWindow = false;
  512. }
  513. m_optionsWindow = new OptionsWindow( this );
  514. m_optionsWindow.Init();
  515. m_contextMenu = new GraphContextMenu( m_mainGraphInstance );
  516. m_nodesLoadedCorrectly = m_contextMenu.CorrectlyLoaded;
  517. m_paletteWindow = new PaletteWindow( this )
  518. {
  519. Resizable = true
  520. };
  521. m_paletteWindow.OnPaletteNodeCreateEvt += OnPaletteNodeCreate;
  522. m_registeredMenus.Add( m_paletteWindow );
  523. m_contextPalette = new ContextPalette( this );
  524. m_contextPalette.OnPaletteNodeCreateEvt += OnContextPaletteNodeCreate;
  525. m_registeredMenus.Add( m_contextPalette );
  526. m_genericMessageUI = new GenericMessageUI();
  527. m_genericMessageUI.OnMessageDisplayEvent += ShowMessageImmediately;
  528. Selection.selectionChanged += OnProjectSelectionChanged;
  529. #if UNITY_2018_1_OR_NEWER
  530. EditorApplication.projectChanged += OnProjectWindowChanged;
  531. #else
  532. EditorApplication.projectWindowChanged += OnProjectWindowChanged;
  533. #endif
  534. m_focusOnSelectionTimestamp = EditorApplication.timeSinceStartup;
  535. m_focusOnMasterNodeTimestamp = EditorApplication.timeSinceStartup;
  536. m_nodeParametersWindow.IsMaximized = m_innerEditorVariables.NodeParametersMaximized;
  537. if( DebugConsoleWindow.UseShaderPanelsInfo )
  538. m_nodeParametersWindow.IsMaximized = m_nodeParametersWindowMaximized;
  539. m_paletteWindow.IsMaximized = m_innerEditorVariables.NodePaletteMaximized;
  540. if( DebugConsoleWindow.UseShaderPanelsInfo )
  541. m_paletteWindow.IsMaximized = m_paletteWindowMaximized;
  542. m_shortcutManager = new ShortcutsManager();
  543. // REGISTER NODE SHORTCUTS
  544. foreach( KeyValuePair<KeyCode, ShortcutKeyData> kvp in m_contextMenu.NodeShortcuts )
  545. {
  546. m_shortcutManager.RegisterNodesShortcuts( kvp.Key, kvp.Value.Name );
  547. }
  548. // REGISTER EDITOR SHORTCUTS
  549. m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.FunctionKey, KeyCode.F1, "Open Selected Node Wiki page", () =>
  550. {
  551. List<ParentNode> selectedNodes = m_mainGraphInstance.SelectedNodes;
  552. if( selectedNodes != null && selectedNodes.Count == 1 )
  553. {
  554. Application.OpenURL( selectedNodes[ 0 ].Attributes.NodeUrl );
  555. }
  556. } );
  557. m_shortcutManager.RegisterEditorShortcut( true, KeyCode.C, "Create Commentary", () =>
  558. {
  559. // Create commentary
  560. ParentNode[] selectedNodes = m_mainGraphInstance.SelectedNodes.ToArray();
  561. UIUtils.MarkUndoAction();
  562. Undo.RegisterCompleteObjectUndo( this, "Adding Commentary Node" );
  563. CommentaryNode node = m_mainGraphInstance.CreateNode( m_commentaryTypeNode, true, -1, false ) as CommentaryNode;
  564. node.CreateFromSelectedNodes( TranformedMousePos, selectedNodes );
  565. node.Focus();
  566. m_mainGraphInstance.DeSelectAll();
  567. m_mainGraphInstance.SelectNode( node, false, false );
  568. SetSaveIsDirty();
  569. ForceRepaint();
  570. } );
  571. m_shortcutManager.RegisterEditorShortcut( true, KeyCode.F, "Focus On Selection", () =>
  572. {
  573. OnToolButtonPressed( ToolButtonType.FocusOnSelection );
  574. ForceRepaint();
  575. } );
  576. //m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.None, KeyCode.B, "New Master Node", () =>
  577. //{
  578. // OnToolButtonPressed( ToolButtonType.MasterNode );
  579. // ForceRepaint();
  580. //} );
  581. m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.None, KeyCode.Space, "Open Node Palette", null, () =>
  582. {
  583. m_contextPalette.Show( m_currentMousePos2D, m_cameraInfo );
  584. } );
  585. m_shortcutManager.RegisterEditorShortcut( true, KeyCode.W, "Toggle Colored Line Mode", () =>
  586. {
  587. m_optionsWindow.ColoredPorts = !m_optionsWindow.ColoredPorts;
  588. ForceRepaint();
  589. } );
  590. m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.Control, KeyCode.W, "Toggle Multi-Line Mode", () =>
  591. {
  592. m_optionsWindow.MultiLinePorts = !m_optionsWindow.MultiLinePorts;
  593. ForceRepaint();
  594. } );
  595. m_shortcutManager.RegisterEditorShortcut( true, KeyCode.P, "Global Preview", () =>
  596. {
  597. GlobalPreview = !GlobalPreview;
  598. EditorPrefs.SetBool( "GlobalPreview", GlobalPreview );
  599. ForceRepaint();
  600. } );
  601. GlobalShowInternalData = EditorPrefs.GetBool( "GlobalShowInternalData", false );
  602. m_shortcutManager.RegisterEditorShortcut( true, KeyCode.I, "Global Show Internal Data", () =>
  603. {
  604. GlobalShowInternalData = !GlobalShowInternalData;
  605. EditorPrefs.SetBool( "GlobalShowInternalData", GlobalShowInternalData );
  606. ForceRepaint();
  607. } );
  608. m_shortcutManager.RegisterEditorShortcut( true,EventModifiers.FunctionKey, KeyCode.Delete, "Delete selected nodes", DeleteSelectedNodeWithRepaint );
  609. m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.FunctionKey, KeyCode.Backspace, "Delete selected nodes", DeleteSelectedNodeWithRepaint );
  610. m_liveShaderEditing = m_innerEditorVariables.LiveMode;
  611. UpdateLiveUI();
  612. }
  613. public AmplifyShaderEditorWindow()
  614. {
  615. m_minNodePos = new Vector2( float.MaxValue, float.MaxValue );
  616. m_maxNodePos = new Vector2( float.MinValue, float.MinValue );
  617. m_duplicatePreventionBuffer = new DuplicatePreventionBuffer();
  618. m_commentaryTypeNode = typeof( CommentaryNode );
  619. titleContent = new GUIContent( "Shader Editor" );
  620. autoRepaintOnSceneChange = true;
  621. m_currentMousePos = new Vector3( 0, 0, 0 );
  622. m_keyEvtMousePos2D = new Vector2( 0, 0 );
  623. m_multipleSelectionStart = new Vector2( 0, 0 );
  624. m_initialized = false;
  625. m_graphBgTexture = null;
  626. m_graphFgTexture = null;
  627. m_cameraOffset = new Vector2( 0, 0 );
  628. CameraZoom = 1;
  629. m_registeredMenus = new List<MenuParent>();
  630. m_nodeParametersWindow = new NodeParametersWindow( this )
  631. {
  632. Resizable = true
  633. };
  634. m_registeredMenus.Add( m_nodeParametersWindow );
  635. m_modeWindow = new ShaderEditorModeWindow( this );
  636. //_registeredMenus.Add( _modeWindow );
  637. m_toolsWindow = new ToolsWindow( this );
  638. m_toolsWindow.ToolButtonPressedEvt += OnToolButtonPressed;
  639. m_consoleLogWindow = new ConsoleLogWindow( this );
  640. m_tipsWindow = new TipsWindow( this );
  641. m_registeredMenus.Add( m_toolsWindow );
  642. m_registeredMenus.Add( m_consoleLogWindow );
  643. m_palettePopup = new PalettePopUp();
  644. m_clipboard = new Clipboard();
  645. m_genericMessageContent = new GUIContent();
  646. m_dragAndDropTool = new DragAndDropTool();
  647. m_dragAndDropTool.OnValidDropObjectEvt += OnValidObjectsDropped;
  648. //_confirmationWindow = new ConfirmationWindow( 100, 100, 300, 100 );
  649. m_saveIsDirty = false;
  650. m_preMadeShaders = new PreMadeShaders();
  651. Undo.undoRedoPerformed += UndoRedoPerformed;
  652. float autoPanSpeed = 2;
  653. m_autoPanArea = new AutoPanData[ 4 ];
  654. m_autoPanArea[ 0 ] = new AutoPanData( AutoPanLocation.TOP, 25, autoPanSpeed * Vector2.up );
  655. m_autoPanArea[ 1 ] = new AutoPanData( AutoPanLocation.BOTTOM, 25, autoPanSpeed * Vector2.down );
  656. m_autoPanArea[ 2 ] = new AutoPanData( AutoPanLocation.LEFT, 25, autoPanSpeed * Vector2.right );
  657. m_autoPanArea[ 3 ] = new AutoPanData( AutoPanLocation.RIGHT, 25, autoPanSpeed * Vector2.left );
  658. m_drawInfo = new DrawInfo();
  659. UIUtils.CurrentWindow = this;
  660. m_nodeExporterUtils = new NodeExporterUtils( this );
  661. m_repaintIsDirty = false;
  662. m_initialized = false;
  663. }
  664. public void SetStandardShader()
  665. {
  666. m_mainGraphInstance.ReplaceMasterNode( AvailableShaderTypes.SurfaceShader );
  667. m_mainGraphInstance.FireMasterNodeReplacedEvent();
  668. }
  669. public void SetTemplateShader( string templateName, bool writeDefaultData )
  670. {
  671. TemplateDataParent templateData = m_templatesManager.GetTemplate( ( string.IsNullOrEmpty( templateName ) ? "6e114a916ca3e4b4bb51972669d463bf" : templateName ) );
  672. m_mainGraphInstance.ReplaceMasterNode( AvailableShaderTypes.Template, writeDefaultData, templateData );
  673. }
  674. public void DeleteSelectedNodeWithRepaint()
  675. {
  676. DeleteSelectedNodes();
  677. SetSaveIsDirty();
  678. }
  679. void UndoRedoPerformed()
  680. {
  681. m_repaintIsDirty = true;
  682. m_saveIsDirty = true;
  683. m_removedKeyboardFocus = true;
  684. m_refreshOnUndo = true;
  685. }
  686. void Destroy()
  687. {
  688. Undo.ClearUndo( this );
  689. m_initialized = false;
  690. m_nodeExporterUtils.Destroy();
  691. m_nodeExporterUtils = null;
  692. m_delayedMaterialSet = null;
  693. m_materialsToUpdate.Clear();
  694. m_materialsToUpdate = null;
  695. GLDraw.Destroy();
  696. UIUtils.Destroy();
  697. m_preMadeShaders.Destroy();
  698. m_preMadeShaders = null;
  699. m_registeredMenus.Clear();
  700. m_registeredMenus = null;
  701. m_mainGraphInstance.Destroy();
  702. m_mainGraphInstance = null;
  703. Resources.UnloadAsset( m_graphBgTexture );
  704. m_graphBgTexture = null;
  705. Resources.UnloadAsset( m_graphFgTexture );
  706. m_graphFgTexture = null;
  707. Resources.UnloadAsset( m_wireTexture );
  708. m_wireTexture = null;
  709. m_contextMenu.Destroy();
  710. m_contextMenu = null;
  711. m_shortcutManager.Destroy();
  712. m_shortcutManager = null;
  713. m_nodeParametersWindow.Destroy();
  714. m_nodeParametersWindow = null;
  715. m_modeWindow.Destroy();
  716. m_modeWindow = null;
  717. m_toolsWindow.Destroy();
  718. m_toolsWindow = null;
  719. m_consoleLogWindow.Destroy();
  720. m_consoleLogWindow = null;
  721. m_tipsWindow.Destroy();
  722. m_tipsWindow = null;
  723. m_optionsWindow.Destroy();
  724. m_optionsWindow = null;
  725. m_paletteWindow.Destroy();
  726. m_paletteWindow = null;
  727. m_palettePopup.Destroy();
  728. m_palettePopup = null;
  729. m_contextPalette.Destroy();
  730. m_contextPalette = null;
  731. m_clipboard.ClearClipboard();
  732. m_clipboard = null;
  733. m_genericMessageUI.Destroy();
  734. m_genericMessageUI = null;
  735. m_genericMessageContent = null;
  736. m_dragAndDropTool.Destroy();
  737. m_dragAndDropTool = null;
  738. m_openedShaderFunction = null;
  739. UIUtils.CurrentWindow = null;
  740. m_duplicatePreventionBuffer.ReleaseAllData();
  741. m_duplicatePreventionBuffer = null;
  742. #if UNITY_2018_1_OR_NEWER
  743. EditorApplication.projectChanged -= OnProjectWindowChanged;
  744. #else
  745. EditorApplication.projectWindowChanged -= OnProjectWindowChanged;
  746. #endif
  747. Selection.selectionChanged -= OnProjectSelectionChanged;
  748. IOUtils.AllOpenedWindows.Remove( this );
  749. if( IOUtils.AllOpenedWindows.Count == 0 )
  750. {
  751. m_templatesManager.Destroy();
  752. ScriptableObject.DestroyImmediate( m_templatesManager );
  753. }
  754. m_templatesManager = null;
  755. IOUtils.Destroy();
  756. Resources.UnloadUnusedAssets();
  757. GC.Collect();
  758. }
  759. void Init()
  760. {
  761. // = AssetDatabase.LoadAssetAtPath( Constants.ASEPath + "", typeof( Texture2D ) ) as Texture2D;
  762. m_graphBgTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.GraphBgTextureGUID ), typeof( Texture2D ) ) as Texture2D;
  763. if( m_graphBgTexture != null )
  764. {
  765. m_graphFgTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.GraphFgTextureGUID ), typeof( Texture2D ) ) as Texture2D;
  766. //Setup usable area
  767. m_cameraInfo = position;
  768. m_graphArea = new Rect( 0, 0, m_cameraInfo.width, m_cameraInfo.height );
  769. // Creating style state to show current selected object
  770. m_graphFontStyle = new GUIStyle()
  771. {
  772. fontSize = 32,
  773. alignment = TextAnchor.MiddleCenter,
  774. fixedWidth = m_cameraInfo.width,
  775. fixedHeight = 50,
  776. stretchWidth = true,
  777. stretchHeight = true
  778. };
  779. m_graphFontStyle.normal.textColor = Color.white;
  780. m_wireTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.WireTextureGUID ), typeof( Texture2D ) ) as Texture2D;
  781. m_initialized = m_graphBgTexture != null &&
  782. m_graphFgTexture != null &&
  783. m_wireTexture != null;
  784. }
  785. }
  786. [OnOpenAssetAttribute()]
  787. static bool OnOpenAsset( int instanceID, int line )
  788. {
  789. if( line > -1 )
  790. {
  791. return false;
  792. }
  793. Shader selectedShader = Selection.activeObject as Shader;
  794. if( selectedShader != null )
  795. {
  796. if( IOUtils.IsASEShader( selectedShader ) )
  797. {
  798. ConvertShaderToASE( selectedShader );
  799. return true;
  800. }
  801. }
  802. else
  803. {
  804. Material mat = Selection.activeObject as Material;
  805. if( mat != null )
  806. {
  807. if( IOUtils.IsASEShader( mat.shader ) )
  808. {
  809. LoadMaterialToASE( mat );
  810. return true;
  811. }
  812. }
  813. else
  814. {
  815. AmplifyShaderFunction shaderFunction = Selection.activeObject as AmplifyShaderFunction;
  816. if( shaderFunction != null )
  817. {
  818. if( IOUtils.IsShaderFunction( shaderFunction.FunctionInfo ) )
  819. {
  820. LoadShaderFunctionToASE( shaderFunction, false );
  821. return true;
  822. }
  823. }
  824. }
  825. }
  826. return false;
  827. }
  828. [MenuItem( "Assets/Create/Amplify Shader/Surface", false, 84 )]
  829. [MenuItem( "Assets/Create/Shader/Amplify Surface Shader" )]
  830. public static void CreateNewShader()
  831. {
  832. string path = string.Empty;
  833. if( Selection.activeObject != null )
  834. {
  835. path = ( IOUtils.dataPath + AssetDatabase.GetAssetPath( Selection.activeObject ) );
  836. }
  837. else
  838. {
  839. UnityEngine.Object[] selection = Selection.GetFiltered( typeof( UnityEngine.Object ), SelectionMode.DeepAssets );
  840. if( selection.Length > 0 && selection[ 0 ] != null )
  841. {
  842. path = ( IOUtils.dataPath + AssetDatabase.GetAssetPath( selection[0] ) );
  843. }
  844. else
  845. {
  846. path = Application.dataPath;
  847. }
  848. }
  849. if( path.IndexOf( '.' ) > -1 )
  850. {
  851. path = path.Substring( 0, path.LastIndexOf( '/' ) );
  852. }
  853. path += "/";
  854. if( IOUtils.AllOpenedWindows.Count > 0 )
  855. {
  856. EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow<AmplifyShaderEditorWindow>();
  857. AmplifyShaderEditorWindow currentWindow = CreateTab();
  858. WindowHelper.AddTab( openedWindow, currentWindow );
  859. UIUtils.CurrentWindow = currentWindow;
  860. Shader shader = UIUtils.CreateNewEmpty( path );
  861. Selection.activeObject = shader;
  862. }
  863. else
  864. {
  865. AmplifyShaderEditorWindow currentWindow = OpenWindow();
  866. UIUtils.CurrentWindow = currentWindow;
  867. Shader shader = UIUtils.CreateNewEmpty( path );
  868. Selection.activeObject = shader;
  869. }
  870. //Selection.objects = new UnityEngine.Object[] { shader };
  871. }
  872. public static void CreateNewTemplateShader( string templateGUID )
  873. {
  874. string path = Selection.activeObject == null ? Application.dataPath : ( IOUtils.dataPath + AssetDatabase.GetAssetPath( Selection.activeObject ) );
  875. if( path.IndexOf( '.' ) > -1 )
  876. {
  877. path = path.Substring( 0, path.LastIndexOf( '/' ) );
  878. }
  879. path += "/";
  880. if( IOUtils.AllOpenedWindows.Count > 0 )
  881. {
  882. EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow<AmplifyShaderEditorWindow>();
  883. AmplifyShaderEditorWindow currentWindow = CreateTab();
  884. WindowHelper.AddTab( openedWindow, currentWindow );
  885. UIUtils.CurrentWindow = currentWindow;
  886. Shader shader = UIUtils.CreateNewEmptyTemplate( templateGUID, path );
  887. Selection.activeObject = shader;
  888. }
  889. else
  890. {
  891. AmplifyShaderEditorWindow currentWindow = OpenWindow();
  892. UIUtils.CurrentWindow = currentWindow;
  893. Shader shader = UIUtils.CreateNewEmptyTemplate( templateGUID, path );
  894. Selection.activeObject = shader;
  895. }
  896. //Selection.objects = new UnityEngine.Object[] { shader };
  897. }
  898. [MenuItem( "Assets/Create/Amplify Shader Function", false, 84 )]
  899. [MenuItem( "Assets/Create/Shader/Amplify Shader Function" )]
  900. public static void CreateNewShaderFunction()
  901. {
  902. AmplifyShaderFunction asset = ScriptableObject.CreateInstance<AmplifyShaderFunction>();
  903. string path = AssetDatabase.GetAssetPath( Selection.activeObject );
  904. if( path == "" )
  905. {
  906. path = "Assets";
  907. }
  908. else if( System.IO.Path.GetExtension( path ) != "" )
  909. {
  910. path = path.Replace( System.IO.Path.GetFileName( AssetDatabase.GetAssetPath( Selection.activeObject ) ), "" );
  911. }
  912. string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath( path + "/New ShaderFunction.asset" );
  913. var endNameEditAction = ScriptableObject.CreateInstance<DoCreateFunction>();
  914. ProjectWindowUtil.StartNameEditingIfProjectWindowExists( asset.GetInstanceID(), endNameEditAction, assetPathAndName, AssetPreview.GetMiniThumbnail( asset ), null );
  915. }
  916. public void UpdateTabTitle( string newTitle, bool modified )
  917. {
  918. string[] titleArray = newTitle.Split( '/' );
  919. newTitle = titleArray[ titleArray.Length - 1 ];
  920. if( !( m_currentTitle.Equals( newTitle ) && m_currentTitleMod == modified ) )
  921. {
  922. this.titleContent.text = GenerateTabTitle( newTitle, modified );
  923. }
  924. m_currentTitle = newTitle;
  925. m_currentTitleMod = modified;
  926. }
  927. public void OnProjectWindowChanged()
  928. {
  929. Shader selectedShader = Selection.activeObject as Shader;
  930. if( selectedShader != null )
  931. {
  932. if( m_mainGraphInstance != null && m_mainGraphInstance.CurrentMasterNode != null && selectedShader == m_mainGraphInstance.CurrentMasterNode.CurrentShader )
  933. {
  934. m_lastOpenedLocation = AssetDatabase.GetAssetPath( selectedShader );
  935. }
  936. }
  937. }
  938. public void LoadProjectSelected( UnityEngine.Object selectedObject = null )
  939. {
  940. bool hasFocus = true;
  941. if( EditorWindow.focusedWindow != this )
  942. {
  943. hasFocus = false;
  944. }
  945. if( hasFocus && m_mainGraphInstance != null && m_mainGraphInstance.CurrentMasterNode != null )
  946. {
  947. LoadObject( selectedObject ?? Selection.activeObject );
  948. }
  949. else
  950. {
  951. m_delayedLoadObject = selectedObject ?? Selection.activeObject;
  952. }
  953. if( !hasFocus )
  954. Focus();
  955. }
  956. public void LoadObject( UnityEngine.Object objToLoad )
  957. {
  958. Shader selectedShader = objToLoad as Shader;
  959. Material selectedMaterial = objToLoad as Material;
  960. AmplifyShaderFunction selectedFunction = objToLoad as AmplifyShaderFunction;
  961. if( selectedFunction != null )
  962. {
  963. IsShaderFunctionWindow = true;
  964. m_mainGraphInstance.CurrentCanvasMode = NodeAvailability.ShaderFunction;
  965. }
  966. else
  967. {
  968. IsShaderFunctionWindow = false;
  969. }
  970. ASESelectionMode selectedFileType = ASESelectionMode.Shader;
  971. if( selectedShader != null )
  972. {
  973. selectedFileType = ASESelectionMode.Shader;
  974. }
  975. else if( selectedMaterial != null )
  976. {
  977. selectedFileType = ASESelectionMode.Material;
  978. }
  979. else if( selectedFunction != null )
  980. {
  981. selectedFileType = ASESelectionMode.ShaderFunction;
  982. }
  983. switch( CurrentSelection )
  984. {
  985. case ASESelectionMode.Shader:
  986. {
  987. if( ShaderIsModified )
  988. {
  989. Shader currShader = m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  990. bool savePrevious = UIUtils.DisplayDialog( AssetDatabase.GetAssetPath( currShader ) );
  991. OnSaveShader( savePrevious, currShader, null, null );
  992. }
  993. }
  994. break;
  995. case ASESelectionMode.Material:
  996. {
  997. if( ShaderIsModified )
  998. {
  999. Shader currShader = m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  1000. bool savePrevious = UIUtils.DisplayDialog( AssetDatabase.GetAssetPath( currShader ) );
  1001. OnSaveShader( savePrevious, currShader, m_mainGraphInstance.CurrentMasterNode.CurrentMaterial, null );
  1002. }
  1003. }
  1004. break;
  1005. case ASESelectionMode.ShaderFunction:
  1006. {
  1007. if( ShaderIsModified )
  1008. {
  1009. bool savePrevious = UIUtils.DisplayDialog( AssetDatabase.GetAssetPath( m_openedShaderFunction ) );
  1010. OnSaveShader( savePrevious, null, null, selectedFunction );
  1011. }
  1012. }
  1013. break;
  1014. }
  1015. switch( selectedFileType )
  1016. {
  1017. case ASESelectionMode.Shader:
  1018. {
  1019. LoadDroppedObject( true, selectedShader, null );
  1020. }
  1021. break;
  1022. case ASESelectionMode.Material:
  1023. {
  1024. LoadDroppedObject( true, selectedMaterial.shader, selectedMaterial );
  1025. }
  1026. break;
  1027. case ASESelectionMode.ShaderFunction:
  1028. {
  1029. LoadDroppedObject( true, null, null, selectedFunction );
  1030. }
  1031. break;
  1032. }
  1033. m_openedShaderFunction = m_mainGraphInstance.CurrentShaderFunction;
  1034. //Need to force one graph draw because it wont call OnGui propertly since its focuses somewhere else
  1035. // Focus() doesn't fix this since it only changes keyboard focus
  1036. m_drawInfo.InvertedZoom = 1 / m_cameraZoom;
  1037. m_mainGraphInstance.Draw( m_drawInfo );
  1038. ShaderIsModified = false;
  1039. Focus();
  1040. Repaint();
  1041. }
  1042. public void OnProjectSelectionChanged()
  1043. {
  1044. if( m_loadShaderOnSelection )
  1045. {
  1046. LoadProjectSelected();
  1047. }
  1048. }
  1049. ShaderLoadResult OnSaveShader( bool value, Shader shader, Material material, AmplifyShaderFunction function )
  1050. {
  1051. if( value )
  1052. {
  1053. SaveToDisk( false );
  1054. }
  1055. return value ? ShaderLoadResult.LOADED : ShaderLoadResult.FILE_NOT_FOUND;
  1056. }
  1057. public void ResetCameraSettings()
  1058. {
  1059. m_cameraInfo = position;
  1060. m_cameraOffset = new Vector2( m_cameraInfo.width * 0.5f, m_cameraInfo.height * 0.5f );
  1061. CameraZoom = 1;
  1062. }
  1063. public void Reset()
  1064. {
  1065. if( m_mainGraphInstance == null )
  1066. {
  1067. m_mainGraphInstance = CreateInstance<ParentGraph>();
  1068. m_mainGraphInstance.Init();
  1069. m_mainGraphInstance.ParentWindow = this;
  1070. m_mainGraphInstance.SetGraphId( 0 );
  1071. }
  1072. m_mainGraphInstance.ResetEvents();
  1073. m_mainGraphInstance.OnNodeEvent += OnNodeStoppedMovingEvent;
  1074. m_mainGraphInstance.OnMaterialUpdatedEvent += OnMaterialUpdated;
  1075. m_mainGraphInstance.OnShaderUpdatedEvent += OnShaderUpdated;
  1076. m_mainGraphInstance.OnEmptyGraphDetectedEvt += OnEmptyGraphDetected;
  1077. m_mainGraphInstance.OnNodeRemovedEvent += m_toolsWindow.OnNodeRemovedFromGraph;
  1078. GraphCount = 1;
  1079. FullCleanUndoStack();
  1080. m_performFullUndoRegister = true;
  1081. m_toolsWindow.BorderStyle = null;
  1082. m_selectionMode = ASESelectionMode.Shader;
  1083. ResetCameraSettings();
  1084. UIUtils.ResetMainSkin();
  1085. m_duplicatePreventionBuffer.ReleaseAllData();
  1086. if( m_genericMessageUI != null )
  1087. m_genericMessageUI.CleanUpMessageStack();
  1088. }
  1089. public Shader CreateNewGraph( string name )
  1090. {
  1091. Reset();
  1092. UIUtils.DirtyMask = false;
  1093. m_mainGraphInstance.CreateNewEmpty( name );
  1094. m_lastOpenedLocation = string.Empty;
  1095. UIUtils.DirtyMask = true;
  1096. return m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  1097. }
  1098. public Shader CreateNewTemplateGraph( string templateGUID )
  1099. {
  1100. Reset();
  1101. UIUtils.DirtyMask = false;
  1102. m_mainGraphInstance.CreateNewEmptyTemplate( templateGUID );
  1103. m_lastOpenedLocation = string.Empty;
  1104. UIUtils.DirtyMask = true;
  1105. return m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  1106. }
  1107. public Shader CreateNewGraph( Shader shader )
  1108. {
  1109. Reset();
  1110. UIUtils.DirtyMask = false;
  1111. m_mainGraphInstance.CreateNewEmpty( shader.name );
  1112. m_mainGraphInstance.CurrentMasterNode.CurrentShader = shader;
  1113. m_lastOpenedLocation = string.Empty;
  1114. UIUtils.DirtyMask = true;
  1115. return m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  1116. }
  1117. public void CreateNewFunctionGraph( AmplifyShaderFunction shaderFunction )
  1118. {
  1119. Reset();
  1120. UIUtils.DirtyMask = false;
  1121. m_mainGraphInstance.CreateNewEmptyFunction( shaderFunction );
  1122. m_mainGraphInstance.CurrentShaderFunction = shaderFunction;
  1123. m_lastOpenedLocation = AssetDatabase.GetAssetPath( shaderFunction ); //string.Empty;
  1124. UIUtils.DirtyMask = true;
  1125. //return m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  1126. }
  1127. public bool SaveToDisk( bool checkTimestamp )
  1128. {
  1129. if( checkTimestamp )
  1130. {
  1131. if( !m_cacheSaveOp )
  1132. {
  1133. m_lastTimeSaved = EditorApplication.timeSinceStartup;
  1134. m_cacheSaveOp = true;
  1135. }
  1136. return false;
  1137. }
  1138. System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
  1139. m_customGraph = null;
  1140. m_cacheSaveOp = false;
  1141. ShaderIsModified = false;
  1142. m_mainGraphInstance.LoadedShaderVersion = VersionInfo.FullNumber;
  1143. m_lastTimeSaved = EditorApplication.timeSinceStartup;
  1144. if( m_mainGraphInstance.CurrentMasterNodeId == Constants.INVALID_NODE_ID )
  1145. {
  1146. Shader currentShader = m_mainGraphInstance.CurrentMasterNode != null ? m_mainGraphInstance.CurrentMasterNode.CurrentShader : null;
  1147. string newShader;
  1148. if( !String.IsNullOrEmpty( m_lastOpenedLocation ) )
  1149. {
  1150. newShader = m_lastOpenedLocation;
  1151. }
  1152. else if( currentShader != null )
  1153. {
  1154. newShader = AssetDatabase.GetAssetPath( currentShader );
  1155. }
  1156. else
  1157. {
  1158. newShader = EditorUtility.SaveFilePanel( "Select Shader to save", Application.dataPath, "MyShader", "shader" );
  1159. }
  1160. if( !String.IsNullOrEmpty( newShader ) )
  1161. {
  1162. ShowMessage( "No Master node assigned.\nShader file will only have node info" );
  1163. IOUtils.StartSaveThread( GenerateGraphInfo(), newShader );
  1164. AssetDatabase.Refresh();
  1165. LoadFromDisk( newShader );
  1166. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  1167. return true;
  1168. }
  1169. }
  1170. else if( m_mainGraphInstance.CurrentMasterNode != null )
  1171. {
  1172. //m_mainGraphInstance.CurrentStandardSurface.ForceReordering();
  1173. Shader currShader = m_mainGraphInstance.CurrentMasterNode.CurrentShader;
  1174. if( currShader != null )
  1175. {
  1176. m_mainGraphInstance.FireMasterNode( currShader );
  1177. Material material = m_mainGraphInstance.CurrentMaterial;
  1178. m_lastpath = ( material != null ) ? AssetDatabase.GetAssetPath( material ) : AssetDatabase.GetAssetPath( currShader );
  1179. EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, m_lastpath );
  1180. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  1181. return true;
  1182. }
  1183. else
  1184. {
  1185. string shaderName;
  1186. string pathName;
  1187. IOUtils.GetShaderName( out shaderName, out pathName, Constants.DefaultShaderName, UIUtils.LatestOpenedFolder );
  1188. if( !String.IsNullOrEmpty( pathName ) )
  1189. {
  1190. UIUtils.CurrentWindow.CurrentGraph.CurrentMasterNode.SetName( shaderName );
  1191. m_mainGraphInstance.FireMasterNode( pathName, true );
  1192. m_lastpath = pathName;
  1193. EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, pathName );
  1194. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  1195. return true;
  1196. }
  1197. }
  1198. }
  1199. else
  1200. {
  1201. //m_nodeParametersWindow.ForceReordering();
  1202. m_mainGraphInstance.ResetNodesLocalVariables();
  1203. List<FunctionInput> functionInputNodes = UIUtils.FunctionInputList();
  1204. functionInputNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  1205. for( int i = 0; i < functionInputNodes.Count; i++ )
  1206. {
  1207. functionInputNodes[ i ].OrderIndex = i;
  1208. }
  1209. List<FunctionOutput> functionOutputNodes = UIUtils.FunctionOutputList();
  1210. functionOutputNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } );
  1211. for( int i = 0; i < functionOutputNodes.Count; i++ )
  1212. {
  1213. functionOutputNodes[ i ].OrderIndex = i;
  1214. }
  1215. m_mainGraphInstance.CurrentShaderFunction.AdditionalDirectives.UpdateSaveItemsFromDirectives();
  1216. m_mainGraphInstance.CurrentShaderFunction.FunctionInfo = GenerateGraphInfo();
  1217. m_mainGraphInstance.CurrentShaderFunction.FunctionInfo = IOUtils.AddAdditionalInfo( m_mainGraphInstance.CurrentShaderFunction.FunctionInfo );
  1218. if( AssetDatabase.IsMainAsset( m_mainGraphInstance.CurrentShaderFunction ) )
  1219. {
  1220. EditorUtility.SetDirty( m_mainGraphInstance.CurrentShaderFunction );
  1221. }
  1222. else
  1223. {
  1224. //Debug.Log( LastOpenedLocation );
  1225. //AssetDatabase.CreateAsset( m_mainGraphInstance.CurrentShaderFunction, LastOpenedLocation );
  1226. }
  1227. AssetDatabase.SaveAssets();
  1228. AssetDatabase.Refresh();
  1229. IOUtils.FunctionNodeChanged = true;
  1230. m_lastpath = AssetDatabase.GetAssetPath( m_mainGraphInstance.CurrentShaderFunction );
  1231. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  1232. //EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, AssetDatabase.GetAssetPath( m_mainGraphInstance.CurrentShaderFunction ) );
  1233. return true;
  1234. }
  1235. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  1236. return false;
  1237. }
  1238. public void OnToolButtonPressed( ToolButtonType type )
  1239. {
  1240. switch( type )
  1241. {
  1242. case ToolButtonType.New:
  1243. {
  1244. UIUtils.CreateNewEmpty();
  1245. }
  1246. break;
  1247. case ToolButtonType.Open:
  1248. {
  1249. UIUtils.OpenFile();
  1250. }
  1251. break;
  1252. case ToolButtonType.Save:
  1253. {
  1254. SaveToDisk( false );
  1255. }
  1256. break;
  1257. case ToolButtonType.Library:
  1258. {
  1259. ShowShaderLibrary();
  1260. }
  1261. break;
  1262. case ToolButtonType.Options: { } break;
  1263. case ToolButtonType.Update:
  1264. {
  1265. SaveToDisk( false );
  1266. }
  1267. break;
  1268. case ToolButtonType.Live:
  1269. {
  1270. m_liveShaderEditing = !m_liveShaderEditing;
  1271. m_innerEditorVariables.LiveMode = m_liveShaderEditing;
  1272. // 0 off
  1273. // 1 on
  1274. // 2 pending
  1275. if( m_liveShaderEditing && m_mainGraphInstance.CurrentMasterNode.CurrentShader == null )
  1276. {
  1277. m_liveShaderEditing = false;
  1278. }
  1279. UpdateLiveUI();
  1280. if( m_liveShaderEditing )
  1281. {
  1282. SaveToDisk( false );
  1283. }
  1284. }
  1285. break;
  1286. case ToolButtonType.OpenSourceCode:
  1287. {
  1288. AssetDatabase.OpenAsset( m_mainGraphInstance.CurrentMasterNode.CurrentShader, 1 );
  1289. }
  1290. break;
  1291. case ToolButtonType.MasterNode:
  1292. {
  1293. m_mainGraphInstance.AssignMasterNode();
  1294. }
  1295. break;
  1296. case ToolButtonType.FocusOnMasterNode:
  1297. {
  1298. double currTime = EditorApplication.timeSinceStartup;
  1299. bool autoZoom = ( currTime - m_focusOnMasterNodeTimestamp ) < AutoZoomTime;
  1300. m_focusOnMasterNodeTimestamp = currTime;
  1301. FocusOnNode( m_mainGraphInstance.CurrentMasterNode, autoZoom ? 1 : m_cameraZoom, true );
  1302. }
  1303. break;
  1304. case ToolButtonType.FocusOnSelection:
  1305. {
  1306. List<ParentNode> selectedNodes = ( m_mainGraphInstance.SelectedNodes.Count > 0 ) ? m_mainGraphInstance.SelectedNodes : m_mainGraphInstance.AllNodes;
  1307. Vector2 minPos = new Vector2( float.MaxValue, float.MaxValue );
  1308. Vector2 maxPos = new Vector2( float.MinValue, float.MinValue );
  1309. Vector2 centroid = Vector2.zero;
  1310. for( int i = 0; i < selectedNodes.Count; i++ )
  1311. {
  1312. Rect currPos = selectedNodes[ i ].TruePosition;
  1313. minPos.x = ( currPos.x < minPos.x ) ? currPos.x : minPos.x;
  1314. minPos.y = ( currPos.y < minPos.y ) ? currPos.y : minPos.y;
  1315. maxPos.x = ( ( currPos.x + currPos.width ) > maxPos.x ) ? ( currPos.x + currPos.width ) : maxPos.x;
  1316. maxPos.y = ( ( currPos.y + currPos.height ) > maxPos.y ) ? ( currPos.y + currPos.height ) : maxPos.y;
  1317. }
  1318. centroid = ( maxPos - minPos );
  1319. double currTime = EditorApplication.timeSinceStartup;
  1320. bool autoZoom = ( currTime - m_focusOnSelectionTimestamp ) < AutoZoomTime;
  1321. m_focusOnSelectionTimestamp = currTime;
  1322. float zoom = m_cameraZoom;
  1323. if( autoZoom )
  1324. {
  1325. zoom = 1f;
  1326. float canvasWidth = m_cameraInfo.width;
  1327. if( m_nodeParametersWindow.IsMaximized )
  1328. canvasWidth -= m_nodeParametersWindow.RealWidth;
  1329. if( m_paletteWindow.IsMaximized )
  1330. canvasWidth -= m_paletteWindow.RealWidth;
  1331. canvasWidth -= 40;
  1332. //float canvasWidth = AvailableCanvasWidth;// - 20;
  1333. float canvasHeight = AvailableCanvasHeight - 60;
  1334. if( centroid.x > canvasWidth ||
  1335. centroid.y > canvasHeight )
  1336. {
  1337. float hZoom = float.MinValue;
  1338. float vZoom = float.MinValue;
  1339. if( centroid.x > canvasWidth )
  1340. {
  1341. hZoom = ( centroid.x ) / canvasWidth;
  1342. }
  1343. if( centroid.y > canvasHeight )
  1344. {
  1345. vZoom = ( centroid.y ) / canvasHeight;
  1346. }
  1347. zoom = ( hZoom > vZoom ) ? hZoom : vZoom;
  1348. }
  1349. }
  1350. minPos.y -= 20 * zoom;
  1351. if( m_nodeParametersWindow.IsMaximized )
  1352. minPos.x -= m_nodeParametersWindow.RealWidth * 0.5f * zoom;
  1353. if( m_paletteWindow.IsMaximized )
  1354. minPos.x += m_paletteWindow.RealWidth * 0.5f * zoom;
  1355. FocusOnPoint( minPos + centroid * 0.5f, zoom );
  1356. }
  1357. break;
  1358. case ToolButtonType.ShowInfoWindow:
  1359. {
  1360. PortLegendInfo.OpenWindow();
  1361. }
  1362. break;
  1363. case ToolButtonType.ShowTipsWindow:
  1364. {
  1365. TipsWindow.ShowWindow( true );
  1366. }
  1367. break;
  1368. case ToolButtonType.ShowConsole:
  1369. {
  1370. m_consoleLogWindow.Toggle();
  1371. }
  1372. break;
  1373. case ToolButtonType.CleanUnusedNodes:
  1374. {
  1375. m_mainGraphInstance.CleanUnusedNodes();
  1376. }
  1377. break;
  1378. case ToolButtonType.Help:
  1379. {
  1380. Application.OpenURL( Constants.HelpURL );
  1381. }
  1382. break;
  1383. }
  1384. }
  1385. void UpdateLiveUI()
  1386. {
  1387. if( m_toolsWindow != null )
  1388. {
  1389. m_toolsWindow.SetStateOnButton( ToolButtonType.Live, ( m_liveShaderEditing ) ? 1 : 0 );
  1390. }
  1391. }
  1392. public void FocusOnNode( ParentNode node, float zoom, bool selectNode, bool late = false )
  1393. {
  1394. if( late )
  1395. {
  1396. m_nodeToFocus = node;
  1397. m_zoomToFocus = zoom;
  1398. m_selectNodeToFocus = selectNode;
  1399. return;
  1400. }
  1401. if( selectNode )
  1402. {
  1403. m_mainGraphInstance.SelectNode( node, false, false );
  1404. }
  1405. FocusOnPoint( node.CenterPosition, zoom );
  1406. }
  1407. public void FocusOnPoint( Vector2 point, float zoom, bool smooth = true )
  1408. {
  1409. if( zoom > 0.999f )
  1410. {
  1411. //CameraZoom = zoom;
  1412. if( smooth )
  1413. SmoothZoom( zoom );
  1414. else
  1415. CameraZoom = zoom;
  1416. }
  1417. if( smooth )
  1418. SmoothCameraOffset( -point + new Vector2( ( m_cameraInfo.width ) * 0.5f, m_cameraInfo.height * 0.5f ) * CameraZoom );
  1419. else
  1420. //m_cameraOffset = -point + new Vector2( ( m_cameraInfo.width ) * 0.5f, m_cameraInfo.height * 0.5f ) * CameraZoom;
  1421. m_cameraOffset = -point + new Vector2( ( m_cameraInfo.width + m_nodeParametersWindow.RealWidth - m_paletteWindow.RealWidth ) * 0.5f, m_cameraInfo.height * 0.5f ) * CameraZoom;
  1422. }
  1423. void SmoothZoom( float newZoom )
  1424. {
  1425. m_smoothZoom = true;
  1426. m_zoomTime = 0;
  1427. m_targetZoom = newZoom;
  1428. m_zoomPivot = m_graphArea.center;
  1429. }
  1430. void SmoothCameraOffset( Vector2 newOffset )
  1431. {
  1432. m_smoothOffset = true;
  1433. m_offsetTime = 0;
  1434. m_targetOffset = newOffset;
  1435. }
  1436. void PreTestLeftMouseDown()
  1437. {
  1438. if( m_currentEvent.type == EventType.MouseDown && m_currentEvent.button == ButtonClickId.LeftMouseButton )
  1439. {
  1440. ParentNode node = m_mainGraphInstance.CheckNodeAt( m_currentMousePos );
  1441. if( node != null )
  1442. {
  1443. m_mainGraphInstance.NodeClicked = node.UniqueId;
  1444. return;
  1445. }
  1446. }
  1447. m_mainGraphInstance.NodeClicked = -1;
  1448. }
  1449. void OnLeftMouseDown()
  1450. {
  1451. Focus();
  1452. m_mouseDownOnValidArea = true;
  1453. m_lmbPressed = true;
  1454. if( m_currentEvent.alt )
  1455. {
  1456. m_altBoxSelection = true;
  1457. }
  1458. UIUtils.ShowContextOnPick = true;
  1459. ParentNode node = ( m_mainGraphInstance.NodeClicked < 0 ) ? m_mainGraphInstance.CheckNodeAt( m_currentMousePos ) : m_mainGraphInstance.GetClickedNode();
  1460. if( node != null )
  1461. {
  1462. m_mainGraphInstance.NodeClicked = node.UniqueId;
  1463. m_altBoxSelection = false;
  1464. if( m_contextMenu.CheckShortcutKey() )
  1465. {
  1466. if( node.ConnStatus == NodeConnectionStatus.Island )
  1467. {
  1468. if( !m_multipleSelectionActive )
  1469. {
  1470. ParentNode newNode = m_contextMenu.CreateNodeFromShortcutKey();
  1471. if( newNode != null )
  1472. {
  1473. newNode.ContainerGraph = m_mainGraphInstance;
  1474. newNode.Vec2Position = TranformedMousePos;
  1475. m_mainGraphInstance.AddNode( newNode, true );
  1476. m_mainGraphInstance.SelectNode( newNode, false, false );
  1477. ForceRepaint();
  1478. }
  1479. ( node as CommentaryNode ).AddNodeToCommentary( newNode );
  1480. }
  1481. }
  1482. }
  1483. else
  1484. {
  1485. if( node.OnClick( m_currentMousePos2D ) )
  1486. {
  1487. if( !node.Selected )
  1488. {
  1489. m_mainGraphInstance.SelectNode( node, ( m_currentEvent.modifiers == EventModifiers.Shift || m_currentEvent.modifiers == EventModifiers.Control ), true );
  1490. }
  1491. else if( m_currentEvent.modifiers == EventModifiers.Shift || m_currentEvent.modifiers == EventModifiers.Control )
  1492. {
  1493. m_mainGraphInstance.DeselectNode( node );
  1494. }
  1495. if( m_currentEvent.alt )
  1496. {
  1497. int conn = 0;
  1498. for( int i = 0; i < node.InputPorts.Count; i++ )
  1499. {
  1500. if( node.InputPorts[ i ].IsConnected )
  1501. conn++;
  1502. }
  1503. if( node.InputPorts.Count > 0 && node.OutputPorts.Count > 0 && conn > 0 && node.OutputPorts[ 0 ].IsConnected )
  1504. {
  1505. m_altDragStarted = true;
  1506. }
  1507. }
  1508. }
  1509. if( m_currentEvent.alt )
  1510. {
  1511. if( node.InputPorts.Count > 0 && node.OutputPorts.Count > 0 && node.InputPorts[ 0 ].IsConnected && node.OutputPorts[ 0 ].IsConnected )
  1512. {
  1513. m_altDragStarted = true;
  1514. }
  1515. }
  1516. return;
  1517. }
  1518. }
  1519. else if( !m_multipleSelectionActive )
  1520. {
  1521. ParentNode newNode = m_contextMenu.CreateNodeFromShortcutKey();
  1522. if( newNode != null )
  1523. {
  1524. newNode.ContainerGraph = m_mainGraphInstance;
  1525. newNode.Vec2Position = TranformedMousePos;
  1526. m_mainGraphInstance.AddNode( newNode, true );
  1527. m_mainGraphInstance.SelectNode( newNode, false, false );
  1528. SetSaveIsDirty();
  1529. ForceRepaint();
  1530. }
  1531. else
  1532. {
  1533. List<WireBezierReference> wireRefs = m_mainGraphInstance.GetWireBezierListInPos( m_currentMousePos2D );
  1534. if( wireRefs != null && wireRefs.Count > 0 )
  1535. {
  1536. for( int i = 0; i < wireRefs.Count; i++ )
  1537. {
  1538. // Place wire code here
  1539. ParentNode outNode = m_mainGraphInstance.GetNode( wireRefs[ i ].OutNodeId );
  1540. ParentNode inNode = m_mainGraphInstance.GetNode( wireRefs[ i ].InNodeId );
  1541. OutputPort outputPort = outNode.GetOutputPortByUniqueId( wireRefs[ i ].OutPortId );
  1542. InputPort inputPort = inNode.GetInputPortByUniqueId( wireRefs[ i ].InPortId );
  1543. // Calculate the 4 points for bezier taking into account wire nodes and their automatic tangents
  1544. Vector3 endPos = new Vector3( inputPort.Position.x, inputPort.Position.y );
  1545. Vector3 startPos = new Vector3( outputPort.Position.x, outputPort.Position.y );
  1546. float mag = ( endPos - startPos ).magnitude;
  1547. float resizedMag = Mathf.Min( mag, Constants.HORIZONTAL_TANGENT_SIZE * m_drawInfo.InvertedZoom );
  1548. Vector3 startTangent = new Vector3( startPos.x + resizedMag, startPos.y );
  1549. Vector3 endTangent = new Vector3( endPos.x - resizedMag, endPos.y );
  1550. if( inNode != null && inNode.GetType() == typeof( WireNode ) )
  1551. endTangent = endPos + ( ( inNode as WireNode ).TangentDirection ) * mag * 0.33f;
  1552. if( outNode != null && outNode.GetType() == typeof( WireNode ) )
  1553. startTangent = startPos - ( ( outNode as WireNode ).TangentDirection ) * mag * 0.33f;
  1554. float dist = HandleUtility.DistancePointBezier( m_currentMousePos, startPos, endPos, startTangent, endTangent );
  1555. if( dist < 10 )
  1556. {
  1557. double doubleTapTime = EditorApplication.timeSinceStartup;
  1558. bool doubleTap = ( doubleTapTime - m_wiredDoubleTapTimestamp ) < WiredDoubleTapTime;
  1559. m_wiredDoubleTapTimestamp = doubleTapTime;
  1560. if( doubleTap )
  1561. {
  1562. Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId );
  1563. Undo.RegisterCompleteObjectUndo( m_mainGraphInstance, Constants.UndoCreateConnectionId );
  1564. Undo.RecordObject( outNode, Constants.UndoCreateConnectionId );
  1565. Undo.RecordObject( inNode, Constants.UndoCreateConnectionId );
  1566. ParentNode wireNode = m_mainGraphInstance.CreateNode( typeof( WireNode ), true );
  1567. if( wireNode != null )
  1568. {
  1569. wireNode.Vec2Position = TranformedMousePos;
  1570. m_mainGraphInstance.CreateConnection( wireNode.InputPorts[ 0 ].NodeId, wireNode.InputPorts[ 0 ].PortId, outputPort.NodeId, outputPort.PortId );
  1571. m_mainGraphInstance.CreateConnection( inputPort.NodeId, inputPort.PortId, wireNode.OutputPorts[ 0 ].NodeId, wireNode.OutputPorts[ 0 ].PortId );
  1572. SetSaveIsDirty();
  1573. ForceRepaint();
  1574. Undo.IncrementCurrentGroup();
  1575. }
  1576. }
  1577. break;
  1578. }
  1579. }
  1580. }
  1581. //Reset focus from any textfield which may be selected at this time
  1582. GUIUtility.keyboardControl = 0;
  1583. }
  1584. }
  1585. if( m_currentEvent.modifiers != EventModifiers.Shift && m_currentEvent.modifiers != EventModifiers.Control && !m_altBoxSelection )
  1586. m_mainGraphInstance.DeSelectAll();
  1587. if( m_wireReferenceUtils.ValidReferences() )
  1588. {
  1589. m_wireReferenceUtils.InvalidateReferences();
  1590. return;
  1591. }
  1592. if( !m_contextMenu.CheckShortcutKey() && m_currentEvent.modifiers != EventModifiers.Shift && m_currentEvent.modifiers != EventModifiers.Control || m_altBoxSelection )
  1593. {
  1594. // Only activate multiple selection if no node is selected and shift key not pressed
  1595. m_multipleSelectionActive = true;
  1596. m_multipleSelectionStart = TranformedMousePos;
  1597. m_multipleSelectionArea.position = m_multipleSelectionStart;
  1598. m_multipleSelectionArea.size = Vector2.zero;
  1599. }
  1600. UseCurrentEvent();
  1601. }
  1602. void OnLeftMouseDrag()
  1603. {
  1604. if( m_lostFocus )
  1605. {
  1606. m_lostFocus = false;
  1607. return;
  1608. }
  1609. if( m_altDragStarted )
  1610. {
  1611. m_altDragStarted = false;
  1612. if( m_currentEvent.modifiers == EventModifiers.Alt && CurrentGraph.SelectedNodes.Count == 1 )
  1613. {
  1614. ParentNode node = CurrentGraph.SelectedNodes[ 0 ];
  1615. int lastId = 0;
  1616. int conn = 0;
  1617. for( int i = 0; i < node.InputPorts.Count; i++ )
  1618. {
  1619. if( node.InputPorts[ i ].IsConnected )
  1620. {
  1621. conn++;
  1622. lastId = i;
  1623. }
  1624. }
  1625. if( conn > 1 )
  1626. lastId = 0;
  1627. OutputPort outputPort = node.InputPorts[ lastId ].GetOutputConnection( 0 );
  1628. ParentNode outputNode = m_mainGraphInstance.GetNode( outputPort.NodeId );
  1629. Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId );
  1630. node.RecordObject( Constants.UndoCreateConnectionId );
  1631. outputNode.RecordObject( Constants.UndoCreateConnectionId );
  1632. List<InputPort> inputPorts = new List<InputPort>();
  1633. for( int i = 0; i < node.OutputPorts[ 0 ].ConnectionCount; i++ )
  1634. {
  1635. InputPort inputPort = node.OutputPorts[ 0 ].GetInputConnection( i );
  1636. ParentNode inputNode = m_mainGraphInstance.GetNode( inputPort.NodeId );
  1637. inputNode.RecordObject( Constants.UndoCreateConnectionId );
  1638. inputPorts.Add( inputPort );
  1639. }
  1640. for( int i = 0; i < inputPorts.Count; i++ )
  1641. {
  1642. m_mainGraphInstance.CreateConnection( inputPorts[ i ].NodeId, inputPorts[ i ].PortId, outputPort.NodeId, outputPort.PortId );
  1643. }
  1644. UIUtils.DeleteConnection( true, node.UniqueId, node.InputPorts[ lastId ].PortId, false, true );
  1645. SetSaveIsDirty();
  1646. ForceRepaint();
  1647. }
  1648. }
  1649. if( !m_wireReferenceUtils.ValidReferences() && !m_altBoxSelection)
  1650. {
  1651. if( m_mouseDownOnValidArea && m_insideEditorWindow )
  1652. {
  1653. if( m_currentEvent.control )
  1654. {
  1655. m_mainGraphInstance.MoveSelectedNodes( m_cameraZoom * m_currentEvent.delta, true );
  1656. }
  1657. else
  1658. {
  1659. m_mainGraphInstance.MoveSelectedNodes( m_cameraZoom * m_currentEvent.delta );
  1660. }
  1661. //m_mainGraphInstance.MoveSelectedNodes( m_cameraZoom * m_currentEvent.delta );
  1662. m_autoPanDirActive = true;
  1663. }
  1664. }
  1665. else
  1666. {
  1667. List<ParentNode> nodes = m_mainGraphInstance.GetNodesInGrid( m_drawInfo.TransformedMousePos );
  1668. if( nodes != null && nodes.Count > 0 )
  1669. {
  1670. Vector2 currentPortPos = new Vector2();
  1671. Vector2 mousePos = TranformedMousePos;
  1672. if( m_wireReferenceUtils.InputPortReference.IsValid )
  1673. {
  1674. OutputPort currentPort = null;
  1675. float smallestDistance = float.MaxValue;
  1676. Vector2 smallestPosition = Vector2.zero;
  1677. for( int nodeIdx = 0; nodeIdx < nodes.Count; nodeIdx++ )
  1678. {
  1679. List<OutputPort> outputPorts = nodes[ nodeIdx ].OutputPorts;
  1680. if( outputPorts != null )
  1681. {
  1682. for( int o = 0; o < outputPorts.Count; o++ )
  1683. {
  1684. if( outputPorts[ o ].Available )
  1685. {
  1686. currentPortPos.x = outputPorts[ o ].Position.x;
  1687. currentPortPos.y = outputPorts[ o ].Position.y;
  1688. currentPortPos = currentPortPos * m_cameraZoom - m_cameraOffset;
  1689. float dist = ( mousePos - currentPortPos ).sqrMagnitude;
  1690. if( dist < smallestDistance )
  1691. {
  1692. smallestDistance = dist;
  1693. smallestPosition = currentPortPos;
  1694. currentPort = outputPorts[ o ];
  1695. }
  1696. }
  1697. }
  1698. }
  1699. }
  1700. if( currentPort != null && currentPort.Available && ( smallestDistance < Constants.SNAP_SQR_DIST || currentPort.InsideActiveArea( ( mousePos + m_cameraOffset ) / m_cameraZoom ) ) )
  1701. {
  1702. m_wireReferenceUtils.ActivateSnap( smallestPosition, currentPort );
  1703. }
  1704. else
  1705. {
  1706. m_wireReferenceUtils.DeactivateSnap();
  1707. }
  1708. }
  1709. if( m_wireReferenceUtils.OutputPortReference.IsValid )
  1710. {
  1711. InputPort currentPort = null;
  1712. float smallestDistance = float.MaxValue;
  1713. Vector2 smallestPosition = Vector2.zero;
  1714. for( int nodeIdx = 0; nodeIdx < nodes.Count; nodeIdx++ )
  1715. {
  1716. List<InputPort> inputPorts = nodes[ nodeIdx ].InputPorts;
  1717. if( inputPorts != null )
  1718. {
  1719. for( int i = 0; i < inputPorts.Count; i++ )
  1720. {
  1721. if( inputPorts[ i ].Available )
  1722. {
  1723. currentPortPos.x = inputPorts[ i ].Position.x;
  1724. currentPortPos.y = inputPorts[ i ].Position.y;
  1725. currentPortPos = currentPortPos * m_cameraZoom - m_cameraOffset;
  1726. float dist = ( mousePos - currentPortPos ).sqrMagnitude;
  1727. if( dist < smallestDistance )
  1728. {
  1729. smallestDistance = dist;
  1730. smallestPosition = currentPortPos;
  1731. currentPort = inputPorts[ i ];
  1732. }
  1733. }
  1734. }
  1735. }
  1736. }
  1737. if( currentPort != null && currentPort.Available && ( smallestDistance < Constants.SNAP_SQR_DIST || currentPort.InsideActiveArea( ( mousePos + m_cameraOffset ) / m_cameraZoom ) ) )
  1738. {
  1739. m_wireReferenceUtils.ActivateSnap( smallestPosition, currentPort );
  1740. }
  1741. else
  1742. {
  1743. m_wireReferenceUtils.DeactivateSnap();
  1744. }
  1745. }
  1746. }
  1747. else if( m_wireReferenceUtils.SnapEnabled )
  1748. {
  1749. m_wireReferenceUtils.DeactivateSnap();
  1750. }
  1751. }
  1752. UseCurrentEvent();
  1753. }
  1754. public void OnLeftMouseUp()
  1755. {
  1756. m_lmbPressed = false;
  1757. if( m_multipleSelectionActive )
  1758. {
  1759. //m_multipleSelectionActive = false;
  1760. UpdateSelectionArea();
  1761. //m_mainGraphInstance.MultipleSelection( m_multipleSelectionArea, ( m_currentEvent.modifiers == EventModifiers.Shift || m_currentEvent.modifiers == EventModifiers.Control ), true );
  1762. if( m_currentEvent.alt && m_altBoxSelection )
  1763. {
  1764. m_mainGraphInstance.MultipleSelection( m_multipleSelectionArea, !m_currentEvent.shift );
  1765. }
  1766. else
  1767. {
  1768. m_mainGraphInstance.DeSelectAll();
  1769. m_mainGraphInstance.MultipleSelection( m_multipleSelectionArea );
  1770. }
  1771. }
  1772. if( m_wireReferenceUtils.ValidReferences() )
  1773. {
  1774. //Check if there is some kind of port beneath the mouse ... if so connect to it
  1775. ParentNode targetNode = m_wireReferenceUtils.SnapEnabled ? m_mainGraphInstance.GetNode( m_wireReferenceUtils.SnapPort.NodeId ) : m_mainGraphInstance.CheckNodeAt( m_currentMousePos );
  1776. if( targetNode != null && targetNode.ConnStatus != NodeConnectionStatus.Island )
  1777. {
  1778. if( m_wireReferenceUtils.InputPortReference.IsValid && m_wireReferenceUtils.InputPortReference.NodeId != targetNode.UniqueId )
  1779. {
  1780. OutputPort outputPort = m_wireReferenceUtils.SnapEnabled ? targetNode.GetOutputPortByUniqueId( m_wireReferenceUtils.SnapPort.PortId ) : targetNode.CheckOutputPortAt( m_currentMousePos );
  1781. if( outputPort != null && !outputPort.Locked && ( !m_wireReferenceUtils.InputPortReference.TypeLocked ||
  1782. m_wireReferenceUtils.InputPortReference.DataType == WirePortDataType.OBJECT ||
  1783. ( m_wireReferenceUtils.InputPortReference.TypeLocked && outputPort.DataType == m_wireReferenceUtils.InputPortReference.DataType ) ) )
  1784. {
  1785. ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.InputPortReference.NodeId );
  1786. InputPort inputPort = originNode.GetInputPortByUniqueId( m_wireReferenceUtils.InputPortReference.PortId );
  1787. UIUtils.MarkUndoAction();
  1788. Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId );
  1789. originNode.RecordObject( Constants.UndoCreateConnectionId );
  1790. targetNode.RecordObject( Constants.UndoCreateConnectionId );
  1791. if( !inputPort.CheckValidType( outputPort.DataType ) )
  1792. {
  1793. UIUtils.ShowIncompatiblePortMessage( true, originNode, inputPort, targetNode, outputPort );
  1794. m_wireReferenceUtils.InvalidateReferences();
  1795. UseCurrentEvent();
  1796. return;
  1797. }
  1798. if( !outputPort.CheckValidType( inputPort.DataType ) )
  1799. {
  1800. UIUtils.ShowIncompatiblePortMessage( false, targetNode, outputPort, originNode, inputPort );
  1801. m_wireReferenceUtils.InvalidateReferences();
  1802. UseCurrentEvent();
  1803. return;
  1804. }
  1805. inputPort.DummyAdd( outputPort.NodeId, outputPort.PortId );
  1806. outputPort.DummyAdd( m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId );
  1807. if( UIUtils.DetectNodeLoopsFrom( originNode, new Dictionary<int, int>() ) )
  1808. {
  1809. inputPort.DummyRemove();
  1810. outputPort.DummyRemove();
  1811. m_wireReferenceUtils.InvalidateReferences();
  1812. ShowMessage( "Infinite Loop detected" );
  1813. UseCurrentEvent();
  1814. return;
  1815. }
  1816. inputPort.DummyRemove();
  1817. outputPort.DummyRemove();
  1818. if( inputPort.IsConnected )
  1819. {
  1820. DeleteConnection( true, m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId, true, false );
  1821. }
  1822. //link output to input
  1823. if( outputPort.ConnectTo( m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId, m_wireReferenceUtils.InputPortReference.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) )
  1824. targetNode.OnOutputPortConnected( outputPort.PortId, m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId );
  1825. //link input to output
  1826. if( inputPort.ConnectTo( outputPort.NodeId, outputPort.PortId, outputPort.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) )
  1827. originNode.OnInputPortConnected( m_wireReferenceUtils.InputPortReference.PortId, targetNode.UniqueId, outputPort.PortId );
  1828. m_mainGraphInstance.MarkWireHighlights();
  1829. }
  1830. else if( outputPort != null && m_wireReferenceUtils.InputPortReference.TypeLocked && m_wireReferenceUtils.InputPortReference.DataType != outputPort.DataType )
  1831. {
  1832. ShowMessage( "Attempting to connect a port locked to type " + m_wireReferenceUtils.InputPortReference.DataType + " into a port of type " + outputPort.DataType );
  1833. }
  1834. ShaderIsModified = true;
  1835. SetSaveIsDirty();
  1836. }
  1837. if( m_wireReferenceUtils.OutputPortReference.IsValid && m_wireReferenceUtils.OutputPortReference.NodeId != targetNode.UniqueId )
  1838. {
  1839. InputPort inputPort = m_wireReferenceUtils.SnapEnabled ? targetNode.GetInputPortByUniqueId( m_wireReferenceUtils.SnapPort.PortId ) : targetNode.CheckInputPortAt( m_currentMousePos );
  1840. if( inputPort != null && !inputPort.Locked && ( !inputPort.TypeLocked ||
  1841. inputPort.DataType == WirePortDataType.OBJECT ||
  1842. ( inputPort.TypeLocked && inputPort.DataType == m_wireReferenceUtils.OutputPortReference.DataType ) ) )
  1843. {
  1844. ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.OutputPortReference.NodeId );
  1845. OutputPort outputPort = originNode.GetOutputPortByUniqueId( m_wireReferenceUtils.OutputPortReference.PortId );
  1846. UIUtils.MarkUndoAction();
  1847. Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId );
  1848. originNode.RecordObject( Constants.UndoCreateConnectionId );
  1849. targetNode.RecordObject( Constants.UndoCreateConnectionId );
  1850. if( !inputPort.CheckValidType( outputPort.DataType ) )
  1851. {
  1852. UIUtils.ShowIncompatiblePortMessage( true, targetNode, inputPort, originNode, outputPort );
  1853. m_wireReferenceUtils.InvalidateReferences();
  1854. UseCurrentEvent();
  1855. return;
  1856. }
  1857. if( !outputPort.CheckValidType( inputPort.DataType ) )
  1858. {
  1859. UIUtils.ShowIncompatiblePortMessage( false, originNode, outputPort, targetNode, inputPort );
  1860. m_wireReferenceUtils.InvalidateReferences();
  1861. UseCurrentEvent();
  1862. return;
  1863. }
  1864. inputPort.DummyAdd( m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId );
  1865. outputPort.DummyAdd( inputPort.NodeId, inputPort.PortId );
  1866. if( UIUtils.DetectNodeLoopsFrom( targetNode, new Dictionary<int, int>() ) )
  1867. {
  1868. inputPort.DummyRemove();
  1869. outputPort.DummyRemove();
  1870. m_wireReferenceUtils.InvalidateReferences();
  1871. ShowMessage( "Infinite Loop detected" );
  1872. UseCurrentEvent();
  1873. return;
  1874. }
  1875. inputPort.DummyRemove();
  1876. outputPort.DummyRemove();
  1877. if( inputPort.IsConnected )
  1878. {
  1879. if( m_currentEvent.control && m_wireReferenceUtils.SwitchPortReference.IsValid )
  1880. {
  1881. ParentNode oldOutputNode = UIUtils.GetNode( inputPort.GetConnection( 0 ).NodeId );
  1882. OutputPort oldOutputPort = oldOutputNode.GetOutputPortByUniqueId( inputPort.GetConnection( 0 ).PortId );
  1883. ParentNode switchNode = UIUtils.GetNode( m_wireReferenceUtils.SwitchPortReference.NodeId );
  1884. InputPort switchPort = switchNode.GetInputPortByUniqueId( m_wireReferenceUtils.SwitchPortReference.PortId );
  1885. switchPort.DummyAdd( oldOutputPort.NodeId, oldOutputPort.PortId );
  1886. oldOutputPort.DummyAdd( switchPort.NodeId, switchPort.PortId );
  1887. if( UIUtils.DetectNodeLoopsFrom( switchNode, new Dictionary<int, int>() ) )
  1888. {
  1889. switchPort.DummyRemove();
  1890. oldOutputPort.DummyRemove();
  1891. m_wireReferenceUtils.InvalidateReferences();
  1892. ShowMessage( "Infinite Loop detected" );
  1893. UseCurrentEvent();
  1894. return;
  1895. }
  1896. switchPort.DummyRemove();
  1897. oldOutputPort.DummyRemove();
  1898. DeleteConnection( true, inputPort.NodeId, inputPort.PortId, true, false );
  1899. ConnectInputToOutput( switchPort.NodeId, switchPort.PortId, oldOutputPort.NodeId, oldOutputPort.PortId );
  1900. }
  1901. else
  1902. {
  1903. DeleteConnection( true, inputPort.NodeId, inputPort.PortId, true, false );
  1904. }
  1905. }
  1906. inputPort.InvalidateAllConnections();
  1907. //link input to output
  1908. if( inputPort.ConnectTo( m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId, m_wireReferenceUtils.OutputPortReference.DataType, inputPort.TypeLocked ) )
  1909. targetNode.OnInputPortConnected( inputPort.PortId, m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId );
  1910. //link output to input
  1911. if( outputPort.ConnectTo( inputPort.NodeId, inputPort.PortId, inputPort.DataType, inputPort.TypeLocked ) )
  1912. originNode.OnOutputPortConnected( m_wireReferenceUtils.OutputPortReference.PortId, targetNode.UniqueId, inputPort.PortId );
  1913. m_mainGraphInstance.MarkWireHighlights();
  1914. }
  1915. else if( inputPort != null && inputPort.TypeLocked && inputPort.DataType != m_wireReferenceUtils.OutputPortReference.DataType )
  1916. {
  1917. ShowMessage( "Attempting to connect a " + m_wireReferenceUtils.OutputPortReference.DataType + " to a port locked to type " + inputPort.DataType );
  1918. }
  1919. ShaderIsModified = true;
  1920. SetSaveIsDirty();
  1921. }
  1922. m_wireReferenceUtils.InvalidateReferences();
  1923. }
  1924. else
  1925. {
  1926. if( UIUtils.ShowContextOnPick )
  1927. m_contextPalette.Show( m_currentMousePos2D, m_cameraInfo );
  1928. else
  1929. m_wireReferenceUtils.InvalidateReferences();
  1930. }
  1931. }
  1932. else if( m_currentEvent.modifiers == EventModifiers.Alt && m_altAvailable && CurrentGraph.SelectedNodes.Count == 1 && !m_altBoxSelection && !m_multipleSelectionActive )
  1933. {
  1934. List<WireBezierReference> wireRefs = m_mainGraphInstance.GetWireBezierListInPos( m_currentMousePos2D );
  1935. if( wireRefs != null && wireRefs.Count > 0 )
  1936. {
  1937. float closestDist = 50;
  1938. int closestId = 0;
  1939. for( int i = 0; i < wireRefs.Count; i++ )
  1940. {
  1941. ParentNode outNode = m_mainGraphInstance.GetNode( wireRefs[ i ].OutNodeId );
  1942. ParentNode inNode = m_mainGraphInstance.GetNode( wireRefs[ i ].InNodeId );
  1943. if( outNode == CurrentGraph.SelectedNodes[ 0 ] || inNode == CurrentGraph.SelectedNodes[ 0 ] )
  1944. continue;
  1945. OutputPort outputPort = outNode.GetOutputPortByUniqueId( wireRefs[ i ].OutPortId );
  1946. InputPort inputPort = inNode.GetInputPortByUniqueId( wireRefs[ i ].InPortId );
  1947. // Calculate the 4 points for bezier taking into account wire nodes and their automatic tangents
  1948. Vector3 endPos = new Vector3( inputPort.Position.x, inputPort.Position.y );
  1949. Vector3 startPos = new Vector3( outputPort.Position.x, outputPort.Position.y );
  1950. float mag = ( endPos - startPos ).magnitude;
  1951. float resizedMag = Mathf.Min( mag, Constants.HORIZONTAL_TANGENT_SIZE * m_drawInfo.InvertedZoom );
  1952. Vector3 startTangent = new Vector3( startPos.x + resizedMag, startPos.y );
  1953. Vector3 endTangent = new Vector3( endPos.x - resizedMag, endPos.y );
  1954. if( inNode != null && inNode.GetType() == typeof( WireNode ) )
  1955. endTangent = endPos + ( ( inNode as WireNode ).TangentDirection ) * mag * 0.33f;
  1956. if( outNode != null && outNode.GetType() == typeof( WireNode ) )
  1957. startTangent = startPos - ( ( outNode as WireNode ).TangentDirection ) * mag * 0.33f;
  1958. //Vector2 pos = ( CurrentGraph.SelectedNodes[0].CenterPosition + m_cameraOffset ) / m_cameraZoom;
  1959. float dist = HandleUtility.DistancePointBezier( /*pos*/ m_currentMousePos, startPos, endPos, startTangent, endTangent );
  1960. if( dist < 40 )
  1961. {
  1962. if( dist < closestDist )
  1963. {
  1964. closestDist = dist;
  1965. closestId = i;
  1966. }
  1967. }
  1968. }
  1969. if( closestDist < 40 )
  1970. {
  1971. ParentNode outNode = m_mainGraphInstance.GetNode( wireRefs[ closestId ].OutNodeId );
  1972. ParentNode inNode = m_mainGraphInstance.GetNode( wireRefs[ closestId ].InNodeId );
  1973. OutputPort outputPort = outNode.GetOutputPortByUniqueId( wireRefs[ closestId ].OutPortId );
  1974. InputPort inputPort = inNode.GetInputPortByUniqueId( wireRefs[ closestId ].InPortId );
  1975. ParentNode selectedNode = CurrentGraph.SelectedNodes[ 0 ];
  1976. if( selectedNode.InputPorts.Count > 0 && selectedNode.OutputPorts.Count > 0 )
  1977. {
  1978. Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId );
  1979. selectedNode.RecordObject( Constants.UndoCreateConnectionId );
  1980. inNode.RecordObject( Constants.UndoCreateConnectionId );
  1981. outNode.RecordObject( Constants.UndoCreateConnectionId );
  1982. m_mainGraphInstance.CreateConnection( selectedNode.UniqueId, selectedNode.InputPorts[ 0 ].PortId, outputPort.NodeId, outputPort.PortId );
  1983. m_mainGraphInstance.CreateConnection( inputPort.NodeId, inputPort.PortId, selectedNode.UniqueId, selectedNode.OutputPorts[ 0 ].PortId );
  1984. }
  1985. SetSaveIsDirty();
  1986. ForceRepaint();
  1987. }
  1988. }
  1989. }
  1990. UIUtils.ShowContextOnPick = true;
  1991. m_altBoxSelection = false;
  1992. m_multipleSelectionActive = false;
  1993. UseCurrentEvent();
  1994. }
  1995. public void ConnectInputToOutput( int inNodeId, int inPortId, int outNodeId, int outPortId, bool registerUndo = true )
  1996. {
  1997. ParentNode inNode = m_mainGraphInstance.GetNode( inNodeId );
  1998. ParentNode outNode = m_mainGraphInstance.GetNode( outNodeId );
  1999. if( inNode != null && outNode != null )
  2000. {
  2001. InputPort inPort = inNode.GetInputPortByUniqueId( inPortId );
  2002. OutputPort outPort = outNode.GetOutputPortByUniqueId( outPortId );
  2003. if( inPort != null && outPort != null )
  2004. {
  2005. if( registerUndo )
  2006. {
  2007. Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId );
  2008. inNode.RecordObject( Constants.UndoCreateConnectionId );
  2009. outNode.RecordObject( Constants.UndoCreateConnectionId );
  2010. }
  2011. if( inPort.ConnectTo( outNodeId, outPortId, outPort.DataType, inPort.TypeLocked ) )
  2012. {
  2013. inNode.OnInputPortConnected( inPortId, outNodeId, outPortId );
  2014. }
  2015. if( outPort.ConnectTo( inNodeId, inPortId, inPort.DataType, inPort.TypeLocked ) )
  2016. {
  2017. outNode.OnOutputPortConnected( outPortId, inNodeId, inPortId );
  2018. }
  2019. }
  2020. m_mainGraphInstance.MarkWireHighlights();
  2021. ShaderIsModified = true;
  2022. }
  2023. }
  2024. void OnRightMouseDown()
  2025. {
  2026. Focus();
  2027. m_rmbStartPos = m_currentMousePos2D;
  2028. UseCurrentEvent();
  2029. }
  2030. void OnRightMouseDrag()
  2031. {
  2032. // We look at the control to detect when user hits a tooltip ( which has a hot control of 0 )
  2033. // This needs to be checked because on this first "frame" of hitting a tooltip because it generates incorrect mouse delta values
  2034. if( GUIUtility.hotControl == 0 && m_lastHotControl != 0 )
  2035. {
  2036. m_lastHotControl = GUIUtility.hotControl;
  2037. return;
  2038. }
  2039. m_lastHotControl = GUIUtility.hotControl;
  2040. if( m_currentEvent.alt )
  2041. {
  2042. ModifyZoom( Constants.ALT_CAMERA_ZOOM_SPEED * ( m_currentEvent.delta.x + m_currentEvent.delta.y ), m_altKeyStartPos );
  2043. }
  2044. else
  2045. {
  2046. m_cameraOffset += m_cameraZoom * m_currentEvent.delta;
  2047. }
  2048. UseCurrentEvent();
  2049. }
  2050. void OnRightMouseUp()
  2051. {
  2052. //Resetting the hot control test variable so it can be used again on right mouse drag detection ( if we did not do this then m_lastHotControl could be left with a a value of 0 and wouldn't be able to be correctly used on rthe drag )
  2053. m_lastHotControl = -1;
  2054. if( ( m_rmbStartPos - m_currentMousePos2D ).sqrMagnitude < Constants.RMB_SCREEN_DIST )
  2055. {
  2056. ParentNode node = m_mainGraphInstance.CheckNodeAt( m_currentMousePos, true );
  2057. if( node == null )
  2058. {
  2059. m_contextPalette.Show( m_currentMousePos2D, m_cameraInfo );
  2060. }
  2061. }
  2062. UseCurrentEvent();
  2063. }
  2064. void UpdateSelectionArea()
  2065. {
  2066. m_multipleSelectionArea.size = TranformedMousePos - m_multipleSelectionStart;
  2067. }
  2068. public void OnValidObjectsDropped( UnityEngine.Object[] droppedObjs )
  2069. {
  2070. bool propagateDraggedObjsToNode = true;
  2071. // Only supporting single drag&drop object selection
  2072. if( droppedObjs.Length == 1 )
  2073. {
  2074. ShaderIsModified = true;
  2075. SetSaveIsDirty();
  2076. // Check if its a shader, material or game object and if so load the shader graph code from it
  2077. Shader newShader = droppedObjs[ 0 ] as Shader;
  2078. Material newMaterial = null;
  2079. if( newShader == null )
  2080. {
  2081. newMaterial = droppedObjs[ 0 ] as Material;
  2082. #if UNITY_2018_1_OR_NEWER
  2083. bool isProcedural = ( newMaterial != null );
  2084. #else
  2085. // Disabling Substance Deprecated warning
  2086. #pragma warning disable 0618
  2087. bool isProcedural = ( newMaterial != null && newMaterial is ProceduralMaterial );
  2088. #pragma warning restore 0618
  2089. #endif
  2090. if( newMaterial != null && !isProcedural )
  2091. {
  2092. if( UIUtils.IsUnityNativeShader( AssetDatabase.GetAssetPath( newMaterial.shader ) ) )
  2093. {
  2094. return;
  2095. }
  2096. //newShader = newMaterial.shader;
  2097. LoadMaterialToASE( newMaterial );
  2098. //m_mainGraphInstance.UpdateMaterialOnMasterNode( newMaterial );
  2099. }
  2100. else
  2101. {
  2102. GameObject go = droppedObjs[ 0 ] as GameObject;
  2103. if( go != null )
  2104. {
  2105. Renderer renderer = go.GetComponent<Renderer>();
  2106. if( renderer )
  2107. {
  2108. newMaterial = renderer.sharedMaterial;
  2109. newShader = newMaterial.shader;
  2110. }
  2111. }
  2112. }
  2113. }
  2114. if( newShader != null )
  2115. {
  2116. ConvertShaderToASE( newShader );
  2117. propagateDraggedObjsToNode = false;
  2118. }
  2119. // if not shader loading then propagate the seletion to whats below the mouse
  2120. if( propagateDraggedObjsToNode )
  2121. {
  2122. ParentNode node = m_mainGraphInstance.CheckNodeAt( m_currentMousePos );
  2123. if( node != null )
  2124. {
  2125. // if there's a node then pass the object into it to see if there's a setup with it
  2126. node.OnObjectDropped( droppedObjs[ 0 ] );
  2127. }
  2128. else
  2129. {
  2130. // If not then check if there's a node that can be created through the dropped object
  2131. ParentNode newNode = m_contextMenu.CreateNodeFromCastType( droppedObjs[ 0 ].GetType() );
  2132. if( newNode )
  2133. {
  2134. newNode.ContainerGraph = m_mainGraphInstance;
  2135. newNode.Vec2Position = TranformedMousePos;
  2136. m_mainGraphInstance.AddNode( newNode, true );
  2137. newNode.SetupFromCastObject( droppedObjs[ 0 ] );
  2138. m_mainGraphInstance.SelectNode( newNode, false, false );
  2139. ForceRepaint();
  2140. bool find = false;
  2141. if( newNode is FunctionNode && CurrentGraph.CurrentShaderFunction != null )
  2142. find = SearchFunctionNodeRecursively( CurrentGraph.CurrentShaderFunction );
  2143. if( find )
  2144. {
  2145. DestroyNode( newNode, false );
  2146. ShowMessage( "Shader Function loop detected, new node was removed to prevent errors." );
  2147. }
  2148. }
  2149. }
  2150. }
  2151. }
  2152. }
  2153. public bool SearchFunctionNodeRecursively( AmplifyShaderFunction function )
  2154. {
  2155. List<FunctionNode> graphList = UIUtils.FunctionList();
  2156. bool nodeFind = false;
  2157. for( int i = 0; i < graphList.Count; i++ )
  2158. {
  2159. ParentGraph temp = CustomGraph;
  2160. CustomGraph = graphList[ i ].FunctionGraph;
  2161. nodeFind = SearchFunctionNodeRecursively( function );
  2162. CustomGraph = temp;
  2163. //Debug.Log( "tested = " + node.Function.FunctionName + " : " + function.FunctionName );
  2164. if( graphList[ i ].Function == function )
  2165. return true;
  2166. }
  2167. return nodeFind;
  2168. }
  2169. public void SetDelayedMaterialMode( Material material )
  2170. {
  2171. if( material == null )
  2172. return;
  2173. m_delayedMaterialSet = material;
  2174. }
  2175. public ShaderLoadResult LoadDroppedObject( bool value, Shader shader, Material material, AmplifyShaderFunction shaderFunction = null )
  2176. {
  2177. UIUtils.CurrentWindow = this;
  2178. ShaderLoadResult result;
  2179. if( shaderFunction != null )
  2180. {
  2181. string assetDatapath = AssetDatabase.GetAssetPath( shaderFunction );
  2182. string latestOpenedFolder = Application.dataPath + assetDatapath.Substring( 6 );
  2183. UIUtils.LatestOpenedFolder = latestOpenedFolder.Substring( 0, latestOpenedFolder.LastIndexOf( '/' ) + 1 );
  2184. result = LoadFromDisk( assetDatapath, shaderFunction );
  2185. CurrentSelection = ASESelectionMode.ShaderFunction;
  2186. IsShaderFunctionWindow = true;
  2187. titleContent.text = GenerateTabTitle( shaderFunction.FunctionName );
  2188. titleContent.image = UIUtils.ShaderFunctionIcon;
  2189. m_lastpath = assetDatapath;
  2190. m_nodeParametersWindow.OnShaderFunctionLoad();
  2191. //EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, assetDatapath );
  2192. }
  2193. else if( value && shader != null )
  2194. {
  2195. string assetDatapath = AssetDatabase.GetAssetPath( shader );
  2196. string latestOpenedFolder = Application.dataPath + assetDatapath.Substring( 6 );
  2197. UIUtils.LatestOpenedFolder = latestOpenedFolder.Substring( 0, latestOpenedFolder.LastIndexOf( '/' ) + 1 );
  2198. result = LoadFromDisk( assetDatapath );
  2199. switch( result )
  2200. {
  2201. case ShaderLoadResult.LOADED:
  2202. {
  2203. m_mainGraphInstance.UpdateShaderOnMasterNode( shader );
  2204. }
  2205. break;
  2206. case ShaderLoadResult.ASE_INFO_NOT_FOUND:
  2207. {
  2208. ShowMessage( "Loaded shader wasn't created with ASE. Saving it will remove previous data." );
  2209. UIUtils.CreateEmptyFromInvalid( shader );
  2210. }
  2211. break;
  2212. case ShaderLoadResult.FILE_NOT_FOUND:
  2213. case ShaderLoadResult.UNITY_NATIVE_PATHS:
  2214. {
  2215. UIUtils.CreateEmptyFromInvalid( shader );
  2216. }
  2217. break;
  2218. }
  2219. m_mainGraphInstance.UpdateMaterialOnMasterNode( material );
  2220. m_mainGraphInstance.SetMaterialModeOnGraph( material );
  2221. if( material != null )
  2222. {
  2223. CurrentSelection = ASESelectionMode.Material;
  2224. IsShaderFunctionWindow = false;
  2225. titleContent.text = GenerateTabTitle( material.name );
  2226. titleContent.image = UIUtils.MaterialIcon;
  2227. if( material.HasProperty( IOUtils.DefaultASEDirtyCheckId ) )
  2228. {
  2229. material.SetInt( IOUtils.DefaultASEDirtyCheckId, 1 );
  2230. }
  2231. m_lastpath = AssetDatabase.GetAssetPath( material );
  2232. EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, m_lastpath );
  2233. }
  2234. else
  2235. {
  2236. CurrentSelection = ASESelectionMode.Shader;
  2237. IsShaderFunctionWindow = false;
  2238. titleContent.text = GenerateTabTitle( shader.name );
  2239. titleContent.image = UIUtils.ShaderIcon;
  2240. m_lastpath = AssetDatabase.GetAssetPath( shader );
  2241. EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, m_lastpath );
  2242. }
  2243. }
  2244. else
  2245. {
  2246. result = ShaderLoadResult.FILE_NOT_FOUND;
  2247. }
  2248. return result;
  2249. }
  2250. bool InsideMenus( Vector2 position )
  2251. {
  2252. for( int i = 0; i < m_registeredMenus.Count; i++ )
  2253. {
  2254. if( m_registeredMenus[ i ].IsInside( position ) )
  2255. {
  2256. return true;
  2257. }
  2258. }
  2259. return false;
  2260. }
  2261. void HandleGUIEvents()
  2262. {
  2263. if( m_currentEvent.type == EventType.KeyDown )
  2264. {
  2265. m_contextMenu.UpdateKeyPress( m_currentEvent.keyCode );
  2266. }
  2267. else if( m_currentEvent.type == EventType.KeyUp )
  2268. {
  2269. m_contextMenu.UpdateKeyReleased( m_currentEvent.keyCode );
  2270. }
  2271. if( InsideMenus( m_currentMousePos2D ) )
  2272. {
  2273. if( m_currentEvent.type == EventType.MouseDown )
  2274. {
  2275. m_mouseDownOnValidArea = false;
  2276. UseCurrentEvent();
  2277. }
  2278. return;
  2279. }
  2280. else if( m_nodeParametersWindow.IsResizing || m_paletteWindow.IsResizing )
  2281. {
  2282. m_mouseDownOnValidArea = false;
  2283. }
  2284. int controlID = GUIUtility.GetControlID( FocusType.Passive );
  2285. switch( m_currentEvent.GetTypeForControl( controlID ) )
  2286. {
  2287. case EventType.MouseDown:
  2288. {
  2289. GUIUtility.hotControl = controlID;
  2290. switch( m_currentEvent.button )
  2291. {
  2292. case ButtonClickId.LeftMouseButton:
  2293. {
  2294. OnLeftMouseDown();
  2295. }
  2296. break;
  2297. case ButtonClickId.RightMouseButton:
  2298. case ButtonClickId.MiddleMouseButton:
  2299. {
  2300. OnRightMouseDown();
  2301. }
  2302. break;
  2303. }
  2304. }
  2305. break;
  2306. case EventType.MouseUp:
  2307. {
  2308. GUIUtility.hotControl = 0;
  2309. switch( m_currentEvent.button )
  2310. {
  2311. case ButtonClickId.LeftMouseButton:
  2312. {
  2313. OnLeftMouseUp();
  2314. }
  2315. break;
  2316. case ButtonClickId.MiddleMouseButton: break;
  2317. case ButtonClickId.RightMouseButton:
  2318. {
  2319. OnRightMouseUp();
  2320. }
  2321. break;
  2322. }
  2323. }
  2324. break;
  2325. case EventType.MouseDrag:
  2326. {
  2327. switch( m_currentEvent.button )
  2328. {
  2329. case ButtonClickId.LeftMouseButton:
  2330. {
  2331. OnLeftMouseDrag();
  2332. }
  2333. break;
  2334. case ButtonClickId.MiddleMouseButton:
  2335. case ButtonClickId.RightMouseButton:
  2336. {
  2337. OnRightMouseDrag();
  2338. }
  2339. break;
  2340. }
  2341. }
  2342. break;
  2343. case EventType.ScrollWheel:
  2344. {
  2345. OnScrollWheel();
  2346. }
  2347. break;
  2348. case EventType.KeyDown:
  2349. {
  2350. OnKeyboardDown();
  2351. }
  2352. break;
  2353. case EventType.KeyUp:
  2354. {
  2355. OnKeyboardUp();
  2356. }
  2357. break;
  2358. case EventType.ValidateCommand:
  2359. {
  2360. switch( m_currentEvent.commandName )
  2361. {
  2362. case CopyCommand:
  2363. case PasteCommand:
  2364. case SelectAll:
  2365. case Duplicate:
  2366. {
  2367. m_currentEvent.Use();
  2368. }
  2369. break;
  2370. case ObjectSelectorClosed:
  2371. {
  2372. m_mouseDownOnValidArea = false;
  2373. }
  2374. break;
  2375. }
  2376. }
  2377. break;
  2378. case EventType.ExecuteCommand:
  2379. {
  2380. m_currentEvent.Use();
  2381. switch( m_currentEvent.commandName )
  2382. {
  2383. case CopyCommand:
  2384. {
  2385. CopyToClipboard();
  2386. }
  2387. break;
  2388. case PasteCommand:
  2389. {
  2390. PasteFromClipboard( true );
  2391. }
  2392. break;
  2393. case SelectAll:
  2394. {
  2395. m_mainGraphInstance.SelectAll();
  2396. ForceRepaint();
  2397. }
  2398. break;
  2399. case Duplicate:
  2400. {
  2401. CopyToClipboard();
  2402. PasteFromClipboard( true );
  2403. }
  2404. break;
  2405. case ObjectSelectorClosed:
  2406. {
  2407. m_mouseDownOnValidArea = false;
  2408. }break;
  2409. }
  2410. }
  2411. break;
  2412. case EventType.Repaint:
  2413. {
  2414. }
  2415. break;
  2416. }
  2417. m_dragAndDropTool.TestDragAndDrop( m_graphArea );
  2418. }
  2419. public void DeleteConnection( bool isInput, int nodeId, int portId, bool registerOnLog, bool propagateCallback )
  2420. {
  2421. m_mainGraphInstance.DeleteConnection( isInput, nodeId, portId, registerOnLog, propagateCallback );
  2422. }
  2423. void DeleteSelectedNodes()
  2424. {
  2425. if( m_mainGraphInstance.SelectedNodes.Count == 0 )
  2426. return;
  2427. UIUtils.ClearUndoHelper();
  2428. ParentNode[] selectedNodes = new ParentNode[ m_mainGraphInstance.SelectedNodes.Count ];
  2429. for( int i = 0; i < selectedNodes.Length; i++ )
  2430. {
  2431. selectedNodes[ i ] = m_mainGraphInstance.SelectedNodes[ i ];
  2432. selectedNodes[ i ].Rewire();
  2433. UIUtils.CheckUndoNode( selectedNodes[ i ] );
  2434. }
  2435. //Check nodes connected to deleted nodes to preserve connections on undo
  2436. List<ParentNode> extraNodes = new List<ParentNode>();
  2437. for( int selectedNodeIdx = 0; selectedNodeIdx < selectedNodes.Length; selectedNodeIdx++ )
  2438. {
  2439. // Check inputs
  2440. {
  2441. int inputIdxCount = selectedNodes[ selectedNodeIdx ].InputPorts.Count;
  2442. if( inputIdxCount > 0 )
  2443. {
  2444. for( int inputIdx = 0; inputIdx < inputIdxCount; inputIdx++ )
  2445. {
  2446. if( selectedNodes[ selectedNodeIdx ].InputPorts[ inputIdx ].IsConnected )
  2447. {
  2448. int nodeIdx = selectedNodes[ selectedNodeIdx ].InputPorts[ inputIdx ].ExternalReferences[ 0 ].NodeId;
  2449. if( nodeIdx > -1 )
  2450. {
  2451. ParentNode node = m_mainGraphInstance.GetNode( nodeIdx );
  2452. if( node != null && UIUtils.CheckUndoNode( node ) )
  2453. {
  2454. extraNodes.Add( node );
  2455. }
  2456. }
  2457. }
  2458. }
  2459. }
  2460. }
  2461. // Check outputs
  2462. int outputIdxCount = selectedNodes[ selectedNodeIdx ].OutputPorts.Count;
  2463. if( outputIdxCount > 0 )
  2464. {
  2465. for( int outputIdx = 0; outputIdx < outputIdxCount; outputIdx++ )
  2466. {
  2467. int inputIdxCount = selectedNodes[ selectedNodeIdx ].OutputPorts[ outputIdx ].ExternalReferences.Count;
  2468. if( inputIdxCount > 0 )
  2469. {
  2470. for( int inputIdx = 0; inputIdx < inputIdxCount; inputIdx++ )
  2471. {
  2472. int nodeIdx = selectedNodes[ selectedNodeIdx ].OutputPorts[ outputIdx ].ExternalReferences[ inputIdx ].NodeId;
  2473. if( nodeIdx > -1 )
  2474. {
  2475. ParentNode node = m_mainGraphInstance.GetNode( nodeIdx );
  2476. if( UIUtils.CheckUndoNode( node ) )
  2477. {
  2478. extraNodes.Add( node );
  2479. }
  2480. }
  2481. }
  2482. }
  2483. }
  2484. }
  2485. }
  2486. UIUtils.ClearUndoHelper();
  2487. //Undo.IncrementCurrentGroup();
  2488. //Record deleted nodes
  2489. UIUtils.MarkUndoAction();
  2490. Undo.RegisterCompleteObjectUndo( this, Constants.UndoDeleteNodeId );
  2491. Undo.RegisterCompleteObjectUndo( m_mainGraphInstance, Constants.UndoDeleteNodeId );
  2492. Undo.RecordObjects( selectedNodes, Constants.UndoDeleteNodeId );
  2493. Undo.RecordObjects( extraNodes.ToArray(), Constants.UndoDeleteNodeId );
  2494. //Record deleting connections
  2495. for( int i = 0; i < selectedNodes.Length; i++ )
  2496. {
  2497. selectedNodes[ i ].Alive = false;
  2498. m_mainGraphInstance.DeleteAllConnectionFromNode( selectedNodes[ i ], false, true , true );
  2499. }
  2500. //Delete
  2501. m_mainGraphInstance.DeleteNodesOnArray( ref selectedNodes );
  2502. //Undo.IncrementCurrentGroup();
  2503. extraNodes.Clear();
  2504. extraNodes = null;
  2505. EditorUtility.SetDirty( this );
  2506. ForceRepaint();
  2507. }
  2508. void OnKeyboardUp()
  2509. {
  2510. CheckKeyboardCameraUp();
  2511. if( m_altPressDown )
  2512. {
  2513. m_altPressDown = false;
  2514. }
  2515. if( m_shortcutManager.ActivateShortcut( m_currentEvent.modifiers, m_lastKeyPressed, false ) )
  2516. {
  2517. ForceRepaint();
  2518. }
  2519. m_lastKeyPressed = KeyCode.None;
  2520. }
  2521. bool OnKeyboardPress( KeyCode code )
  2522. {
  2523. return ( m_currentEvent.keyCode == code && m_lastKeyPressed == KeyCode.None );
  2524. }
  2525. void CheckKeyboardCameraDown()
  2526. {
  2527. if( m_contextPalette.IsActive )
  2528. return;
  2529. if( m_currentEvent.alt )
  2530. {
  2531. bool foundKey = false;
  2532. float dir = 0;
  2533. switch( m_currentEvent.keyCode )
  2534. {
  2535. case KeyCode.UpArrow: foundKey = true; dir = 1; break;
  2536. case KeyCode.DownArrow: foundKey = true; dir = -1; break;
  2537. case KeyCode.LeftArrow: foundKey = true; dir = 1; break;
  2538. case KeyCode.RightArrow: foundKey = true; dir = -1; break;
  2539. }
  2540. if( foundKey )
  2541. {
  2542. ModifyZoom( Constants.ALT_CAMERA_ZOOM_SPEED * dir * m_cameraSpeed, new Vector2( m_cameraInfo.width * 0.5f, m_cameraInfo.height * 0.5f ) );
  2543. if( m_cameraSpeed < 15 )
  2544. m_cameraSpeed += 0.2f;
  2545. UseCurrentEvent();
  2546. }
  2547. }
  2548. else
  2549. {
  2550. bool foundKey = false;
  2551. Vector2 dir = Vector2.zero;
  2552. switch( m_currentEvent.keyCode )
  2553. {
  2554. case KeyCode.UpArrow: foundKey = true; dir = Vector2.up; break;
  2555. case KeyCode.DownArrow: foundKey = true; dir = Vector2.down; break;
  2556. case KeyCode.LeftArrow: foundKey = true; dir = Vector2.right; break;
  2557. case KeyCode.RightArrow: foundKey = true; dir = Vector2.left; break;
  2558. }
  2559. if( foundKey )
  2560. {
  2561. m_cameraOffset += m_cameraZoom * m_cameraSpeed * dir;
  2562. if( m_cameraSpeed < 15 )
  2563. m_cameraSpeed += 0.2f;
  2564. UseCurrentEvent();
  2565. }
  2566. }
  2567. }
  2568. void CheckKeyboardCameraUp()
  2569. {
  2570. switch( m_currentEvent.keyCode )
  2571. {
  2572. case KeyCode.UpArrow:
  2573. case KeyCode.DownArrow:
  2574. case KeyCode.LeftArrow:
  2575. case KeyCode.RightArrow: m_cameraSpeed = 1;break;
  2576. }
  2577. }
  2578. void OnKeyboardDown()
  2579. {
  2580. //if( DebugConsoleWindow.DeveloperMode )
  2581. //{
  2582. // if( OnKeyboardPress( KeyCode.F8 ) )
  2583. // {
  2584. // Shader currShader = CurrentGraph.CurrentShader;
  2585. // ShaderUtilEx.OpenCompiledShader( currShader, ShaderInspectorPlatformsPopupEx.GetCurrentMode(), ShaderInspectorPlatformsPopupEx.GetCurrentPlatformMask(), ShaderInspectorPlatformsPopupEx.GetCurrentVariantStripping() == 0 );
  2586. // string filename = Application.dataPath;
  2587. // filename = filename.Replace( "Assets", "Temp/Compiled-" );
  2588. // string shaderFilename = AssetDatabase.GetAssetPath( currShader );
  2589. // int lastIndex = shaderFilename.LastIndexOf( '/' ) + 1;
  2590. // filename = filename + shaderFilename.Substring( lastIndex );
  2591. // string compiledContents = IOUtils.LoadTextFileFromDisk( filename );
  2592. // Debug.Log( compiledContents );
  2593. // }
  2594. // if( OnKeyboardPress( KeyCode.F9 ) )
  2595. // {
  2596. // m_nodeExporterUtils.CalculateShaderInstructions( CurrentGraph.CurrentShader );
  2597. // }
  2598. //}
  2599. CheckKeyboardCameraDown();
  2600. if( m_lastKeyPressed == KeyCode.None )
  2601. {
  2602. m_shortcutManager.ActivateShortcut( m_currentEvent.modifiers, m_currentEvent.keyCode, true );
  2603. }
  2604. if( m_currentEvent.control && m_currentEvent.shift && m_currentEvent.keyCode == KeyCode.V )
  2605. {
  2606. PasteFromClipboard( false );
  2607. }
  2608. if( !m_altPressDown && ( OnKeyboardPress( KeyCode.LeftAlt ) || OnKeyboardPress( KeyCode.RightAlt ) || OnKeyboardPress( KeyCode.AltGr ) ) )
  2609. {
  2610. m_altPressDown = true;
  2611. m_altAvailable = true;
  2612. m_altKeyStartPos = m_currentMousePos2D;
  2613. }
  2614. if( m_currentEvent.keyCode != KeyCode.None && m_currentEvent.modifiers == EventModifiers.None )
  2615. {
  2616. m_lastKeyPressed = m_currentEvent.keyCode;
  2617. }
  2618. }
  2619. void OnScrollWheel()
  2620. {
  2621. ModifyZoomSmooth( m_currentEvent.delta.y, m_currentMousePos2D );
  2622. UseCurrentEvent();
  2623. }
  2624. void ModifyZoom( float zoomIncrement, Vector2 pivot )
  2625. {
  2626. float minCam = Mathf.Min( ( m_cameraInfo.width - ( m_nodeParametersWindow.RealWidth + m_paletteWindow.RealWidth ) ), ( m_cameraInfo.height - ( m_toolsWindow.Height ) ) );
  2627. if( minCam < 1 )
  2628. minCam = 1;
  2629. float dynamicMaxZoom = m_mainGraphInstance.MaxNodeDist / minCam;
  2630. Vector2 canvasPos = TranformPosition( pivot );
  2631. if( zoomIncrement < 0 )
  2632. CameraZoom = Mathf.Max( m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED, Constants.CAMERA_MIN_ZOOM );
  2633. else if( CameraZoom < Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) )
  2634. CameraZoom = m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED;// Mathf.Min( m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED, Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) );
  2635. m_cameraOffset.x = pivot.x * m_cameraZoom - canvasPos.x;
  2636. m_cameraOffset.y = pivot.y * m_cameraZoom - canvasPos.y;
  2637. }
  2638. void ModifyZoomSmooth( float zoomIncrement, Vector2 pivot )
  2639. {
  2640. if( m_smoothZoom && Mathf.Sign( m_targetZoomIncrement * zoomIncrement ) >= 0 )
  2641. m_targetZoomIncrement += zoomIncrement;
  2642. else
  2643. m_targetZoomIncrement = zoomIncrement;
  2644. m_smoothZoom = true;
  2645. m_zoomTime = 0;
  2646. float minCam = Mathf.Min( ( m_cameraInfo.width - ( m_nodeParametersWindow.RealWidth + m_paletteWindow.RealWidth ) ), ( m_cameraInfo.height - ( m_toolsWindow.Height ) ) );
  2647. if( minCam < 1 )
  2648. minCam = 1;
  2649. float dynamicMaxZoom = m_mainGraphInstance.MaxNodeDist / minCam;
  2650. if( m_targetZoomIncrement < 0 )
  2651. m_targetZoom = Mathf.Max( m_cameraZoom + m_targetZoomIncrement * Constants.CAMERA_ZOOM_SPEED, Constants.CAMERA_MIN_ZOOM );
  2652. else if( CameraZoom < Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) )
  2653. m_targetZoom = m_cameraZoom + m_targetZoomIncrement * Constants.CAMERA_ZOOM_SPEED;// Mathf.Min( m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED, Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) );
  2654. m_zoomPivot = pivot;
  2655. }
  2656. void OnSelectionChange()
  2657. {
  2658. ForceRepaint();
  2659. }
  2660. private void OnFocus()
  2661. {
  2662. EditorGUI.FocusTextInControl( null );
  2663. }
  2664. void OnLostFocus()
  2665. {
  2666. m_lostFocus = true;
  2667. m_multipleSelectionActive = false;
  2668. m_wireReferenceUtils.InvalidateReferences();
  2669. m_genericMessageUI.CleanUpMessageStack();
  2670. m_nodeParametersWindow.OnLostFocus();
  2671. m_paletteWindow.OnLostFocus();
  2672. m_contextMenu.ResetShortcutKeyStates();
  2673. }
  2674. void CopyToClipboard()
  2675. {
  2676. m_copyPasteDeltaMul = 0;
  2677. m_copyPasteDeltaPos = new Vector2( float.MaxValue, float.MaxValue );
  2678. m_clipboard.ClearClipboard();
  2679. m_copyPasteInitialPos = m_mainGraphInstance.SelectedNodesCentroid;
  2680. m_clipboard.AddToClipboard( m_mainGraphInstance.SelectedNodes, m_copyPasteInitialPos, m_mainGraphInstance );
  2681. }
  2682. ParentNode CreateNodeFromClipboardData( int clipId )
  2683. {
  2684. string[] parameters = m_clipboard.CurrentClipboardStrData[ clipId ].Data.Split( IOUtils.FIELD_SEPARATOR );
  2685. System.Type nodeType = System.Type.GetType( parameters[ IOUtils.NodeTypeId ] );
  2686. NodeAttributes attributes = m_contextMenu.GetNodeAttributesForType( nodeType );
  2687. if( attributes != null && !UIUtils.GetNodeAvailabilityInBitArray( attributes.NodeAvailabilityFlags, m_mainGraphInstance.CurrentCanvasMode ) && !UIUtils.GetNodeAvailabilityInBitArray( attributes.NodeAvailabilityFlags, m_currentNodeAvailability ) )
  2688. return null;
  2689. ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( nodeType );
  2690. newNode.IsNodeBeingCopied = true;
  2691. if( newNode != null )
  2692. {
  2693. newNode.ContainerGraph = m_mainGraphInstance;
  2694. newNode.ClipboardFullReadFromString( ref parameters );
  2695. m_mainGraphInstance.AddNode( newNode, true, true, true, false );
  2696. newNode.IsNodeBeingCopied = false;
  2697. m_clipboard.CurrentClipboardStrData[ clipId ].NewNodeId = newNode.UniqueId;
  2698. return newNode;
  2699. }
  2700. return null;
  2701. }
  2702. void CreateConnectionsFromClipboardData( int clipId )
  2703. {
  2704. if( String.IsNullOrEmpty( m_clipboard.CurrentClipboardStrData[ clipId ].Connections ) )
  2705. return;
  2706. string[] lines = m_clipboard.CurrentClipboardStrData[ clipId ].Connections.Split( IOUtils.LINE_TERMINATOR );
  2707. for( int lineIdx = 0; lineIdx < lines.Length; lineIdx++ )
  2708. {
  2709. string[] parameters = lines[ lineIdx ].Split( IOUtils.FIELD_SEPARATOR );
  2710. int InNodeId = 0;
  2711. int InPortId = 0;
  2712. int OutNodeId = 0;
  2713. int OutPortId = 0;
  2714. try
  2715. {
  2716. InNodeId = Convert.ToInt32( parameters[ IOUtils.InNodeId ] );
  2717. InPortId = Convert.ToInt32( parameters[ IOUtils.InPortId ] );
  2718. OutNodeId = Convert.ToInt32( parameters[ IOUtils.OutNodeId ] );
  2719. OutPortId = Convert.ToInt32( parameters[ IOUtils.OutPortId ] );
  2720. }
  2721. catch( Exception e )
  2722. {
  2723. Debug.LogException( e );
  2724. }
  2725. int newInNodeId = m_clipboard.GeNewNodeId( InNodeId );
  2726. int newOutNodeId = m_clipboard.GeNewNodeId( OutNodeId );
  2727. if( newInNodeId > -1 && newOutNodeId > -1 )
  2728. {
  2729. ParentNode inNode = m_mainGraphInstance.GetNode( newInNodeId );
  2730. ParentNode outNode = m_mainGraphInstance.GetNode( newOutNodeId );
  2731. InputPort inputPort = null;
  2732. OutputPort outputPort = null;
  2733. if( inNode != null && outNode != null )
  2734. {
  2735. inNode.IsNodeBeingCopied = true;
  2736. outNode.IsNodeBeingCopied = true;
  2737. inputPort = inNode.GetInputPortByUniqueId( InPortId );
  2738. outputPort = outNode.GetOutputPortByUniqueId( OutPortId );
  2739. if( inputPort != null && outputPort != null )
  2740. {
  2741. inputPort.ConnectTo( newOutNodeId, OutPortId, outputPort.DataType, false );
  2742. outputPort.ConnectTo( newInNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked );
  2743. inNode.OnInputPortConnected( InPortId, newOutNodeId, OutPortId );
  2744. outNode.OnOutputPortConnected( OutPortId, newInNodeId, InPortId );
  2745. }
  2746. inNode.IsNodeBeingCopied = false;
  2747. outNode.IsNodeBeingCopied = false;
  2748. }
  2749. }
  2750. }
  2751. }
  2752. void PasteFromClipboard( bool copyConnections )
  2753. {
  2754. m_mainGraphInstance.IsDuplicating = true;
  2755. m_copyPasteInitialPos = m_clipboard.GetDataFromEditorPrefs();
  2756. if( m_clipboard.CurrentClipboardStrData.Count == 0 )
  2757. {
  2758. return;
  2759. }
  2760. Vector2 deltaPos = TranformedKeyEvtMousePos - m_copyPasteInitialPos;
  2761. if( ( m_copyPasteDeltaPos - deltaPos ).magnitude > 5.0f )
  2762. {
  2763. m_copyPasteDeltaMul = 0;
  2764. }
  2765. else
  2766. {
  2767. m_copyPasteDeltaMul += 1;
  2768. }
  2769. m_copyPasteDeltaPos = deltaPos;
  2770. m_mainGraphInstance.DeSelectAll();
  2771. UIUtils.InhibitMessages = true;
  2772. if( m_clipboard.CurrentClipboardStrData.Count > 0 )
  2773. {
  2774. UIUtils.MarkUndoAction();
  2775. Undo.RegisterCompleteObjectUndo( this, Constants.UndoPasteNodeId );
  2776. }
  2777. List<ParentNode> createdNodes = new List<ParentNode>();
  2778. for( int i = 0; i < m_clipboard.CurrentClipboardStrData.Count; i++ )
  2779. {
  2780. ParentNode node = CreateNodeFromClipboardData( i );
  2781. if( node != null )
  2782. {
  2783. m_clipboard.CurrentClipboardStrData[ i ].NewNodeId = node.UniqueId;
  2784. Vector2 pos = node.Vec2Position;
  2785. node.Vec2Position = pos + deltaPos + m_copyPasteDeltaMul * Constants.CopyPasteDeltaPos;
  2786. //node.RefreshExternalReferences();
  2787. node.AfterDuplication();
  2788. createdNodes.Add( node );
  2789. m_mainGraphInstance.SelectNode( node, true, false );
  2790. }
  2791. }
  2792. if( copyConnections )
  2793. {
  2794. for( int i = 0; i < m_clipboard.CurrentClipboardStrData.Count; i++ )
  2795. {
  2796. CreateConnectionsFromClipboardData( i );
  2797. }
  2798. }
  2799. // Refresh external references must always be called after all nodes are created
  2800. for( int i = 0; i < createdNodes.Count; i++ )
  2801. {
  2802. createdNodes[ i ].RefreshExternalReferences();
  2803. }
  2804. createdNodes.Clear();
  2805. createdNodes = null;
  2806. //Need to force increment on Undo because if not Undo may incorrectly group consecutive pastes
  2807. Undo.IncrementCurrentGroup();
  2808. UIUtils.InhibitMessages = false;
  2809. ShaderIsModified = true;
  2810. SetSaveIsDirty();
  2811. ForceRepaint();
  2812. m_mainGraphInstance.IsDuplicating = false;
  2813. }
  2814. public string GenerateGraphInfo()
  2815. {
  2816. string graphInfo = IOUtils.ShaderBodyBegin + '\n';
  2817. string nodesInfo = "";
  2818. string connectionsInfo = "";
  2819. graphInfo += VersionInfo.FullLabel + '\n';
  2820. graphInfo += (
  2821. m_cameraInfo.x.ToString() + IOUtils.FIELD_SEPARATOR +
  2822. m_cameraInfo.y.ToString() + IOUtils.FIELD_SEPARATOR +
  2823. m_cameraInfo.width.ToString() + IOUtils.FIELD_SEPARATOR +
  2824. m_cameraInfo.height.ToString() + IOUtils.FIELD_SEPARATOR +
  2825. m_cameraOffset.x.ToString() + IOUtils.FIELD_SEPARATOR +
  2826. m_cameraOffset.y.ToString() + IOUtils.FIELD_SEPARATOR +
  2827. m_cameraZoom.ToString() + IOUtils.FIELD_SEPARATOR +
  2828. m_nodeParametersWindow.IsMaximized + IOUtils.FIELD_SEPARATOR +
  2829. m_paletteWindow.IsMaximized + '\n'
  2830. );
  2831. m_mainGraphInstance.OrderNodesByGraphDepth();
  2832. m_mainGraphInstance.WriteToString( ref nodesInfo, ref connectionsInfo );
  2833. graphInfo += nodesInfo;
  2834. graphInfo += connectionsInfo;
  2835. graphInfo += IOUtils.ShaderBodyEnd + '\n';
  2836. return graphInfo;
  2837. }
  2838. // TODO: this need to be fused to the main load function somehow
  2839. public static void LoadFromMeta( ref ParentGraph graph, GraphContextMenu contextMenu, string meta )
  2840. {
  2841. graph.IsLoading = true;
  2842. graph.CleanNodes();
  2843. int checksumId = meta.IndexOf( IOUtils.CHECKSUM );
  2844. if( checksumId > -1 )
  2845. {
  2846. string checkSumStoredValue = meta.Substring( checksumId );
  2847. string trimmedBuffer = meta.Remove( checksumId );
  2848. string[] typeValuePair = checkSumStoredValue.Split( IOUtils.VALUE_SEPARATOR );
  2849. if( typeValuePair != null && typeValuePair.Length == 2 )
  2850. {
  2851. // Check read checksum and compare with the actual shader body to detect external changes
  2852. string currentChecksumValue = IOUtils.CreateChecksum( trimmedBuffer );
  2853. if( DebugConsoleWindow.DeveloperMode && !currentChecksumValue.Equals( typeValuePair[ 1 ] ) )
  2854. {
  2855. //ShowMessage( "Wrong checksum" );
  2856. }
  2857. trimmedBuffer = trimmedBuffer.Replace( "\r", string.Empty );
  2858. // find node info body
  2859. int shaderBodyId = trimmedBuffer.IndexOf( IOUtils.ShaderBodyBegin );
  2860. if( shaderBodyId > -1 )
  2861. {
  2862. trimmedBuffer = trimmedBuffer.Substring( shaderBodyId );
  2863. //Find set of instructions
  2864. string[] instructions = trimmedBuffer.Split( IOUtils.LINE_TERMINATOR );
  2865. // First line is to be ignored and second line contains version
  2866. string[] versionParams = instructions[ 1 ].Split( IOUtils.VALUE_SEPARATOR );
  2867. if( versionParams.Length == 2 )
  2868. {
  2869. int version = 0;
  2870. try
  2871. {
  2872. version = Convert.ToInt32( versionParams[ 1 ] );
  2873. }
  2874. catch( Exception e )
  2875. {
  2876. Debug.LogException( e );
  2877. }
  2878. //if( version > versionInfo.FullNumber )
  2879. //{
  2880. //ShowMessage( "This shader was created on a new ASE version\nPlease install v." + version );
  2881. //}
  2882. if( DebugConsoleWindow.DeveloperMode )
  2883. {
  2884. //if( version < versionInfo.FullNumber )
  2885. //{
  2886. //ShowMessage( "This shader was created on a older ASE version\nSaving will update it to the new one." );
  2887. //}
  2888. }
  2889. graph.LoadedShaderVersion = version;
  2890. }
  2891. else
  2892. {
  2893. //ShowMessage( "Corrupted version" );
  2894. }
  2895. // Dummy values,camera values can only be applied after node loading is complete
  2896. Rect dummyCameraInfo = new Rect();
  2897. Vector2 dummyCameraOffset = new Vector2();
  2898. //float dummyCameraZoom = 0;
  2899. //bool applyDummy = false;
  2900. //bool dummyNodeParametersWindowMaximized = false;
  2901. //bool dummyPaletteWindowMaximized = false;
  2902. //Second line contains camera information ( position, size, offset and zoom )
  2903. string[] cameraParams = instructions[ 2 ].Split( IOUtils.FIELD_SEPARATOR );
  2904. if( cameraParams.Length == 9 )
  2905. {
  2906. //applyDummy = true;
  2907. try
  2908. {
  2909. dummyCameraInfo.x = Convert.ToSingle( cameraParams[ 0 ] );
  2910. dummyCameraInfo.y = Convert.ToSingle( cameraParams[ 1 ] );
  2911. dummyCameraInfo.width = Convert.ToSingle( cameraParams[ 2 ] );
  2912. dummyCameraInfo.height = Convert.ToSingle( cameraParams[ 3 ] );
  2913. dummyCameraOffset.x = Convert.ToSingle( cameraParams[ 4 ] );
  2914. dummyCameraOffset.y = Convert.ToSingle( cameraParams[ 5 ] );
  2915. //dummyCameraZoom = Convert.ToSingle( cameraParams[ 6 ] );
  2916. //dummyNodeParametersWindowMaximized = Convert.ToBoolean( cameraParams[ 7 ] );
  2917. //dummyPaletteWindowMaximized = Convert.ToBoolean( cameraParams[ 8 ] );
  2918. }
  2919. catch( Exception e )
  2920. {
  2921. Debug.LogException( e );
  2922. }
  2923. }
  2924. else
  2925. {
  2926. //ShowMessage( "Camera parameters are corrupted" );
  2927. }
  2928. // valid instructions are only between the line after version and the line before the last one ( which contains ShaderBodyEnd )
  2929. for( int instructionIdx = 3; instructionIdx < instructions.Length - 1; instructionIdx++ )
  2930. {
  2931. //TODO: After all is working, convert string parameters to ints in order to speed up reading
  2932. string[] parameters = instructions[ instructionIdx ].Split( IOUtils.FIELD_SEPARATOR );
  2933. // All nodes must be created before wiring the connections ...
  2934. // Since all nodes on the save op are written before the wires, we can safely create them
  2935. // If that order is not maintained the it's because of external editing and its the users responsability
  2936. switch( parameters[ 0 ] )
  2937. {
  2938. case IOUtils.NodeParam:
  2939. {
  2940. string typeStr = parameters[ IOUtils.NodeTypeId ];
  2941. //System.Type type = System.Type.GetType( parameters[ IOUtils.NodeTypeId ] );
  2942. System.Type type = System.Type.GetType( IOUtils.NodeTypeReplacer.ContainsKey( typeStr ) ? IOUtils.NodeTypeReplacer[ typeStr ] : typeStr );
  2943. if( type != null )
  2944. {
  2945. System.Type oldType = type;
  2946. NodeAttributes attribs = contextMenu.GetNodeAttributesForType( type );
  2947. if( attribs == null )
  2948. {
  2949. attribs = contextMenu.GetDeprecatedNodeAttributesForType( type );
  2950. if( attribs != null )
  2951. {
  2952. if( attribs.Deprecated && attribs.DeprecatedAlternativeType != null )
  2953. {
  2954. type = attribs.DeprecatedAlternativeType;
  2955. //ShowMessage( string.Format( "Node {0} is deprecated and was replaced by {1} ", attribs.Name, attribs.DeprecatedAlternative ) );
  2956. }
  2957. }
  2958. }
  2959. ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( type );
  2960. if( newNode != null )
  2961. {
  2962. try
  2963. {
  2964. newNode.ContainerGraph = graph;
  2965. if( oldType != type )
  2966. {
  2967. newNode.ParentReadFromString( ref parameters );
  2968. newNode.ReadFromDeprecated( ref parameters, oldType );
  2969. }
  2970. else
  2971. newNode.ReadFromString( ref parameters );
  2972. if( oldType == type )
  2973. {
  2974. newNode.ReadInputDataFromString( ref parameters );
  2975. if( UIUtils.CurrentShaderVersion() > 5107 )
  2976. {
  2977. newNode.ReadOutputDataFromString( ref parameters );
  2978. }
  2979. }
  2980. }
  2981. catch( Exception e )
  2982. {
  2983. Debug.LogException( e, newNode );
  2984. }
  2985. graph.AddNode( newNode, false, true, false );
  2986. }
  2987. }
  2988. else
  2989. {
  2990. UIUtils.ShowMessage( string.Format( "{0} is not a valid ASE node ", parameters[ IOUtils.NodeTypeId ] ), MessageSeverity.Error );
  2991. }
  2992. }
  2993. break;
  2994. case IOUtils.WireConnectionParam:
  2995. {
  2996. int InNodeId = 0;
  2997. int InPortId = 0;
  2998. int OutNodeId = 0;
  2999. int OutPortId = 0;
  3000. try
  3001. {
  3002. InNodeId = Convert.ToInt32( parameters[ IOUtils.InNodeId ] );
  3003. InPortId = Convert.ToInt32( parameters[ IOUtils.InPortId ] );
  3004. OutNodeId = Convert.ToInt32( parameters[ IOUtils.OutNodeId ] );
  3005. OutPortId = Convert.ToInt32( parameters[ IOUtils.OutPortId ] );
  3006. }
  3007. catch( Exception e )
  3008. {
  3009. Debug.LogException( e );
  3010. }
  3011. ParentNode inNode = graph.GetNode( InNodeId );
  3012. ParentNode outNode = graph.GetNode( OutNodeId );
  3013. //if ( UIUtils.CurrentShaderVersion() < 5002 )
  3014. //{
  3015. // InPortId = inNode.VersionConvertInputPortId( InPortId );
  3016. // OutPortId = outNode.VersionConvertOutputPortId( OutPortId );
  3017. //}
  3018. InputPort inputPort = null;
  3019. OutputPort outputPort = null;
  3020. if( inNode != null && outNode != null )
  3021. {
  3022. if( UIUtils.CurrentShaderVersion() < 5002 )
  3023. {
  3024. InPortId = inNode.VersionConvertInputPortId( InPortId );
  3025. OutPortId = outNode.VersionConvertOutputPortId( OutPortId );
  3026. inputPort = inNode.GetInputPortByArrayId( InPortId );
  3027. outputPort = outNode.GetOutputPortByArrayId( OutPortId );
  3028. }
  3029. else
  3030. {
  3031. inputPort = inNode.GetInputPortByUniqueId( InPortId );
  3032. outputPort = outNode.GetOutputPortByUniqueId( OutPortId );
  3033. }
  3034. if( inputPort != null && outputPort != null )
  3035. {
  3036. bool inputCompatible = inputPort.CheckValidType( outputPort.DataType );
  3037. bool outputCompatible = outputPort.CheckValidType( inputPort.DataType );
  3038. if( inputCompatible && outputCompatible )
  3039. {
  3040. inputPort.ConnectTo( OutNodeId, OutPortId, outputPort.DataType, false );
  3041. outputPort.ConnectTo( InNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked );
  3042. inNode.OnInputPortConnected( InPortId, OutNodeId, OutPortId, false );
  3043. outNode.OnOutputPortConnected( OutPortId, InNodeId, InPortId );
  3044. }
  3045. else if( DebugConsoleWindow.DeveloperMode )
  3046. {
  3047. if( !inputCompatible )
  3048. UIUtils.ShowIncompatiblePortMessage( true, inNode, inputPort, outNode, outputPort );
  3049. if( !outputCompatible )
  3050. UIUtils.ShowIncompatiblePortMessage( true, outNode, outputPort, inNode, inputPort );
  3051. }
  3052. }
  3053. else if( DebugConsoleWindow.DeveloperMode )
  3054. {
  3055. if( inputPort == null )
  3056. {
  3057. UIUtils.ShowMessage( "Input Port " + InPortId + " doesn't exist on node " + InNodeId, MessageSeverity.Error );
  3058. }
  3059. else
  3060. {
  3061. UIUtils.ShowMessage( "Output Port " + OutPortId + " doesn't exist on node " + OutNodeId, MessageSeverity.Error );
  3062. }
  3063. }
  3064. }
  3065. else if( DebugConsoleWindow.DeveloperMode )
  3066. {
  3067. if( inNode == null )
  3068. {
  3069. UIUtils.ShowMessage( "Input node " + InNodeId + " doesn't exist", MessageSeverity.Error );
  3070. }
  3071. else
  3072. {
  3073. UIUtils.ShowMessage( "Output node " + OutNodeId + " doesn't exist", MessageSeverity.Error );
  3074. }
  3075. }
  3076. }
  3077. break;
  3078. }
  3079. }
  3080. }
  3081. }
  3082. }
  3083. graph.CheckForDuplicates();
  3084. graph.UpdateRegisters();
  3085. graph.RefreshExternalReferences();
  3086. graph.ForceSignalPropagationOnMasterNode();
  3087. graph.LoadedShaderVersion = VersionInfo.FullNumber;
  3088. //Reset();
  3089. graph.IsLoading = false;
  3090. }
  3091. public ShaderLoadResult LoadFromDisk( string pathname, AmplifyShaderFunction shaderFunction = null )
  3092. {
  3093. m_mainGraphInstance.IsLoading = true;
  3094. System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
  3095. FullCleanUndoStack();
  3096. m_performFullUndoRegister = true;
  3097. UIUtils.DirtyMask = false;
  3098. if( UIUtils.IsUnityNativeShader( pathname ) )
  3099. {
  3100. ShowMessage( "Cannot edit native unity shaders.\nReplacing by a new one." );
  3101. return ShaderLoadResult.UNITY_NATIVE_PATHS;
  3102. }
  3103. m_lastOpenedLocation = pathname;
  3104. Lastpath = pathname;
  3105. string buffer = string.Empty;
  3106. if( shaderFunction == null )
  3107. buffer = IOUtils.LoadTextFileFromDisk( pathname );
  3108. else
  3109. buffer = shaderFunction.FunctionInfo;
  3110. if( String.IsNullOrEmpty( buffer ) )
  3111. {
  3112. ShowMessage( "Could not open file " + pathname );
  3113. return ShaderLoadResult.FILE_NOT_FOUND;
  3114. }
  3115. if( !IOUtils.HasValidShaderBody( ref buffer ) )
  3116. {
  3117. return ShaderLoadResult.ASE_INFO_NOT_FOUND;
  3118. }
  3119. m_mainGraphInstance.CleanNodes();
  3120. Reset();
  3121. Shader shader = null;
  3122. ShaderLoadResult loadResult = ShaderLoadResult.LOADED;
  3123. // Find checksum value on body
  3124. int checksumId = buffer.IndexOf( IOUtils.CHECKSUM );
  3125. if( checksumId > -1 )
  3126. {
  3127. string checkSumStoredValue = buffer.Substring( checksumId );
  3128. string trimmedBuffer = buffer.Remove( checksumId );
  3129. string[] typeValuePair = checkSumStoredValue.Split( IOUtils.VALUE_SEPARATOR );
  3130. if( typeValuePair != null && typeValuePair.Length == 2 )
  3131. {
  3132. // Check read checksum and compare with the actual shader body to detect external changes
  3133. string currentChecksumValue = IOUtils.CreateChecksum( trimmedBuffer );
  3134. if( DebugConsoleWindow.DeveloperMode && !currentChecksumValue.Equals( typeValuePair[ 1 ] ) )
  3135. {
  3136. ShowMessage( "Wrong checksum" );
  3137. }
  3138. trimmedBuffer = trimmedBuffer.Replace( "\r", string.Empty );
  3139. // find node info body
  3140. int shaderBodyId = trimmedBuffer.IndexOf( IOUtils.ShaderBodyBegin );
  3141. if( shaderBodyId > -1 )
  3142. {
  3143. trimmedBuffer = trimmedBuffer.Substring( shaderBodyId );
  3144. //Find set of instructions
  3145. string[] instructions = trimmedBuffer.Split( IOUtils.LINE_TERMINATOR );
  3146. // First line is to be ignored and second line contains version
  3147. string[] versionParams = instructions[ 1 ].Split( IOUtils.VALUE_SEPARATOR );
  3148. if( versionParams.Length == 2 )
  3149. {
  3150. int version = 0;
  3151. try
  3152. {
  3153. version = Convert.ToInt32( versionParams[ 1 ] );
  3154. }
  3155. catch( Exception e )
  3156. {
  3157. Debug.LogException( e );
  3158. }
  3159. if( version > VersionInfo.FullNumber )
  3160. {
  3161. ShowMessage( "This shader was created on a new ASE version\nPlease install v." + version );
  3162. }
  3163. if( DebugConsoleWindow.DeveloperMode )
  3164. {
  3165. if( version < VersionInfo.FullNumber )
  3166. {
  3167. ShowMessage( "This shader was created on a older ASE version\nSaving will update it to the new one." );
  3168. }
  3169. }
  3170. m_mainGraphInstance.LoadedShaderVersion = version;
  3171. }
  3172. else
  3173. {
  3174. ShowMessage( "Corrupted version" );
  3175. }
  3176. // Dummy values,camera values can only be applied after node loading is complete
  3177. Rect dummyCameraInfo = new Rect();
  3178. Vector2 dummyCameraOffset = new Vector2();
  3179. float dummyCameraZoom = 0;
  3180. bool applyDummy = false;
  3181. bool dummyNodeParametersWindowMaximized = false;
  3182. bool dummyPaletteWindowMaximized = false;
  3183. //Second line contains camera information ( position, size, offset and zoom )
  3184. string[] cameraParams = instructions[ 2 ].Split( IOUtils.FIELD_SEPARATOR );
  3185. if( cameraParams.Length == 9 )
  3186. {
  3187. applyDummy = true;
  3188. try
  3189. {
  3190. dummyCameraInfo.x = Convert.ToSingle( cameraParams[ 0 ] );
  3191. dummyCameraInfo.y = Convert.ToSingle( cameraParams[ 1 ] );
  3192. dummyCameraInfo.width = Convert.ToSingle( cameraParams[ 2 ] );
  3193. dummyCameraInfo.height = Convert.ToSingle( cameraParams[ 3 ] );
  3194. dummyCameraOffset.x = Convert.ToSingle( cameraParams[ 4 ] );
  3195. dummyCameraOffset.y = Convert.ToSingle( cameraParams[ 5 ] );
  3196. dummyCameraZoom = Convert.ToSingle( cameraParams[ 6 ] );
  3197. float centerWidth = ( this.position.width - dummyCameraInfo.width ) * 0.5f * dummyCameraZoom;
  3198. float centerHeight = ( this.position.height - dummyCameraInfo.height ) * 0.5f * dummyCameraZoom;
  3199. dummyCameraInfo.x += centerWidth;
  3200. dummyCameraOffset.x += centerWidth;
  3201. dummyCameraInfo.y += centerHeight;
  3202. dummyCameraOffset.y += centerHeight;
  3203. dummyNodeParametersWindowMaximized = Convert.ToBoolean( cameraParams[ 7 ] );
  3204. dummyPaletteWindowMaximized = Convert.ToBoolean( cameraParams[ 8 ] );
  3205. }
  3206. catch( Exception e )
  3207. {
  3208. Debug.LogException( e );
  3209. }
  3210. }
  3211. else
  3212. {
  3213. ShowMessage( "Camera parameters are corrupted" );
  3214. }
  3215. // valid instructions are only between the line after version and the line before the last one ( which contains ShaderBodyEnd )
  3216. for( int instructionIdx = 3; instructionIdx < instructions.Length - 1; instructionIdx++ )
  3217. {
  3218. //TODO: After all is working, convert string parameters to ints in order to speed up reading
  3219. string[] parameters = instructions[ instructionIdx ].Split( IOUtils.FIELD_SEPARATOR );
  3220. // All nodes must be created before wiring the connections ...
  3221. // Since all nodes on the save op are written before the wires, we can safely create them
  3222. // If that order is not maintained the it's because of external editing and its the users responsability
  3223. switch( parameters[ 0 ] )
  3224. {
  3225. case IOUtils.NodeParam:
  3226. {
  3227. string typeStr = parameters[ IOUtils.NodeTypeId ];
  3228. System.Type type = System.Type.GetType( IOUtils.NodeTypeReplacer.ContainsKey( typeStr ) ? IOUtils.NodeTypeReplacer[ typeStr ] : typeStr );
  3229. if( type != null )
  3230. {
  3231. System.Type oldType = type;
  3232. NodeAttributes attribs = m_contextMenu.GetNodeAttributesForType( type );
  3233. if( attribs == null )
  3234. {
  3235. attribs = m_contextMenu.GetDeprecatedNodeAttributesForType( type );
  3236. if( attribs != null )
  3237. {
  3238. if( attribs.Deprecated )
  3239. {
  3240. if( attribs.DeprecatedAlternativeType != null )
  3241. {
  3242. type = attribs.DeprecatedAlternativeType;
  3243. ShowMessage( string.Format( "Node {0} is deprecated and was replaced by {1} ", attribs.Name, attribs.DeprecatedAlternative ) );
  3244. }
  3245. else
  3246. {
  3247. if( string.IsNullOrEmpty( attribs.DeprecatedAlternative ))
  3248. ShowMessage( string.Format( Constants.DeprecatedNoAlternativeMessageStr, attribs.Name, attribs.DeprecatedAlternative ), MessageSeverity.Normal, false );
  3249. else
  3250. ShowMessage( string.Format( Constants.DeprecatedMessageStr, attribs.Name, attribs.DeprecatedAlternative ), MessageSeverity.Normal, false );
  3251. }
  3252. }
  3253. }
  3254. }
  3255. ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( type );
  3256. if( newNode != null )
  3257. {
  3258. try
  3259. {
  3260. newNode.ContainerGraph = m_mainGraphInstance;
  3261. if( oldType != type )
  3262. {
  3263. newNode.ParentReadFromString( ref parameters );
  3264. newNode.ReadFromDeprecated( ref parameters, oldType );
  3265. }
  3266. else
  3267. newNode.ReadFromString( ref parameters );
  3268. if( oldType == type )
  3269. {
  3270. newNode.ReadInputDataFromString( ref parameters );
  3271. if( UIUtils.CurrentShaderVersion() > 5107 )
  3272. {
  3273. newNode.ReadOutputDataFromString( ref parameters );
  3274. }
  3275. }
  3276. }
  3277. catch( Exception e )
  3278. {
  3279. Debug.LogException( e, newNode );
  3280. }
  3281. m_mainGraphInstance.AddNode( newNode, false, true, false );
  3282. }
  3283. }
  3284. else
  3285. {
  3286. ShowMessage( string.Format( "{0} is not a valid ASE node ", parameters[ IOUtils.NodeTypeId ] ), MessageSeverity.Error );
  3287. }
  3288. }
  3289. break;
  3290. case IOUtils.WireConnectionParam:
  3291. {
  3292. int InNodeId = 0;
  3293. int InPortId = 0;
  3294. int OutNodeId = 0;
  3295. int OutPortId = 0;
  3296. try
  3297. {
  3298. InNodeId = Convert.ToInt32( parameters[ IOUtils.InNodeId ] );
  3299. InPortId = Convert.ToInt32( parameters[ IOUtils.InPortId ] );
  3300. OutNodeId = Convert.ToInt32( parameters[ IOUtils.OutNodeId ] );
  3301. OutPortId = Convert.ToInt32( parameters[ IOUtils.OutPortId ] );
  3302. }
  3303. catch( Exception e )
  3304. {
  3305. Debug.LogException( e );
  3306. }
  3307. ParentNode inNode = m_mainGraphInstance.GetNode( InNodeId );
  3308. ParentNode outNode = m_mainGraphInstance.GetNode( OutNodeId );
  3309. //if ( UIUtils.CurrentShaderVersion() < 5002 )
  3310. //{
  3311. // InPortId = inNode.VersionConvertInputPortId( InPortId );
  3312. // OutPortId = outNode.VersionConvertOutputPortId( OutPortId );
  3313. //}
  3314. InputPort inputPort = null;
  3315. OutputPort outputPort = null;
  3316. if( inNode != null && outNode != null )
  3317. {
  3318. if( UIUtils.CurrentShaderVersion() < 5002 )
  3319. {
  3320. InPortId = inNode.VersionConvertInputPortId( InPortId );
  3321. OutPortId = outNode.VersionConvertOutputPortId( OutPortId );
  3322. inputPort = inNode.GetInputPortByArrayId( InPortId );
  3323. outputPort = outNode.GetOutputPortByArrayId( OutPortId );
  3324. }
  3325. else
  3326. {
  3327. inputPort = inNode.GetInputPortByUniqueId( InPortId );
  3328. outputPort = outNode.GetOutputPortByUniqueId( OutPortId );
  3329. }
  3330. if( inputPort != null && outputPort != null )
  3331. {
  3332. bool inputCompatible = inputPort.CheckValidType( outputPort.DataType );
  3333. bool outputCompatible = outputPort.CheckValidType( inputPort.DataType );
  3334. if( inputCompatible && outputCompatible )
  3335. {
  3336. inputPort.ConnectTo( OutNodeId, OutPortId, outputPort.DataType, false );
  3337. outputPort.ConnectTo( InNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked );
  3338. inNode.OnInputPortConnected( InPortId, OutNodeId, OutPortId, false );
  3339. outNode.OnOutputPortConnected( OutPortId, InNodeId, InPortId );
  3340. }
  3341. else if( DebugConsoleWindow.DeveloperMode )
  3342. {
  3343. if( !inputCompatible )
  3344. UIUtils.ShowIncompatiblePortMessage( true, inNode, inputPort, outNode, outputPort );
  3345. if( !outputCompatible )
  3346. UIUtils.ShowIncompatiblePortMessage( true, outNode, outputPort, inNode, inputPort );
  3347. }
  3348. }
  3349. else if( DebugConsoleWindow.DeveloperMode )
  3350. {
  3351. if( inputPort == null )
  3352. {
  3353. UIUtils.ShowMessage( "Input Port " + InPortId + " doesn't exist on node " + InNodeId, MessageSeverity.Error );
  3354. }
  3355. else
  3356. {
  3357. UIUtils.ShowMessage( "Output Port " + OutPortId + " doesn't exist on node " + OutNodeId, MessageSeverity.Error );
  3358. }
  3359. }
  3360. }
  3361. else if( DebugConsoleWindow.DeveloperMode )
  3362. {
  3363. if( inNode == null )
  3364. {
  3365. UIUtils.ShowMessage( "Input node " + InNodeId + " doesn't exist", MessageSeverity.Error );
  3366. }
  3367. else
  3368. {
  3369. UIUtils.ShowMessage( "Output node " + OutNodeId + " doesn't exist", MessageSeverity.Error );
  3370. }
  3371. }
  3372. }
  3373. break;
  3374. }
  3375. }
  3376. if( shaderFunction != null )
  3377. {
  3378. m_onLoadDone = 2;
  3379. if( applyDummy )
  3380. {
  3381. m_cameraInfo = dummyCameraInfo;
  3382. m_cameraOffset = dummyCameraOffset;
  3383. CameraZoom = dummyCameraZoom;
  3384. if( DebugConsoleWindow.UseShaderPanelsInfo )
  3385. {
  3386. m_nodeParametersWindowMaximized = m_nodeParametersWindow.IsMaximized = dummyNodeParametersWindowMaximized;
  3387. m_paletteWindowMaximized = m_paletteWindow.IsMaximized = dummyPaletteWindowMaximized;
  3388. }
  3389. }
  3390. }
  3391. else
  3392. {
  3393. shader = AssetDatabase.LoadAssetAtPath<Shader>( pathname );
  3394. if( shader )
  3395. {
  3396. m_onLoadDone = 2;
  3397. if( applyDummy )
  3398. {
  3399. m_cameraInfo = dummyCameraInfo;
  3400. m_cameraOffset = dummyCameraOffset;
  3401. CameraZoom = dummyCameraZoom;
  3402. if( DebugConsoleWindow.UseShaderPanelsInfo )
  3403. {
  3404. m_nodeParametersWindowMaximized = m_nodeParametersWindow.IsMaximized = dummyNodeParametersWindowMaximized;
  3405. m_paletteWindowMaximized = m_paletteWindow.IsMaximized = dummyPaletteWindowMaximized;
  3406. }
  3407. }
  3408. }
  3409. else
  3410. {
  3411. ShowMessage( "Could not load shader asset" );
  3412. }
  3413. }
  3414. }
  3415. else
  3416. {
  3417. ShowMessage( "Graph info not found" );
  3418. }
  3419. }
  3420. else
  3421. {
  3422. ShowMessage( "Corrupted checksum" );
  3423. }
  3424. }
  3425. else
  3426. {
  3427. ShowMessage( "Checksum not found" );
  3428. }
  3429. //m_mainGraphInstance.LoadedShaderVersion = m_versionInfo.FullNumber;
  3430. if( UIUtils.CurrentMasterNode() )
  3431. UIUtils.CurrentMasterNode().ForcePortType();
  3432. UIUtils.DirtyMask = true;
  3433. m_checkInvalidConnections = true;
  3434. m_mainGraphInstance.CheckForDuplicates();
  3435. m_mainGraphInstance.UpdateRegisters();
  3436. m_mainGraphInstance.RefreshExternalReferences();
  3437. m_mainGraphInstance.ForceSignalPropagationOnMasterNode();
  3438. if( shaderFunction != null )
  3439. {
  3440. //if( CurrentGraph.CurrentFunctionOutput == null )
  3441. //{
  3442. // //Fix in case a function output node is not marked as main node
  3443. // CurrentGraph.AssignMasterNode( UIUtils.FunctionOutputList()[ 0 ], false );
  3444. //}
  3445. CurrentGraph.CurrentShaderFunction = shaderFunction;
  3446. }
  3447. else
  3448. {
  3449. if( shader != null )
  3450. {
  3451. m_mainGraphInstance.UpdateShaderOnMasterNode( shader );
  3452. if( m_mainGraphInstance.CurrentCanvasMode == NodeAvailability.TemplateShader )
  3453. {
  3454. m_mainGraphInstance.RefreshLinkedMasterNodes();
  3455. m_mainGraphInstance.CurrentMasterNode.OnRefreshLinkedPortsComplete();
  3456. }
  3457. }
  3458. }
  3459. m_mainGraphInstance.LoadedShaderVersion = VersionInfo.FullNumber;
  3460. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  3461. m_mainGraphInstance.IsLoading = false;
  3462. return loadResult;
  3463. }
  3464. public void FullCleanUndoStack()
  3465. {
  3466. Undo.ClearUndo( this );
  3467. m_mainGraphInstance.FullCleanUndoStack();
  3468. }
  3469. public void FullRegisterOnUndoStack()
  3470. {
  3471. Undo.RegisterCompleteObjectUndo( this, Constants.UndoRegisterFullGrapId );
  3472. m_mainGraphInstance.FullRegisterOnUndoStack();
  3473. }
  3474. public void ShowPortInfo()
  3475. {
  3476. GetWindow<PortLegendInfo>();
  3477. }
  3478. public void ShowShaderLibrary()
  3479. {
  3480. GetWindow<ShaderLibrary>();
  3481. }
  3482. public void ShowMessage( string message, MessageSeverity severity = MessageSeverity.Normal, bool registerTimestamp = true )
  3483. {
  3484. if( UIUtils.InhibitMessages || m_genericMessageUI == null )
  3485. return;
  3486. m_consoleLogWindow.AddMessage( NodeMessageType.Info, message );
  3487. if( m_genericMessageUI.DisplayingMessage )
  3488. {
  3489. m_genericMessageUI.AddToQueue( message, severity );
  3490. }
  3491. else
  3492. {
  3493. if( registerTimestamp )
  3494. m_genericMessageUI.StartMessageCounter();
  3495. ShowMessageImmediately( message, severity );
  3496. }
  3497. }
  3498. public void ShowMessageImmediately( string message, MessageSeverity severity = MessageSeverity.Normal )
  3499. {
  3500. if( UIUtils.InhibitMessages )
  3501. return;
  3502. switch( severity )
  3503. {
  3504. case MessageSeverity.Normal: { m_genericMessageContent.text = string.Empty; } break;
  3505. case MessageSeverity.Warning: { m_genericMessageContent.text = "Warning!\n"; } break;
  3506. case MessageSeverity.Error: { m_genericMessageContent.text = "Error!!!\n"; } break;
  3507. }
  3508. m_genericMessageContent.text += message;
  3509. Debug.Log( message );
  3510. try
  3511. {
  3512. ShowNotification( m_genericMessageContent );
  3513. }
  3514. catch( Exception e )
  3515. {
  3516. Debug.LogException( e );
  3517. }
  3518. }
  3519. public bool MouseInteracted = false;
  3520. void CheckNodeReplacement()
  3521. {
  3522. if( m_replaceMasterNode )
  3523. {
  3524. m_replaceMasterNode = false;
  3525. switch( m_replaceMasterNodeType )
  3526. {
  3527. default:
  3528. case AvailableShaderTypes.SurfaceShader:
  3529. {
  3530. SetStandardShader();
  3531. }
  3532. break;
  3533. case AvailableShaderTypes.Template:
  3534. {
  3535. if( m_replaceMasterNodeDataFromCache )
  3536. {
  3537. TemplateDataParent templateData = m_templatesManager.GetTemplate( m_replaceMasterNodeData );
  3538. m_mainGraphInstance.CrossCheckTemplateNodes( templateData );
  3539. //m_clipboard.GetMultiPassNodesFromClipboard( m_mainGraphInstance.MultiPassMasterNodes.NodesList );
  3540. }
  3541. else
  3542. {
  3543. SetTemplateShader( m_replaceMasterNodeData, false );
  3544. }
  3545. }
  3546. break;
  3547. }
  3548. }
  3549. }
  3550. void OnGUI()
  3551. {
  3552. AmplifyShaderEditorWindow cacheWindow = UIUtils.CurrentWindow;
  3553. UIUtils.CurrentWindow = this;
  3554. if( !m_initialized || (object)UIUtils.MainSkin == null || !UIUtils.Initialized )
  3555. {
  3556. UIUtils.InitMainSkin();
  3557. Init();
  3558. }
  3559. m_currentEvent = Event.current;
  3560. if( m_currentEvent.type == EventType.ExecuteCommand || m_currentEvent.type == EventType.ValidateCommand )
  3561. m_currentCommandName = m_currentEvent.commandName;
  3562. else
  3563. m_currentCommandName = string.Empty;
  3564. System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
  3565. MouseInteracted = false;
  3566. if( m_refreshOnUndo )
  3567. {
  3568. m_refreshOnUndo = false;
  3569. m_mainGraphInstance.RefreshOnUndo();
  3570. }
  3571. if( m_refreshAvailableNodes )
  3572. {
  3573. RefreshAvaibleNodes();
  3574. }
  3575. if( m_previousShaderFunction != CurrentGraph.CurrentShaderFunction )
  3576. {
  3577. m_nodeParametersWindow.ForceUpdate = true;
  3578. m_previousShaderFunction = CurrentGraph.CurrentShaderFunction;
  3579. }
  3580. if( m_nodeToFocus != null && m_currentEvent.type == EventType.Layout )
  3581. {
  3582. FocusOnNode( m_nodeToFocus, m_zoomToFocus, m_selectNodeToFocus );
  3583. m_nodeToFocus = null;
  3584. }
  3585. m_mainGraphInstance.OnDuplicateEventWrapper();
  3586. m_currentInactiveTime = CalculateInactivityTime();
  3587. if( m_nodeParametersWindow != null && m_innerEditorVariables.NodeParametersMaximized!= m_nodeParametersWindow.IsMaximized )
  3588. m_innerEditorVariables.NodeParametersMaximized = m_nodeParametersWindow.IsMaximized;
  3589. if( m_paletteWindow != null && m_innerEditorVariables.NodePaletteMaximized != m_paletteWindow.IsMaximized )
  3590. m_innerEditorVariables.NodePaletteMaximized = m_paletteWindow.IsMaximized;
  3591. if( m_checkInvalidConnections )
  3592. {
  3593. m_checkInvalidConnections = false;
  3594. m_mainGraphInstance.DeleteInvalidConnections();
  3595. }
  3596. //if ( m_repaintIsDirty )
  3597. //{
  3598. // m_repaintIsDirty = false;
  3599. // ForceRepaint();
  3600. //}
  3601. if( m_forcingMaterialUpdateFlag )
  3602. {
  3603. Focus();
  3604. if( m_materialsToUpdate.Count > 0 )
  3605. {
  3606. float percentage = 100.0f * (float)( UIUtils.TotalExampleMaterials - m_materialsToUpdate.Count ) / (float)UIUtils.TotalExampleMaterials;
  3607. if( m_forcingMaterialUpdateOp ) // Read
  3608. {
  3609. Debug.Log( percentage + "% Recompiling " + m_materialsToUpdate[ 0 ].name );
  3610. LoadDroppedObject( true, m_materialsToUpdate[ 0 ].shader, m_materialsToUpdate[ 0 ] );
  3611. }
  3612. else // Write
  3613. {
  3614. Debug.Log( percentage + "% Saving " + m_materialsToUpdate[ 0 ].name );
  3615. SaveToDisk( false );
  3616. m_materialsToUpdate.RemoveAt( 0 );
  3617. }
  3618. m_forcingMaterialUpdateOp = !m_forcingMaterialUpdateOp;
  3619. }
  3620. else
  3621. {
  3622. Debug.Log( "100% - All Materials compiled " );
  3623. m_forcingMaterialUpdateFlag = false;
  3624. }
  3625. }
  3626. if( m_removedKeyboardFocus )
  3627. {
  3628. m_removedKeyboardFocus = false;
  3629. GUIUtility.keyboardControl = 0;
  3630. }
  3631. Vector2 pos = m_currentEvent.mousePosition;
  3632. pos.x += position.x;
  3633. pos.y += position.y;
  3634. m_insideEditorWindow = position.Contains( pos );
  3635. if( m_delayedLoadObject != null && m_mainGraphInstance.CurrentMasterNode != null )
  3636. {
  3637. LoadObject( m_delayedLoadObject );
  3638. m_delayedLoadObject = null;
  3639. }
  3640. else if( m_delayedLoadObject != null && m_mainGraphInstance.CurrentOutputNode != null )
  3641. {
  3642. LoadObject( m_delayedLoadObject );
  3643. m_delayedLoadObject = null;
  3644. }
  3645. if( m_delayedMaterialSet != null && m_mainGraphInstance.CurrentMasterNode != null )
  3646. {
  3647. m_mainGraphInstance.UpdateMaterialOnMasterNode( m_delayedMaterialSet );
  3648. m_mainGraphInstance.SetMaterialModeOnGraph( m_delayedMaterialSet );
  3649. CurrentSelection = ASESelectionMode.Material;
  3650. IsShaderFunctionWindow = false;
  3651. m_delayedMaterialSet = null;
  3652. }
  3653. Material currentMaterial = m_mainGraphInstance.CurrentMaterial;
  3654. if( m_forceUpdateFromMaterialFlag )
  3655. {
  3656. Focus();
  3657. m_forceUpdateFromMaterialFlag = false;
  3658. if( currentMaterial != null )
  3659. {
  3660. m_mainGraphInstance.CopyValuesFromMaterial( currentMaterial );
  3661. m_repaintIsDirty = true;
  3662. }
  3663. }
  3664. m_repaintCount = 0;
  3665. m_cameraInfo = position;
  3666. //if( m_currentEvent.type == EventType.keyDown )
  3667. if( m_currentEvent.type == EventType.Repaint )
  3668. m_keyEvtMousePos2D = m_currentEvent.mousePosition;
  3669. m_currentMousePos2D = m_currentEvent.mousePosition;
  3670. m_currentMousePos.x = m_currentMousePos2D.x;
  3671. m_currentMousePos.y = m_currentMousePos2D.y;
  3672. m_graphArea.width = m_cameraInfo.width;
  3673. m_graphArea.height = m_cameraInfo.height;
  3674. m_autoPanDirActive = m_lmbPressed || m_forceAutoPanDir || m_multipleSelectionActive || m_wireReferenceUtils.ValidReferences();
  3675. // Need to use it in order to prevent Mismatched LayoutGroup on ValidateCommand when rendering nodes
  3676. //if( Event.current.type == EventType.ValidateCommand )
  3677. //{
  3678. // Event.current.Use();
  3679. //}
  3680. // Nodes Graph background area
  3681. //GUILayout.BeginArea( m_graphArea, "Nodes" );
  3682. {
  3683. // Camera movement is simulated by grabing the current camera offset, transforming it into texture space and manipulating the tiled texture uv coords
  3684. GUI.DrawTextureWithTexCoords( m_graphArea, m_graphBgTexture,
  3685. new Rect( ( -m_cameraOffset.x / m_graphBgTexture.width ),
  3686. ( m_cameraOffset.y / m_graphBgTexture.height ) - m_cameraZoom * m_cameraInfo.height / m_graphBgTexture.height,
  3687. m_cameraZoom * m_cameraInfo.width / m_graphBgTexture.width,
  3688. m_cameraZoom * m_cameraInfo.height / m_graphBgTexture.height ) );
  3689. Color col = GUI.color;
  3690. GUI.color = new Color( 1, 1, 1, 0.7f );
  3691. GUI.DrawTexture( m_graphArea, m_graphFgTexture, ScaleMode.StretchToFill, true );
  3692. GUI.color = col;
  3693. }
  3694. //GUILayout.EndArea();
  3695. bool restoreMouse = false;
  3696. if( InsideMenus( m_currentMousePos2D ) /*|| _confirmationWindow.IsActive*/ )
  3697. {
  3698. if( Event.current.type == EventType.MouseDown )
  3699. {
  3700. restoreMouse = true;
  3701. Event.current.type = EventType.Ignore;
  3702. }
  3703. // Must guarantee that mouse up ops on menus will reset auto pan if it is set
  3704. if( m_currentEvent.type == EventType.MouseUp && m_currentEvent.button == ButtonClickId.LeftMouseButton )
  3705. {
  3706. m_lmbPressed = false;
  3707. }
  3708. }
  3709. // Nodes
  3710. //GUILayout.BeginArea( m_graphArea );
  3711. {
  3712. m_drawInfo.CameraArea = m_cameraInfo;
  3713. m_drawInfo.TransformedCameraArea = m_graphArea;
  3714. m_drawInfo.MousePosition = m_currentMousePos2D;
  3715. m_drawInfo.CameraOffset = m_cameraOffset;
  3716. m_drawInfo.InvertedZoom = 1 / m_cameraZoom;
  3717. m_drawInfo.LeftMouseButtonPressed = m_currentEvent.button == ButtonClickId.LeftMouseButton;
  3718. m_drawInfo.CurrentEventType = m_currentEvent.type;
  3719. m_drawInfo.ZoomChanged = m_zoomChanged;
  3720. m_drawInfo.TransformedMousePos = m_currentMousePos2D * m_cameraZoom - m_cameraOffset;
  3721. if( m_drawInfo.CurrentEventType == EventType.Repaint )
  3722. UIUtils.UpdateMainSkin( m_drawInfo );
  3723. // Draw mode indicator
  3724. m_modeWindow.Draw( m_graphArea, m_currentMousePos2D, m_mainGraphInstance.CurrentShader, currentMaterial,
  3725. 0.5f * ( m_graphArea.width - m_paletteWindow.RealWidth - m_nodeParametersWindow.RealWidth ),
  3726. ( m_nodeParametersWindow.IsMaximized ? m_nodeParametersWindow.RealWidth : 0 ),
  3727. ( m_paletteWindow.IsMaximized ? m_paletteWindow.RealWidth : 0 )/*, m_openedAssetFromNode*/ );
  3728. PreTestLeftMouseDown();
  3729. //m_mainGraphInstance.DrawBezierBoundingBox();
  3730. //CheckNodeReplacement();
  3731. // Main Graph Draw
  3732. m_repaintIsDirty = m_mainGraphInstance.Draw( m_drawInfo ) || m_repaintIsDirty;
  3733. m_mainGraphInstance.DrawGrid( m_drawInfo );
  3734. bool hasUnusedConnNodes = m_mainGraphInstance.HasUnConnectedNodes;
  3735. m_toolsWindow.SetStateOnButton( ToolButtonType.CleanUnusedNodes, hasUnusedConnNodes ? 1 : 0 );
  3736. m_zoomChanged = false;
  3737. MasterNode masterNode = m_mainGraphInstance.CurrentMasterNode;
  3738. if( masterNode != null )
  3739. {
  3740. m_toolsWindow.DrawShaderTitle( m_nodeParametersWindow, m_paletteWindow, AvailableCanvasWidth, m_graphArea.height, masterNode.CroppedShaderName );
  3741. }
  3742. else if( m_mainGraphInstance.CurrentOutputNode != null )
  3743. {
  3744. string functionName = string.Empty;
  3745. if( m_mainGraphInstance.CurrentShaderFunction != null )
  3746. functionName = m_mainGraphInstance.CurrentShaderFunction.FunctionName;
  3747. m_toolsWindow.DrawShaderTitle( m_nodeParametersWindow, m_paletteWindow, AvailableCanvasWidth, m_graphArea.height, functionName );
  3748. }
  3749. }
  3750. //GUILayout.EndArea();
  3751. if( restoreMouse )
  3752. {
  3753. Event.current.type = EventType.MouseDown;
  3754. m_drawInfo.CurrentEventType = EventType.MouseDown;
  3755. }
  3756. m_toolsWindow.InitialX = m_nodeParametersWindow.RealWidth;
  3757. m_toolsWindow.Width = m_cameraInfo.width - ( m_nodeParametersWindow.RealWidth + m_paletteWindow.RealWidth );
  3758. m_toolsWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, false );
  3759. m_tipsWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, false );
  3760. bool autoMinimize = false;
  3761. if( position.width < m_lastWindowWidth && position.width < Constants.MINIMIZE_WINDOW_LOCK_SIZE )
  3762. {
  3763. autoMinimize = true;
  3764. }
  3765. if( autoMinimize )
  3766. m_nodeParametersWindow.IsMaximized = false;
  3767. ParentNode selectedNode = ( m_mainGraphInstance.SelectedNodes.Count == 1 ) ? m_mainGraphInstance.SelectedNodes[ 0 ] : m_mainGraphInstance.CurrentMasterNode;
  3768. m_repaintIsDirty = m_nodeParametersWindow.Draw( m_cameraInfo, selectedNode, m_currentMousePos2D, m_currentEvent.button, false ) || m_repaintIsDirty; //TODO: If multiple nodes from the same type are selected also show a parameters window which modifies all of them
  3769. if( m_nodeParametersWindow.IsResizing )
  3770. m_repaintIsDirty = true;
  3771. // Test to ignore mouse on main palette when inside context palette ... IsInside also takes active state into account
  3772. bool ignoreMouseForPalette = m_contextPalette.IsInside( m_currentMousePos2D );
  3773. if( ignoreMouseForPalette && Event.current.type == EventType.MouseDown )
  3774. {
  3775. Event.current.type = EventType.Ignore;
  3776. m_drawInfo.CurrentEventType = EventType.Ignore;
  3777. }
  3778. if( autoMinimize )
  3779. m_paletteWindow.IsMaximized = false;
  3780. m_paletteWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, !m_contextPalette.IsActive );
  3781. if( m_paletteWindow.IsResizing )
  3782. {
  3783. m_repaintIsDirty = true;
  3784. }
  3785. if( ignoreMouseForPalette )
  3786. {
  3787. if( restoreMouse )
  3788. {
  3789. Event.current.type = EventType.MouseDown;
  3790. m_drawInfo.CurrentEventType = EventType.MouseDown;
  3791. }
  3792. }
  3793. if( m_contextPalette.IsActive )
  3794. {
  3795. m_contextPalette.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, m_contextPalette.IsActive );
  3796. }
  3797. if( m_palettePopup.IsActive )
  3798. {
  3799. m_palettePopup.Draw( m_currentMousePos2D );
  3800. m_repaintIsDirty = true;
  3801. int controlID = GUIUtility.GetControlID( FocusType.Passive );
  3802. if( m_currentEvent.GetTypeForControl( controlID ) == EventType.MouseUp )
  3803. {
  3804. if( m_currentEvent.button == ButtonClickId.LeftMouseButton )
  3805. {
  3806. m_palettePopup.Deactivate();
  3807. if( !InsideMenus( m_currentMousePos2D ) )
  3808. {
  3809. ParentNode newNode = CreateNode( m_paletteChosenType, TranformedMousePos, m_paletteChosenFunction );
  3810. //Debug.Log("created menu");
  3811. m_mainGraphInstance.SelectNode( newNode, false, false );
  3812. bool find = false;
  3813. if( newNode is FunctionNode && CurrentGraph.CurrentShaderFunction != null )
  3814. find = SearchFunctionNodeRecursively( CurrentGraph.CurrentShaderFunction );
  3815. if( find )
  3816. {
  3817. DestroyNode( newNode, false );
  3818. ShowMessage( "Shader Function loop detected, new node was removed to prevent errors." );
  3819. }
  3820. else
  3821. {
  3822. newNode.RefreshExternalReferences();
  3823. }
  3824. }
  3825. }
  3826. }
  3827. }
  3828. if( m_consoleLogWindow.IsActive )
  3829. {
  3830. m_consoleLogWindow.InitialX = m_nodeParametersWindow.IsMaximized ? m_nodeParametersWindow.RealWidth : 0;
  3831. m_consoleLogWindow.Width = m_cameraInfo.width - ( ( m_nodeParametersWindow.IsMaximized ? m_nodeParametersWindow.RealWidth : 0 ) + ( m_paletteWindow.IsMaximized ? m_paletteWindow.RealWidth : 0 ) );
  3832. m_consoleLogWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, false );
  3833. }
  3834. // Handle all events ( mouse interaction + others )
  3835. if( !MouseInteracted )
  3836. HandleGUIEvents();
  3837. if( m_currentEvent.type == EventType.Repaint )
  3838. {
  3839. m_mainGraphInstance.UpdateMarkForDeletion();
  3840. }
  3841. // UI Overlay
  3842. // Selection Box
  3843. if( m_multipleSelectionActive )
  3844. {
  3845. UpdateSelectionArea();
  3846. Rect transformedArea = m_multipleSelectionArea;
  3847. transformedArea.position = ( transformedArea.position + m_cameraOffset ) / m_cameraZoom;
  3848. transformedArea.size /= m_cameraZoom;
  3849. if( transformedArea.width < 0 )
  3850. {
  3851. transformedArea.width = -transformedArea.width;
  3852. transformedArea.x -= transformedArea.width;
  3853. }
  3854. if( transformedArea.height < 0 )
  3855. {
  3856. transformedArea.height = -transformedArea.height;
  3857. transformedArea.y -= transformedArea.height;
  3858. }
  3859. Color original = GUI.color;
  3860. GUI.color = Constants.BoxSelectionColor;
  3861. GUI.Label( transformedArea, "", UIUtils.Box );
  3862. GUI.color = original;
  3863. //GUI.backgroundColor = original;
  3864. }
  3865. bool isResizing = m_nodeParametersWindow.IsResizing || m_paletteWindow.IsResizing;
  3866. //Test boundaries for auto-pan
  3867. if( !isResizing && m_autoPanDirActive )
  3868. {
  3869. m_autoPanArea[ (int)AutoPanLocation.LEFT ].AdjustInitialX = m_nodeParametersWindow.IsMaximized ? m_nodeParametersWindow.RealWidth : 0;
  3870. m_autoPanArea[ (int)AutoPanLocation.RIGHT ].AdjustInitialX = m_paletteWindow.IsMaximized ? -m_paletteWindow.RealWidth : 0;
  3871. Vector2 autoPanDir = Vector2.zero;
  3872. for( int i = 0; i < m_autoPanArea.Length; i++ )
  3873. {
  3874. if( m_autoPanArea[ i ].CheckArea( m_currentMousePos2D, m_cameraInfo, false ) )
  3875. {
  3876. autoPanDir += m_autoPanArea[ i ].Velocity;
  3877. }
  3878. }
  3879. m_cameraOffset += autoPanDir;
  3880. if( !m_wireReferenceUtils.ValidReferences() && m_insideEditorWindow && !m_altBoxSelection )
  3881. {
  3882. m_mainGraphInstance.MoveSelectedNodes( -autoPanDir );
  3883. }
  3884. m_repaintIsDirty = true;
  3885. }
  3886. m_isDirty = m_isDirty || m_mainGraphInstance.IsDirty;
  3887. if( m_isDirty )
  3888. {
  3889. m_isDirty = false;
  3890. //ShaderIsModified = true;
  3891. EditorUtility.SetDirty( this );
  3892. }
  3893. m_saveIsDirty = m_saveIsDirty || m_mainGraphInstance.SaveIsDirty;
  3894. if( m_liveShaderEditing )
  3895. {
  3896. if( m_saveIsDirty )
  3897. {
  3898. if( m_liveShaderEditing && focusedWindow && m_currentInactiveTime > InactivitySaveTime )
  3899. {
  3900. m_saveIsDirty = false;
  3901. if( m_mainGraphInstance.CurrentMasterNodeId != Constants.INVALID_NODE_ID )
  3902. {
  3903. SaveToDisk( true );
  3904. }
  3905. else
  3906. {
  3907. ShowMessage( LiveShaderError );
  3908. }
  3909. }
  3910. }
  3911. }
  3912. else if( m_saveIsDirty )
  3913. {
  3914. ShaderIsModified = true;
  3915. m_saveIsDirty = false;
  3916. }
  3917. if( m_onLoadDone > 0 )
  3918. {
  3919. m_onLoadDone--;
  3920. if( m_onLoadDone == 0 )
  3921. {
  3922. ShaderIsModified = false;
  3923. }
  3924. }
  3925. if( m_repaintIsDirty )
  3926. {
  3927. m_repaintIsDirty = false;
  3928. Repaint();
  3929. //ForceRepaint();
  3930. }
  3931. if( m_cacheSaveOp )
  3932. {
  3933. if( ( EditorApplication.timeSinceStartup - m_lastTimeSaved ) > SaveTime )
  3934. {
  3935. SaveToDisk( false );
  3936. }
  3937. }
  3938. m_genericMessageUI.CheckForMessages();
  3939. if( m_ctrlSCallback )
  3940. {
  3941. m_ctrlSCallback = false;
  3942. OnToolButtonPressed( ToolButtonType.Update );
  3943. }
  3944. m_lastWindowWidth = position.width;
  3945. m_nodeExporterUtils.Update();
  3946. if( m_markedToSave )
  3947. {
  3948. m_markedToSave = false;
  3949. SaveToDisk( false );
  3950. }
  3951. if( m_performFullUndoRegister )
  3952. {
  3953. m_performFullUndoRegister = false;
  3954. FullRegisterOnUndoStack();
  3955. }
  3956. if( CheckFunctions )
  3957. CheckFunctions = false;
  3958. System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
  3959. UIUtils.CurrentWindow = cacheWindow;
  3960. if( !m_nodesLoadedCorrectly )
  3961. {
  3962. try
  3963. {
  3964. ShowNotification( NodesExceptionMessage );
  3965. }
  3966. catch( Exception e )
  3967. {
  3968. Debug.LogException( e );
  3969. }
  3970. }
  3971. CheckNodeReplacement();
  3972. }
  3973. void OnInspectorUpdate()
  3974. {
  3975. if( m_afterDeserializeFlag )
  3976. {
  3977. m_afterDeserializeFlag = false;
  3978. //m_mainGraphInstance.ParentWindow = this;
  3979. }
  3980. if( IsShaderFunctionWindow && CurrentGraph.CurrentShaderFunction == null )
  3981. {
  3982. Close();
  3983. }
  3984. }
  3985. public void SetCtrlSCallback( bool imediate )
  3986. {
  3987. //MasterNode node = _mainGraphInstance.CurrentMasterNode;
  3988. if( /*node != null && node.CurrentShader != null && */m_shaderIsModified )
  3989. {
  3990. if( imediate )
  3991. {
  3992. OnToolButtonPressed( ToolButtonType.Update );
  3993. }
  3994. else
  3995. {
  3996. m_ctrlSCallback = true;
  3997. }
  3998. }
  3999. }
  4000. public void SetSaveIsDirty()
  4001. {
  4002. m_saveIsDirty = true && UIUtils.DirtyMask;
  4003. }
  4004. public void OnPaletteNodeCreate( System.Type type, string name, AmplifyShaderFunction function )
  4005. {
  4006. m_mainGraphInstance.DeSelectAll();
  4007. m_paletteChosenType = type;
  4008. m_paletteChosenFunction = function;
  4009. m_palettePopup.Activate( name );
  4010. }
  4011. public void OnContextPaletteNodeCreate( System.Type type, string name, AmplifyShaderFunction function )
  4012. {
  4013. m_mainGraphInstance.DeSelectAll();
  4014. ParentNode newNode = CreateNode( type, m_contextPalette.StartDropPosition * m_cameraZoom - m_cameraOffset, function );
  4015. //Debug.Log( "created context" );
  4016. m_mainGraphInstance.SelectNode( newNode, false, false );
  4017. bool find = false;
  4018. if( newNode is FunctionNode && CurrentGraph.CurrentShaderFunction != null )
  4019. find = SearchFunctionNodeRecursively( CurrentGraph.CurrentShaderFunction );
  4020. if( find )
  4021. {
  4022. DestroyNode( newNode, false );
  4023. ShowMessage( "Shader Function loop detected, new node was removed to prevent errors." );
  4024. }
  4025. else
  4026. {
  4027. newNode.RefreshExternalReferences();
  4028. }
  4029. }
  4030. void OnNodeStoppedMovingEvent( ParentNode node )
  4031. {
  4032. CheckZoomBoundaries( node.Vec2Position );
  4033. //ShaderIsModified = true;
  4034. }
  4035. void OnRefreshFunctionNodeEvent( FunctionNode node )
  4036. {
  4037. Debug.Log( node );
  4038. }
  4039. void OnMaterialUpdated( MasterNode masterNode )
  4040. {
  4041. if( masterNode != null )
  4042. {
  4043. if( masterNode.CurrentMaterial )
  4044. {
  4045. m_toolsWindow.SetStateOnButton( ToolButtonType.Update, ShaderIsModified ? 0 : 2, ShaderIsModified ? "Click to update Shader preview." : "Preview up-to-date." );
  4046. }
  4047. else
  4048. {
  4049. m_toolsWindow.SetStateOnButton( ToolButtonType.Update, 1, "Set an active Material in the Master Node." );
  4050. }
  4051. UpdateLiveUI();
  4052. }
  4053. else
  4054. {
  4055. m_toolsWindow.SetStateOnButton( ToolButtonType.Update, 1, "Set an active Material in the Master Node." );
  4056. }
  4057. }
  4058. void OnShaderUpdated( MasterNode masterNode )
  4059. {
  4060. m_toolsWindow.SetStateOnButton( ToolButtonType.OpenSourceCode, masterNode.CurrentShader != null ? 1 : 0 );
  4061. }
  4062. public void CheckZoomBoundaries( Vector2 newPosition )
  4063. {
  4064. if( newPosition.x < m_minNodePos.x )
  4065. {
  4066. m_minNodePos.x = newPosition.x;
  4067. }
  4068. else if( newPosition.x > m_maxNodePos.x )
  4069. {
  4070. m_maxNodePos.x = newPosition.x;
  4071. }
  4072. if( newPosition.y < m_minNodePos.y )
  4073. {
  4074. m_minNodePos.y = newPosition.y;
  4075. }
  4076. else if( newPosition.y > m_maxNodePos.y )
  4077. {
  4078. m_maxNodePos.y = newPosition.y;
  4079. }
  4080. }
  4081. public void DestroyNode( ParentNode node, bool registerUndo = true ) { m_mainGraphInstance.DestroyNode( node, registerUndo ); }
  4082. public ParentNode CreateNode( System.Type type, Vector2 position, AmplifyShaderFunction function = null, bool selectNode = true )
  4083. {
  4084. ParentNode node;
  4085. if( function == null )
  4086. node = m_mainGraphInstance.CreateNode( type, true );
  4087. else
  4088. node = m_mainGraphInstance.CreateNode( function, true );
  4089. Vector2 newPosition = position;
  4090. node.Vec2Position = newPosition;
  4091. CheckZoomBoundaries( newPosition );
  4092. // Connect node if a wire is active
  4093. if( m_wireReferenceUtils.ValidReferences() )
  4094. {
  4095. if( m_wireReferenceUtils.InputPortReference.IsValid )
  4096. {
  4097. ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.InputPortReference.NodeId );
  4098. InputPort originPort = originNode.GetInputPortByUniqueId( m_wireReferenceUtils.InputPortReference.PortId );
  4099. OutputPort outputPort = node.GetFirstOutputPortOfType( m_wireReferenceUtils.InputPortReference.DataType, true );
  4100. if( outputPort != null && originPort.CheckValidType( outputPort.DataType ) && ( !m_wireReferenceUtils.InputPortReference.TypeLocked ||
  4101. m_wireReferenceUtils.InputPortReference.DataType == WirePortDataType.OBJECT ||
  4102. ( m_wireReferenceUtils.InputPortReference.TypeLocked && outputPort.DataType == m_wireReferenceUtils.InputPortReference.DataType ) ) )
  4103. {
  4104. //link output to input
  4105. if( outputPort.ConnectTo( m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId, m_wireReferenceUtils.InputPortReference.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) )
  4106. node.OnOutputPortConnected( outputPort.PortId, m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId );
  4107. //link input to output
  4108. if( originNode.GetInputPortByUniqueId( m_wireReferenceUtils.InputPortReference.PortId ).ConnectTo( outputPort.NodeId, outputPort.PortId, m_wireReferenceUtils.InputPortReference.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) )
  4109. originNode.OnInputPortConnected( m_wireReferenceUtils.InputPortReference.PortId, node.UniqueId, outputPort.PortId );
  4110. }
  4111. }
  4112. if( m_wireReferenceUtils.OutputPortReference.IsValid )
  4113. {
  4114. ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.OutputPortReference.NodeId );
  4115. InputPort inputPort = node.GetFirstInputPortOfType( m_wireReferenceUtils.OutputPortReference.DataType, true );
  4116. if( inputPort != null && ( !inputPort.TypeLocked ||
  4117. inputPort.DataType == WirePortDataType.OBJECT ||
  4118. ( inputPort.TypeLocked && inputPort.DataType == m_wireReferenceUtils.OutputPortReference.DataType ) ) )
  4119. {
  4120. inputPort.InvalidateAllConnections();
  4121. //link input to output
  4122. if( inputPort.ConnectTo( m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId, m_wireReferenceUtils.OutputPortReference.DataType, inputPort.TypeLocked ) )
  4123. node.OnInputPortConnected( inputPort.PortId, m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId );
  4124. //link output to input
  4125. if( originNode.GetOutputPortByUniqueId( m_wireReferenceUtils.OutputPortReference.PortId ).ConnectTo( inputPort.NodeId, inputPort.PortId, m_wireReferenceUtils.OutputPortReference.DataType, inputPort.TypeLocked ) )
  4126. originNode.OnOutputPortConnected( m_wireReferenceUtils.OutputPortReference.PortId, node.UniqueId, inputPort.PortId );
  4127. }
  4128. }
  4129. m_wireReferenceUtils.InvalidateReferences();
  4130. //for ( int i = 0; i < m_mainGraphInstance.VisibleNodes.Count; i++ )
  4131. //{
  4132. // m_mainGraphInstance.VisibleNodes[ i ].OnNodeInteraction( node );
  4133. //}
  4134. }
  4135. if( selectNode )
  4136. m_mainGraphInstance.SelectNode( node, false, false );
  4137. //_repaintIsDirty = true
  4138. SetSaveIsDirty();
  4139. ForceRepaint();
  4140. return node;
  4141. }
  4142. public void UpdateTime()
  4143. {
  4144. if( UIUtils.CurrentWindow != this )
  4145. return;
  4146. double deltaTime = Time.realtimeSinceStartup - m_time;
  4147. m_time = Time.realtimeSinceStartup;
  4148. if( m_smoothZoom )
  4149. {
  4150. if( Mathf.Abs( m_targetZoom - m_cameraZoom ) < 0.001f )
  4151. {
  4152. m_smoothZoom = false;
  4153. m_cameraZoom = m_targetZoom;
  4154. m_zoomTime = 0;
  4155. }
  4156. else
  4157. {
  4158. m_zoomTime += deltaTime;
  4159. Vector2 canvasPos = m_zoomPivot * m_cameraZoom;
  4160. m_cameraZoom = Mathf.SmoothDamp( m_cameraZoom, m_targetZoom, ref m_zoomVelocity, 0.1f, 10000, (float)deltaTime * 1.5f );
  4161. canvasPos = canvasPos - m_zoomPivot * m_cameraZoom;
  4162. m_cameraOffset = m_cameraOffset - canvasPos;
  4163. m_targetOffset = m_targetOffset - canvasPos;
  4164. }
  4165. }
  4166. if( m_smoothOffset )
  4167. {
  4168. if( ( m_targetOffset - m_cameraOffset ).SqrMagnitude() < 1f )
  4169. {
  4170. m_smoothOffset = false;
  4171. m_offsetTime = 0;
  4172. }
  4173. else
  4174. {
  4175. m_offsetTime += deltaTime;
  4176. m_cameraOffset = Vector2.SmoothDamp( m_cameraOffset, m_targetOffset, ref m_camVelocity, 0.1f, 100000, (float)deltaTime * 1.5f );
  4177. }
  4178. }
  4179. if( m_cachedEditorTimeId == -1 )
  4180. m_cachedEditorTimeId = Shader.PropertyToID( "_EditorTime" );
  4181. if( m_cachedEditorDeltaTimeId == -1 )
  4182. m_cachedEditorDeltaTimeId = Shader.PropertyToID( "_EditorDeltaTime" );
  4183. //Update Game View?
  4184. //Shader.SetGlobalVector( "_Time", new Vector4( Time.realtimeSinceStartup / 20, Time.realtimeSinceStartup, Time.realtimeSinceStartup * 2, Time.realtimeSinceStartup * 3 ) );
  4185. //System.Type T = System.Type.GetType( "UnityEditor.GameView,UnityEditor" );
  4186. //UnityEngine.Object[] array = Resources.FindObjectsOfTypeAll( T );
  4187. //EditorWindow gameView = ( array.Length <= 0 ) ? null : ( ( EditorWindow ) array[ 0 ] );
  4188. //gameView.Repaint();
  4189. if( RenderSettings.sun != null )
  4190. {
  4191. Vector3 lightdir = -RenderSettings.sun.transform.forward;//.rotation.eulerAngles;
  4192. Shader.SetGlobalVector( "_EditorWorldLightPos", new Vector4( lightdir.x, lightdir.y, lightdir.z, 0 ) );
  4193. Shader.SetGlobalColor( "_EditorLightColor", RenderSettings.sun.color.linear );
  4194. }
  4195. Shader.SetGlobalFloat( "_EditorTime", (float)m_time );
  4196. Shader.SetGlobalFloat( "_EditorDeltaTime", (float)deltaTime );
  4197. }
  4198. public void UpdateNodePreviewList()
  4199. {
  4200. if( UIUtils.CurrentWindow != this )
  4201. return;
  4202. UIUtils.CheckNullMaterials();
  4203. for( int i = 0; i < CurrentGraph.AllNodes.Count; i++ )
  4204. {
  4205. ParentNode node = CurrentGraph.AllNodes[ i ];
  4206. if( node != null )
  4207. {
  4208. node.RenderNodePreview();
  4209. }
  4210. }
  4211. Repaint();
  4212. }
  4213. public void ForceRepaint()
  4214. {
  4215. m_repaintCount += 1;
  4216. m_repaintIsDirty = true;
  4217. //Repaint();
  4218. }
  4219. public void ForceUpdateFromMaterial() { m_forceUpdateFromMaterialFlag = true; }
  4220. void UseCurrentEvent()
  4221. {
  4222. m_currentEvent.Use();
  4223. }
  4224. public void OnBeforeSerialize()
  4225. {
  4226. //if ( !UIUtils.SerializeFromUndo() )
  4227. //{
  4228. // m_mainGraphInstance.DeSelectAll();
  4229. //}
  4230. if( DebugConsoleWindow.UseShaderPanelsInfo )
  4231. {
  4232. if( m_nodeParametersWindow != null )
  4233. m_nodeParametersWindowMaximized = m_nodeParametersWindow.IsMaximized;
  4234. if( m_paletteWindow != null )
  4235. m_paletteWindowMaximized = m_paletteWindow.IsMaximized;
  4236. }
  4237. }
  4238. public void OnAfterDeserialize()
  4239. {
  4240. m_afterDeserializeFlag = true;
  4241. //m_customGraph = null;
  4242. if( DebugConsoleWindow.UseShaderPanelsInfo )
  4243. {
  4244. if( m_nodeParametersWindow != null )
  4245. m_nodeParametersWindow.IsMaximized = m_nodeParametersWindowMaximized;
  4246. if( m_paletteWindow != null )
  4247. m_paletteWindow.IsMaximized = m_paletteWindowMaximized;
  4248. }
  4249. }
  4250. void OnDestroy()
  4251. {
  4252. m_ctrlSCallback = false;
  4253. Destroy();
  4254. }
  4255. public override void OnDisable()
  4256. {
  4257. base.OnDisable();
  4258. m_ctrlSCallback = false;
  4259. EditorApplication.update -= UpdateTime;
  4260. EditorApplication.update -= UpdateNodePreviewList;
  4261. EditorApplication.update -= IOUtils.UpdateIO;
  4262. for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ )
  4263. {
  4264. if( IOUtils.AllOpenedWindows[ i ] != this )
  4265. {
  4266. EditorApplication.update += IOUtils.UpdateIO;
  4267. break;
  4268. }
  4269. }
  4270. }
  4271. void OnEmptyGraphDetected( ParentGraph graph )
  4272. {
  4273. if( m_delayedLoadObject != null )
  4274. {
  4275. LoadObject( m_delayedLoadObject );
  4276. m_delayedLoadObject = null;
  4277. Repaint();
  4278. }
  4279. else
  4280. {
  4281. if( !string.IsNullOrEmpty( Lastpath ) )
  4282. {
  4283. Shader shader = AssetDatabase.LoadAssetAtPath<Shader>( Lastpath );
  4284. if( shader == null )
  4285. {
  4286. Material material = AssetDatabase.LoadAssetAtPath<Material>( Lastpath );
  4287. if( material != null )
  4288. {
  4289. LoadDroppedObject( true, material.shader, material, null );
  4290. }
  4291. else
  4292. {
  4293. AmplifyShaderFunction function = AssetDatabase.LoadAssetAtPath<AmplifyShaderFunction>( Lastpath );
  4294. if( function != null )
  4295. {
  4296. LoadDroppedObject( true, null, null, function );
  4297. }
  4298. }
  4299. }
  4300. else
  4301. {
  4302. LoadDroppedObject( true, shader, null, null );
  4303. }
  4304. Repaint();
  4305. }
  4306. }
  4307. }
  4308. public void ForceMaterialsToUpdate( ref Dictionary<string, string> availableMaterials )
  4309. {
  4310. m_forcingMaterialUpdateOp = true;
  4311. m_forcingMaterialUpdateFlag = true;
  4312. m_materialsToUpdate.Clear();
  4313. foreach( KeyValuePair<string, string> kvp in availableMaterials )
  4314. {
  4315. Material material = AssetDatabase.LoadAssetAtPath<Material>( AssetDatabase.GUIDToAssetPath( kvp.Value ) );
  4316. if( material != null )
  4317. {
  4318. m_materialsToUpdate.Add( material );
  4319. }
  4320. }
  4321. }
  4322. public void ReplaceMasterNode( MasterNodeCategoriesData data, bool cacheMasterNodes )
  4323. {
  4324. m_replaceMasterNodeType = data.Category;
  4325. m_replaceMasterNode = true;
  4326. m_replaceMasterNodeData = data.Name;
  4327. m_replaceMasterNodeDataFromCache = cacheMasterNodes;
  4328. if( cacheMasterNodes )
  4329. {
  4330. m_clipboard.AddMultiPassNodesToClipboard( m_mainGraphInstance.MultiPassMasterNodes.NodesList );
  4331. }
  4332. }
  4333. public Vector2 TranformPosition( Vector2 pos )
  4334. {
  4335. return pos * m_cameraZoom - m_cameraOffset;
  4336. }
  4337. public void UpdateTabTitle()
  4338. {
  4339. if( m_isShaderFunctionWindow )
  4340. {
  4341. if( m_openedShaderFunction != null )
  4342. {
  4343. this.titleContent.text = GenerateTabTitle( m_openedShaderFunction.FunctionName );
  4344. }
  4345. }
  4346. else
  4347. {
  4348. if( m_selectionMode == ASESelectionMode.Material )
  4349. {
  4350. this.titleContent.text = GenerateTabTitle( m_mainGraphInstance.CurrentMaterial.name );
  4351. }
  4352. else
  4353. {
  4354. this.titleContent.text = GenerateTabTitle( m_mainGraphInstance.CurrentShader.name );
  4355. }
  4356. }
  4357. }
  4358. public ParentGraph CustomGraph
  4359. {
  4360. get { return m_customGraph; }
  4361. set { m_customGraph = value; }
  4362. }
  4363. public ParentGraph CurrentGraph
  4364. {
  4365. get
  4366. {
  4367. if( m_customGraph != null )
  4368. return m_customGraph;
  4369. return m_mainGraphInstance;
  4370. }
  4371. }
  4372. public void RefreshAvaibleNodes()
  4373. {
  4374. if( m_contextMenu != null && m_mainGraphInstance != null )
  4375. {
  4376. m_contextMenu.RefreshNodes( m_mainGraphInstance );
  4377. m_paletteWindow.ForceUpdate = true;
  4378. m_contextPalette.ForceUpdate = true;
  4379. m_refreshAvailableNodes = false;
  4380. }
  4381. }
  4382. public void LateRefreshAvailableNodes()
  4383. {
  4384. m_refreshAvailableNodes = true;
  4385. }
  4386. public ParentGraph OutsideGraph { get { return m_mainGraphInstance; } }
  4387. public bool ShaderIsModified
  4388. {
  4389. get { return m_shaderIsModified; }
  4390. set
  4391. {
  4392. m_shaderIsModified = value && UIUtils.DirtyMask;
  4393. m_toolsWindow.SetStateOnButton( ToolButtonType.Save, m_shaderIsModified ? 1 : 0 );
  4394. if( !IsShaderFunctionWindow )
  4395. {
  4396. MasterNode masterNode = m_mainGraphInstance.CurrentMasterNode;
  4397. if( masterNode != null && masterNode.CurrentShader != null )
  4398. {
  4399. m_toolsWindow.SetStateOnButton( ToolButtonType.Update, m_shaderIsModified ? 0 : 2 );
  4400. UpdateTabTitle( masterNode.ShaderName, m_shaderIsModified );
  4401. }
  4402. else
  4403. {
  4404. m_toolsWindow.SetStateOnButton( ToolButtonType.Update, 1 );
  4405. }
  4406. //if( m_mainGraphInstance.CurrentStandardSurface != null )
  4407. // UpdateTabTitle( m_mainGraphInstance.CurrentStandardSurface.ShaderName, m_shaderIsModified );
  4408. }
  4409. else
  4410. {
  4411. m_toolsWindow.SetStateOnButton( ToolButtonType.Update, m_shaderIsModified ? 0 : 2 );
  4412. if( m_mainGraphInstance.CurrentShaderFunction != null )
  4413. UpdateTabTitle( m_mainGraphInstance.CurrentShaderFunction.FunctionName, m_shaderIsModified );
  4414. }
  4415. }
  4416. }
  4417. public void MarkToRepaint() { m_repaintIsDirty = true; }
  4418. public void RequestSave() { m_markedToSave = true; }
  4419. public void RequestRepaint() { m_repaintIsDirty = true; }
  4420. public OptionsWindow Options { get { return m_optionsWindow; } }
  4421. public GraphContextMenu ContextMenuInstance { get { return m_contextMenu; } set { m_contextMenu = value; } }
  4422. public ShortcutsManager ShortcutManagerInstance { get { return m_shortcutManager; } }
  4423. public bool GlobalPreview
  4424. {
  4425. get { return m_globalPreview; }
  4426. set { m_globalPreview = value; }
  4427. }
  4428. public bool GlobalShowInternalData
  4429. {
  4430. get { return m_globalShowInternalData; }
  4431. set { m_globalShowInternalData = value; }
  4432. }
  4433. public double EditorTime
  4434. {
  4435. get { return m_time; }
  4436. set { m_time = value; }
  4437. }
  4438. public ASESelectionMode CurrentSelection
  4439. {
  4440. get { return m_selectionMode; }
  4441. set
  4442. {
  4443. m_selectionMode = value;
  4444. switch( m_selectionMode )
  4445. {
  4446. default:
  4447. case ASESelectionMode.Shader:
  4448. {
  4449. m_toolsWindow.BorderStyle = UIUtils.GetCustomStyle( CustomStyle.ShaderBorder );
  4450. }
  4451. break;
  4452. case ASESelectionMode.Material:
  4453. {
  4454. m_toolsWindow.BorderStyle = UIUtils.GetCustomStyle( CustomStyle.MaterialBorder );
  4455. }
  4456. break;
  4457. case ASESelectionMode.ShaderFunction:
  4458. {
  4459. m_toolsWindow.BorderStyle = UIUtils.GetCustomStyle( CustomStyle.ShaderFunctionBorder );
  4460. }
  4461. break;
  4462. }
  4463. }
  4464. }
  4465. public bool LiveShaderEditing
  4466. {
  4467. get { return m_liveShaderEditing; }
  4468. set
  4469. {
  4470. m_liveShaderEditing = value;
  4471. m_innerEditorVariables.LiveMode = m_liveShaderEditing;
  4472. UpdateLiveUI();
  4473. }
  4474. }
  4475. public NodeAvailability CurrentNodeAvailability
  4476. {
  4477. get { return m_currentNodeAvailability; }
  4478. set
  4479. {
  4480. NodeAvailability cache = m_currentNodeAvailability;
  4481. m_currentNodeAvailability = value;
  4482. if( cache != value )
  4483. RefreshAvaibleNodes();
  4484. }
  4485. }
  4486. public void InvalidateAlt() { m_altAvailable = false; }
  4487. public PaletteWindow CurrentPaletteWindow { get { return m_paletteWindow; } }
  4488. public PreMadeShaders PreMadeShadersInstance { get { return m_preMadeShaders; } }
  4489. public Rect CameraInfo { get { return m_cameraInfo; } }
  4490. public Vector2 TranformedMousePos { get { return m_currentMousePos2D * m_cameraZoom - m_cameraOffset; } }
  4491. public Vector2 TranformedKeyEvtMousePos { get { return m_keyEvtMousePos2D * m_cameraZoom - m_cameraOffset; } }
  4492. public PalettePopUp PalettePopUpInstance { get { return m_palettePopup; } }
  4493. public DuplicatePreventionBuffer DuplicatePrevBufferInstance { get { return m_duplicatePreventionBuffer; } }
  4494. public NodeParametersWindow ParametersWindow { get { return m_nodeParametersWindow; } }
  4495. public NodeExporterUtils CurrentNodeExporterUtils { get { return m_nodeExporterUtils; } }
  4496. public AmplifyShaderFunction OpenedShaderFunction { get { return m_openedShaderFunction; } }
  4497. public DrawInfo CameraDrawInfo { get { return m_drawInfo; } }
  4498. public string Lastpath { get { return m_lastpath; } set { m_lastpath = value; } }
  4499. public string LastOpenedLocation { get { return m_lastOpenedLocation; } set { m_lastOpenedLocation = value; } }
  4500. public float AvailableCanvasWidth { get { return ( m_cameraInfo.width - m_paletteWindow.RealWidth - m_nodeParametersWindow.RealWidth ); } }
  4501. public float AvailableCanvasHeight { get { return ( m_cameraInfo.height ); } }
  4502. public float CameraZoom { get { return m_cameraZoom; } set { m_cameraZoom = value; m_zoomChanged = true; } }
  4503. public int GraphCount { get { return m_graphCount; } set { m_graphCount = value; } }
  4504. public bool ForceAutoPanDir { get { return m_forceAutoPanDir; } set { m_forceAutoPanDir = value; } }
  4505. public bool OpenedAssetFromNode { get { return m_openedAssetFromNode; } set { m_openedAssetFromNode = value; } }
  4506. public bool IsShaderFunctionWindow { get { return m_isShaderFunctionWindow; } set { m_isShaderFunctionWindow = value; } }
  4507. public bool NodesLoadedCorrectly { get { return m_nodesLoadedCorrectly; } set { m_nodesLoadedCorrectly = value; } }
  4508. public double CurrentInactiveTime { get { return m_currentInactiveTime; } }
  4509. public string ReplaceMasterNodeData { get { return m_replaceMasterNodeData; } }
  4510. public AvailableShaderTypes ReplaceMasterNodeType { get { return m_replaceMasterNodeType; } }
  4511. public NodeWireReferencesUtils WireReferenceUtils { get { return m_wireReferenceUtils; } }
  4512. public ContextPalette WindowContextPallete { get { return m_contextPalette; } }
  4513. // This needs to go to UIUtils
  4514. public Texture2D WireTexture { get { return m_wireTexture; } }
  4515. public Event CurrentEvent { get { return m_currentEvent; } }
  4516. public string CurrentCommandName { get { return m_currentCommandName; } }
  4517. public InnerWindowEditorVariables InnerWindowVariables { get { return m_innerEditorVariables; } }
  4518. public TemplatesManager TemplatesManagerInstance { get { return m_templatesManager; } }
  4519. public Material CurrentMaterial { get { return CurrentGraph.CurrentMaterial; } }
  4520. }
  4521. }