StickyNoteNode.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using System;
  4. using UnityEngine;
  5. using UnityEditor;
  6. namespace AmplifyShaderEditor
  7. {
  8. [Serializable]
  9. [NodeAttributes( "Sticky Note", "Miscellaneous", "Allows adding notes into canvas" )]
  10. public sealed class StickyNoteNode : ParentNode, ISerializationCallbackReceiver
  11. {
  12. private const string WarningText = "Characters $ and @ are NOT allowed inside notes since they are internally used as delimiters over the node meta.\nThey will be automatically removed when saving the shader.";
  13. private const string CommentaryTitle = "Comment";
  14. private const string NoteTitle = "Note Title";
  15. private const float BORDER_SIZE_X = 50;
  16. private const float BORDER_SIZE_Y = 50;
  17. private const float MIN_SIZE_X = 100;
  18. private const float MIN_SIZE_Y = 100;
  19. private const float COMMENTARY_BOX_HEIGHT = 30;
  20. private const float NOTE_AREA_ADJUST = 5;
  21. private readonly Vector2 ResizeButtonPos = new Vector2( 1, 1 );
  22. [SerializeField]
  23. private string m_innerTitleText = "New Note";
  24. [SerializeField]
  25. private string m_titleText = string.Empty;
  26. [SerializeField]
  27. private string m_noteText = string.Empty;
  28. [SerializeField]
  29. private eResizeAxis m_resizeAxis = eResizeAxis.ALL;
  30. [SerializeField]
  31. private Rect m_resizeLeftIconCoords;
  32. [SerializeField]
  33. private Rect m_resizeRightIconCoords;
  34. [SerializeField]
  35. private Rect m_auxHeaderPos;
  36. [SerializeField]
  37. private Rect m_innerTitleArea;
  38. [SerializeField]
  39. private Rect m_noteTextArea;
  40. private Texture2D m_resizeIconTex;
  41. private bool m_isResizingRight = false;
  42. private bool m_isResizingLeft = false;
  43. private Vector2 m_resizeStartPoint = Vector2.zero;
  44. private string m_focusTitleName = "StickyNoteTitleText";
  45. private string m_focusNoteName = "StickyNoteInnerText";
  46. private bool m_focusOnTitle = false;
  47. private bool m_checkCommentText = true;
  48. private bool m_checkTitleText = true;
  49. public Color m_frameColor = Color.white;
  50. private bool m_isEditingInnerTitle;
  51. private bool m_stopEditingInnerTitle;
  52. private bool m_startEditingInnerTitle;
  53. private bool m_isEditingNoteText;
  54. private bool m_stopEditingNoteText;
  55. private bool m_startEditingNoteText;
  56. private double m_clickTimeTitle;
  57. private double m_doubleClickTimeTitle = 0.3;
  58. private double m_clickTimeNote;
  59. private double m_doubleClickTimeNote = 0.3;
  60. protected override void CommonInit( int uniqueId )
  61. {
  62. base.CommonInit( uniqueId );
  63. m_reorderLocked = true;
  64. m_rmbIgnore = true;
  65. m_defaultInteractionMode = InteractionMode.Both;
  66. m_connStatus = NodeConnectionStatus.Island;
  67. m_textLabelWidth = 90;
  68. m_position.width = 150;
  69. m_position.height = 100;
  70. }
  71. protected override void OnUniqueIDAssigned()
  72. {
  73. base.OnUniqueIDAssigned();
  74. m_focusTitleName = CommentaryTitle + OutputId;
  75. m_focusNoteName = NoteTitle + OutputId;
  76. }
  77. public override void DrawProperties()
  78. {
  79. base.DrawProperties();
  80. NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr,()=>
  81. {
  82. EditorGUI.BeginChangeCheck();
  83. m_titleText = EditorGUILayoutTextField( "Frame Title", m_titleText );
  84. if ( EditorGUI.EndChangeCheck() )
  85. {
  86. m_checkTitleText = true;
  87. }
  88. EditorGUI.BeginChangeCheck();
  89. m_innerTitleText = EditorGUILayoutTextField( NoteTitle, m_innerTitleText );
  90. if ( EditorGUI.EndChangeCheck() )
  91. {
  92. m_checkCommentText = true;
  93. }
  94. m_noteText = EditorGUILayoutTextArea( m_noteText , UIUtils.MainSkin.textArea );
  95. m_frameColor = EditorGUILayoutColorField( "Frame Color", m_frameColor );
  96. } );
  97. EditorGUILayout.HelpBox( WarningText, MessageType.Warning );
  98. }
  99. public override void OnNodeLayout( DrawInfo drawInfo )
  100. {
  101. //base.OnLayout( drawInfo );
  102. CalculatePositionAndVisibility( drawInfo );
  103. m_headerPosition = m_globalPosition;
  104. m_headerPosition.height = UIUtils.CurrentHeaderHeight;
  105. m_auxHeaderPos = m_position;
  106. m_auxHeaderPos.height = UIUtils.HeaderMaxHeight;
  107. m_innerTitleArea = m_globalPosition;
  108. m_innerTitleArea.height = COMMENTARY_BOX_HEIGHT * drawInfo.InvertedZoom;
  109. m_innerTitleArea.xMin += 10 * drawInfo.InvertedZoom;
  110. m_innerTitleArea.xMax -= 10 * drawInfo.InvertedZoom;
  111. m_noteTextArea = m_globalPosition;
  112. m_noteTextArea.height -= m_innerTitleArea.height;
  113. m_noteTextArea.yMin += m_innerTitleArea.height + NOTE_AREA_ADJUST * drawInfo.InvertedZoom;
  114. m_noteTextArea.yMax += 4*NOTE_AREA_ADJUST * drawInfo.InvertedZoom;
  115. m_noteTextArea.xMin += 10 * drawInfo.InvertedZoom;
  116. m_noteTextArea.xMax -= 10 * drawInfo.InvertedZoom;
  117. if ( m_resizeIconTex == null )
  118. {
  119. m_resizeIconTex = UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButton ).normal.background;
  120. }
  121. // LEFT RESIZE BUTTON
  122. m_resizeLeftIconCoords = m_globalPosition;
  123. m_resizeLeftIconCoords.x = m_globalPosition.x + 2;
  124. m_resizeLeftIconCoords.y = m_globalPosition.y + m_globalPosition.height - 2 - ( m_resizeIconTex.height + ResizeButtonPos.y ) * drawInfo.InvertedZoom;
  125. m_resizeLeftIconCoords.width = m_resizeIconTex.width * drawInfo.InvertedZoom;
  126. m_resizeLeftIconCoords.height = m_resizeIconTex.height * drawInfo.InvertedZoom;
  127. // RIGHT RESIZE BUTTON
  128. m_resizeRightIconCoords = m_globalPosition;
  129. m_resizeRightIconCoords.x = m_globalPosition.x + m_globalPosition.width - 1 - ( m_resizeIconTex.width + ResizeButtonPos.x ) * drawInfo.InvertedZoom;
  130. m_resizeRightIconCoords.y = m_globalPosition.y + m_globalPosition.height - 2 - ( m_resizeIconTex.height + ResizeButtonPos.y ) * drawInfo.InvertedZoom;
  131. m_resizeRightIconCoords.width = m_resizeIconTex.width * drawInfo.InvertedZoom;
  132. m_resizeRightIconCoords.height = m_resizeIconTex.height * drawInfo.InvertedZoom;
  133. }
  134. public override void OnNodeRepaint( DrawInfo drawInfo )
  135. {
  136. if ( !m_isVisible )
  137. return;
  138. m_colorBuffer = GUI.color;
  139. // Background
  140. GUI.color = Constants.NodeBodyColor * m_frameColor;
  141. GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryBackground ) );
  142. // Header
  143. GUI.color = m_headerColor * m_headerColorModifier * m_frameColor;
  144. GUI.Label( m_headerPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeHeader ) );
  145. GUI.color = m_colorBuffer;
  146. // Fixed Title ( only renders when not editing )
  147. if ( !m_isEditingInnerTitle && !m_startEditingInnerTitle && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
  148. {
  149. GUI.Label( m_innerTitleArea, m_innerTitleText, UIUtils.CommentaryTitle );
  150. }
  151. // Note Text ( only renders when not editing )
  152. if( !m_isEditingNoteText && !m_startEditingNoteText && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
  153. {
  154. GUI.Label( m_noteTextArea, m_noteText, UIUtils.StickyNoteText );
  155. }
  156. // Buttons
  157. GUI.Label( m_resizeLeftIconCoords, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButtonInv ) );
  158. GUI.Label( m_resizeRightIconCoords, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButton ) );
  159. // Selection Box
  160. if ( m_selected )
  161. {
  162. GUI.color = Constants.NodeSelectedColor;
  163. RectOffset cache = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border;
  164. UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border = UIUtils.RectOffsetSix;
  165. GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) );
  166. UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border = cache;
  167. GUI.color = m_colorBuffer;
  168. }
  169. if ( !string.IsNullOrEmpty( m_titleText ) )
  170. {
  171. Rect titleRect = m_globalPosition;
  172. titleRect.y -= 24;
  173. titleRect.height = 24;
  174. GUI.Label( titleRect, m_titleText, UIUtils.GetCustomStyle( CustomStyle.CommentarySuperTitle ) );
  175. }
  176. }
  177. public override void Move( Vector2 delta, bool snap )
  178. {
  179. if( m_isResizingRight || m_isResizingLeft )
  180. return;
  181. base.Move( delta, snap );
  182. }
  183. public override void Draw( DrawInfo drawInfo )
  184. {
  185. base.Draw( drawInfo );
  186. // Custom Editable Title
  187. if ( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
  188. {
  189. if( !m_startEditingNoteText && !m_isEditingNoteText )
  190. {
  191. if( !m_isEditingInnerTitle && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_innerTitleArea.Contains( drawInfo.MousePosition ) ) ) )
  192. {
  193. if( ( EditorApplication.timeSinceStartup - m_clickTimeTitle ) < m_doubleClickTimeTitle )
  194. m_startEditingInnerTitle = true;
  195. else
  196. GUI.FocusControl( null );
  197. m_clickTimeTitle = EditorApplication.timeSinceStartup;
  198. }
  199. else if( m_isEditingInnerTitle && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_innerTitleArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) )
  200. {
  201. m_stopEditingInnerTitle = true;
  202. }
  203. if( m_isEditingInnerTitle || m_startEditingInnerTitle )
  204. {
  205. EditorGUI.BeginChangeCheck();
  206. GUI.SetNextControlName( m_focusTitleName );
  207. m_innerTitleText = EditorGUITextField( m_innerTitleArea, string.Empty, m_innerTitleText, UIUtils.CommentaryTitle );
  208. if( EditorGUI.EndChangeCheck() )
  209. {
  210. m_checkCommentText = true;
  211. }
  212. if( m_startEditingInnerTitle )
  213. EditorGUI.FocusTextInControl( m_focusTitleName );
  214. }
  215. if( drawInfo.CurrentEventType == EventType.Repaint )
  216. {
  217. if( m_startEditingInnerTitle )
  218. {
  219. m_startEditingInnerTitle = false;
  220. m_isEditingInnerTitle = true;
  221. }
  222. if( m_stopEditingInnerTitle )
  223. {
  224. m_stopEditingInnerTitle = false;
  225. m_isEditingInnerTitle = false;
  226. GUI.FocusControl( null );
  227. }
  228. }
  229. }
  230. ////////////////////////
  231. if( !m_startEditingInnerTitle && !m_isEditingInnerTitle )
  232. {
  233. if( !m_isEditingNoteText && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_noteTextArea.Contains( drawInfo.MousePosition ) ) ) )
  234. {
  235. if( ( EditorApplication.timeSinceStartup - m_clickTimeNote ) < m_doubleClickTimeNote )
  236. m_startEditingNoteText = true;
  237. else
  238. GUI.FocusControl( null );
  239. m_clickTimeNote = EditorApplication.timeSinceStartup;
  240. }
  241. else if( m_isEditingNoteText && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_noteTextArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) )
  242. {
  243. m_stopEditingInnerTitle = true;
  244. }
  245. if( m_isEditingNoteText || m_startEditingNoteText )
  246. {
  247. GUI.SetNextControlName( m_focusNoteName );
  248. m_noteText = EditorGUITextArea( m_noteTextArea, m_noteText, UIUtils.StickyNoteText );
  249. if( m_startEditingNoteText )
  250. EditorGUI.FocusTextInControl( m_focusNoteName );
  251. }
  252. if( drawInfo.CurrentEventType == EventType.Repaint )
  253. {
  254. if( m_startEditingNoteText )
  255. {
  256. m_startEditingNoteText = false;
  257. m_isEditingNoteText = true;
  258. }
  259. if( m_stopEditingInnerTitle )
  260. {
  261. m_stopEditingInnerTitle = false;
  262. m_isEditingNoteText = false;
  263. GUI.FocusControl( null );
  264. }
  265. }
  266. }
  267. ////////////////////////
  268. }
  269. if ( drawInfo.CurrentEventType == EventType.MouseDown && drawInfo.LeftMouseButtonPressed )
  270. {
  271. // Left Button
  272. if( m_resizeLeftIconCoords.Contains( drawInfo.MousePosition ) && ContainerGraph.ParentWindow.CurrentEvent.modifiers != EventModifiers.Shift )
  273. {
  274. if ( !m_isResizingLeft )
  275. {
  276. m_isResizingLeft = true;
  277. ContainerGraph.ParentWindow.ForceAutoPanDir = true;
  278. m_resizeStartPoint = drawInfo.TransformedMousePos;
  279. }
  280. }
  281. // Right Button
  282. if ( m_resizeRightIconCoords.Contains( drawInfo.MousePosition ) && ContainerGraph.ParentWindow.CurrentEvent.modifiers != EventModifiers.Shift )
  283. {
  284. if ( !m_isResizingRight )
  285. {
  286. m_isResizingRight = true;
  287. ContainerGraph.ParentWindow.ForceAutoPanDir = true;
  288. m_resizeStartPoint = drawInfo.TransformedMousePos;
  289. }
  290. }
  291. }
  292. if ( drawInfo.CurrentEventType == EventType.Repaint || drawInfo.CurrentEventType == EventType.MouseUp )
  293. {
  294. // Left Button
  295. EditorGUIUtility.AddCursorRect( m_resizeLeftIconCoords, MouseCursor.ResizeUpRight );
  296. if ( m_isResizingLeft )
  297. {
  298. if ( drawInfo.CurrentEventType == EventType.MouseUp )
  299. {
  300. m_isResizingLeft = false;
  301. ContainerGraph.ParentWindow.ForceAutoPanDir = false;
  302. FireStoppedMovingEvent( false, InteractionMode.Target );
  303. }
  304. else
  305. {
  306. Vector2 currSize = ( drawInfo.TransformedMousePos - m_resizeStartPoint ) /*/ drawInfo.InvertedZoom*/;
  307. m_resizeStartPoint = drawInfo.TransformedMousePos;
  308. if ( m_resizeAxis != eResizeAxis.Y_AXIS )
  309. {
  310. m_position.x += currSize.x;
  311. m_position.width -= currSize.x;
  312. if ( m_position.width < MIN_SIZE_X )
  313. {
  314. m_position.x -= ( MIN_SIZE_X - m_position.width );
  315. m_position.width = MIN_SIZE_X;
  316. }
  317. }
  318. if ( m_resizeAxis != eResizeAxis.X_AXIS )
  319. {
  320. m_position.height += currSize.y;
  321. if ( m_position.height < MIN_SIZE_Y )
  322. {
  323. m_position.height = MIN_SIZE_Y;
  324. }
  325. }
  326. }
  327. }
  328. // Right Button
  329. EditorGUIUtility.AddCursorRect( m_resizeRightIconCoords, MouseCursor.ResizeUpLeft );
  330. if ( m_isResizingRight )
  331. {
  332. if ( drawInfo.CurrentEventType == EventType.MouseUp )
  333. {
  334. m_isResizingRight = false;
  335. ContainerGraph.ParentWindow.ForceAutoPanDir = false;
  336. FireStoppedMovingEvent( false, InteractionMode.Target );
  337. }
  338. else
  339. {
  340. Vector2 currSize = ( drawInfo.TransformedMousePos - m_resizeStartPoint ) /*/ drawInfo.InvertedZoom*/;
  341. m_resizeStartPoint = drawInfo.TransformedMousePos;
  342. if ( m_resizeAxis != eResizeAxis.Y_AXIS )
  343. {
  344. m_position.width += currSize.x;
  345. if ( m_position.width < MIN_SIZE_X )
  346. {
  347. m_position.width = MIN_SIZE_X;
  348. }
  349. }
  350. if ( m_resizeAxis != eResizeAxis.X_AXIS )
  351. {
  352. m_position.height += currSize.y;
  353. if ( m_position.height < MIN_SIZE_Y )
  354. {
  355. m_position.height = MIN_SIZE_Y;
  356. }
  357. }
  358. }
  359. }
  360. }
  361. if ( m_checkCommentText )
  362. {
  363. m_checkCommentText = false;
  364. m_innerTitleText = m_innerTitleText.Replace( IOUtils.FIELD_SEPARATOR, ' ' );
  365. }
  366. if ( m_checkTitleText )
  367. {
  368. m_checkTitleText = false;
  369. m_titleText = m_titleText.Replace( IOUtils.FIELD_SEPARATOR, ' ' );
  370. }
  371. if ( m_focusOnTitle && drawInfo.CurrentEventType == EventType.KeyUp )
  372. {
  373. m_focusOnTitle = false;
  374. m_startEditingInnerTitle = true;
  375. }
  376. }
  377. public void Focus()
  378. {
  379. m_focusOnTitle = true;
  380. }
  381. public override void ReadFromString( ref string[] nodeParams )
  382. {
  383. base.ReadFromString( ref nodeParams );
  384. m_position.width = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  385. m_position.height = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  386. m_innerTitleText = GetCurrentParam( ref nodeParams );
  387. m_titleText = GetCurrentParam( ref nodeParams );
  388. string[] colorChannels = GetCurrentParam( ref nodeParams ).Split( IOUtils.VECTOR_SEPARATOR );
  389. if ( colorChannels.Length == 4 )
  390. {
  391. m_frameColor.r = Convert.ToSingle( colorChannels[ 0 ] );
  392. m_frameColor.g = Convert.ToSingle( colorChannels[ 1 ] );
  393. m_frameColor.b = Convert.ToSingle( colorChannels[ 2 ] );
  394. m_frameColor.a = Convert.ToSingle( colorChannels[ 3 ] );
  395. }
  396. else
  397. {
  398. UIUtils.ShowMessage( UniqueId, "Incorrect number of color values", MessageSeverity.Error );
  399. }
  400. m_noteText = GetCurrentParam( ref nodeParams );
  401. m_noteText = m_noteText.Replace( Constants.LineFeedSeparator, '\n' );
  402. m_noteText = m_noteText.Replace( Constants.SemiColonSeparator, ';' );
  403. }
  404. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  405. {
  406. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  407. IOUtils.AddFieldValueToString( ref nodeInfo, m_position.width );
  408. IOUtils.AddFieldValueToString( ref nodeInfo, m_position.height );
  409. IOUtils.AddFieldValueToString( ref nodeInfo, m_innerTitleText );
  410. IOUtils.AddFieldValueToString( ref nodeInfo, m_titleText );
  411. IOUtils.AddFieldValueToString( ref nodeInfo, m_frameColor.r.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.g.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.b.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.a.ToString() );
  412. m_noteText = m_noteText.Replace( Constants.LineFeedSeparator.ToString(), string.Empty);
  413. m_noteText = m_noteText.Replace( Constants.SemiColonSeparator.ToString(), string.Empty );
  414. m_noteText = UIUtils.ForceLFLineEnding( m_noteText );
  415. string parsedText = m_noteText.Replace( '\n', Constants.LineFeedSeparator );
  416. parsedText = parsedText.Replace( ';', Constants.SemiColonSeparator );
  417. IOUtils.AddFieldValueToString( ref nodeInfo, parsedText );
  418. }
  419. public override Rect Position { get { return Event.current.alt ? m_position : m_auxHeaderPos; } }
  420. public override bool Contains( Vector3 pos )
  421. {
  422. return Event.current.alt ? m_globalPosition.Contains( pos ) : ( m_headerPosition.Contains( pos ) || m_resizeRightIconCoords.Contains( pos ) || m_resizeLeftIconCoords.Contains( pos ) );
  423. }
  424. }
  425. }