MenuParent.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using UnityEngine;
  4. using UnityEditor;
  5. namespace AmplifyShaderEditor
  6. {
  7. public enum MenuAnchor
  8. {
  9. TOP_LEFT = 0,
  10. TOP_CENTER,
  11. TOP_RIGHT,
  12. MIDDLE_LEFT,
  13. MIDDLE_CENTER,
  14. MIDDLE_RIGHT,
  15. BOTTOM_LEFT,
  16. BOTTOM_CENTER,
  17. BOTTOM_RIGHT,
  18. NONE
  19. }
  20. public enum MenuAutoSize
  21. {
  22. MATCH_VERTICAL = 0,
  23. MATCH_HORIZONTAL,
  24. NONE
  25. }
  26. public class MenuParent
  27. {
  28. protected AmplifyShaderEditorWindow m_parentWindow = null;
  29. protected const float MinimizeButtonXSpacing = 5;
  30. protected const float MinimizeButtonYSpacing = 5.5f;
  31. protected const float ResizeAreaWidth = 5;
  32. protected const float MinimizeCollisionAdjust = 5;
  33. protected GUIStyle m_style;
  34. protected GUIContent m_content;
  35. protected Rect m_maximizedArea;
  36. protected Rect m_transformedArea;
  37. protected Rect m_resizeArea;
  38. protected MenuAnchor m_anchor;
  39. protected MenuAutoSize m_autoSize;
  40. protected bool m_isActive = true;
  41. protected bool m_isMaximized = true;
  42. protected bool m_lockOnMinimize = false;
  43. protected bool m_preLockState = false;
  44. protected Rect m_minimizedArea;
  45. protected Rect m_minimizeButtonPos;
  46. protected float m_realWidth;
  47. protected GUIStyle m_empty = new GUIStyle();
  48. protected float m_resizeDelta;
  49. protected bool m_isResizing = false;
  50. protected bool m_resizable = false;
  51. protected GUIStyle m_resizeAreaStyle;
  52. protected bool m_isMouseInside = false;
  53. protected Vector2 m_currentScrollPos;
  54. public MenuParent( AmplifyShaderEditorWindow parentWindow, float x, float y, float width, float height, string name, MenuAnchor anchor = MenuAnchor.NONE, MenuAutoSize autoSize = MenuAutoSize.NONE )
  55. {
  56. m_parentWindow = parentWindow;
  57. m_anchor = anchor;
  58. m_autoSize = autoSize;
  59. m_maximizedArea = new Rect( x, y, width, height );
  60. m_content = new GUIContent( GUIContent.none );
  61. m_content.text = name;
  62. m_transformedArea = new Rect();
  63. m_resizeArea = new Rect();
  64. m_resizeArea.width = ResizeAreaWidth;
  65. m_resizeAreaStyle = GUIStyle.none;
  66. m_currentScrollPos = Vector2.zero;
  67. }
  68. public void SetMinimizedArea( float x, float y, float width, float height )
  69. {
  70. m_minimizedArea = new Rect( x, y, width, height );
  71. }
  72. protected void InitDraw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId )
  73. {
  74. if ( m_style == null )
  75. {
  76. m_style = new GUIStyle( UIUtils.TextArea );
  77. m_style.normal.background = m_style.normal.scaledBackgrounds[ 0 ];
  78. m_style.normal.scaledBackgrounds = null;
  79. m_style.border = new RectOffset( 4, 4, 4, 4 );
  80. m_style.stretchHeight = true;
  81. m_style.stretchWidth = true;
  82. m_style.fontSize = ( int ) Constants.DefaultTitleFontSize;
  83. m_style.fontStyle = FontStyle.Normal;
  84. Texture minimizeTex = UIUtils.GetCustomStyle( CustomStyle.MaximizeButton ).normal.background;
  85. m_minimizeButtonPos = new Rect( 0, 0, minimizeTex.width, minimizeTex.height );
  86. }
  87. Rect currentArea = m_isMaximized ? m_maximizedArea : m_minimizedArea;
  88. if ( m_isMaximized )
  89. {
  90. if ( m_resizable )
  91. {
  92. if ( m_isResizing )
  93. {
  94. if ( m_anchor == MenuAnchor.TOP_LEFT )
  95. m_resizeDelta = ( ParentWindow.CurrentEvent.mousePosition.x - m_maximizedArea.width );
  96. else if ( m_anchor == MenuAnchor.TOP_RIGHT )
  97. m_resizeDelta = ParentWindow.CurrentEvent.mousePosition.x - ( parentPosition.width - m_maximizedArea.width);
  98. }
  99. }
  100. m_realWidth = m_maximizedArea.width;
  101. if ( m_resizable )
  102. {
  103. if ( m_anchor == MenuAnchor.TOP_LEFT )
  104. {
  105. currentArea.width += m_resizeDelta;
  106. m_realWidth += m_resizeDelta;
  107. }
  108. else if ( m_anchor == MenuAnchor.TOP_RIGHT )
  109. {
  110. currentArea.width -= m_resizeDelta;
  111. m_realWidth -= m_resizeDelta;
  112. }
  113. }
  114. }
  115. else
  116. {
  117. if ( currentArea.x < 0 )
  118. {
  119. m_realWidth = currentArea.width + currentArea.x;
  120. }
  121. else if ( ( currentArea.x + currentArea.width ) > parentPosition.width )
  122. {
  123. m_realWidth = parentPosition.width - currentArea.x;
  124. }
  125. if ( m_realWidth < 0 )
  126. m_realWidth = 0;
  127. }
  128. switch ( m_anchor )
  129. {
  130. case MenuAnchor.TOP_LEFT:
  131. {
  132. m_transformedArea.x = currentArea.x;
  133. m_transformedArea.y = currentArea.y;
  134. if ( m_isMaximized )
  135. {
  136. m_minimizeButtonPos.x = m_transformedArea.x + m_transformedArea.width - m_minimizeButtonPos.width - MinimizeButtonXSpacing;
  137. m_minimizeButtonPos.y = m_transformedArea.y + MinimizeButtonYSpacing;
  138. m_resizeArea.x = m_transformedArea.x + m_transformedArea.width;
  139. m_resizeArea.y = m_minimizeButtonPos.y;
  140. m_resizeArea.height = m_transformedArea.height;
  141. }
  142. else
  143. {
  144. float width = ( m_transformedArea.width - m_transformedArea.x );
  145. m_minimizeButtonPos.x = m_transformedArea.x + width * 0.5f - m_minimizeButtonPos.width * 0.5f;
  146. m_minimizeButtonPos.y = m_transformedArea.height * 0.5f - m_minimizeButtonPos.height * 0.5f;
  147. }
  148. }
  149. break;
  150. case MenuAnchor.TOP_CENTER:
  151. {
  152. m_transformedArea.x = parentPosition.width * 0.5f + currentArea.x;
  153. m_transformedArea.y = currentArea.y;
  154. }
  155. break;
  156. case MenuAnchor.TOP_RIGHT:
  157. {
  158. m_transformedArea.x = parentPosition.width - currentArea.x - currentArea.width;
  159. m_transformedArea.y = currentArea.y;
  160. if ( m_isMaximized )
  161. {
  162. m_minimizeButtonPos.x = m_transformedArea.x + MinimizeButtonXSpacing;
  163. m_minimizeButtonPos.y = m_transformedArea.y + MinimizeButtonYSpacing;
  164. m_resizeArea.x = m_transformedArea.x - ResizeAreaWidth;
  165. m_resizeArea.y = m_minimizeButtonPos.y;
  166. m_resizeArea.height = m_transformedArea.height;
  167. }
  168. else
  169. {
  170. float width = ( parentPosition.width - m_transformedArea.x );
  171. m_minimizeButtonPos.x = m_transformedArea.x + width * 0.5f - m_minimizeButtonPos.width * 0.5f;
  172. m_minimizeButtonPos.y = m_transformedArea.height * 0.5f - m_minimizeButtonPos.height * 0.5f;
  173. }
  174. }
  175. break;
  176. case MenuAnchor.MIDDLE_LEFT:
  177. {
  178. m_transformedArea.x = currentArea.x;
  179. m_transformedArea.y = parentPosition.height * 0.5f + currentArea.y;
  180. }
  181. break;
  182. case MenuAnchor.MIDDLE_CENTER:
  183. {
  184. m_transformedArea.x = parentPosition.width * 0.5f + currentArea.x;
  185. m_transformedArea.y = parentPosition.height * 0.5f + currentArea.y;
  186. }
  187. break;
  188. case MenuAnchor.MIDDLE_RIGHT:
  189. {
  190. m_transformedArea.x = parentPosition.width - currentArea.x - currentArea.width;
  191. m_transformedArea.y = parentPosition.height * 0.5f + currentArea.y;
  192. }
  193. break;
  194. case MenuAnchor.BOTTOM_LEFT:
  195. {
  196. m_transformedArea.x = currentArea.x;
  197. m_transformedArea.y = parentPosition.height - currentArea.y - currentArea.height;
  198. }
  199. break;
  200. case MenuAnchor.BOTTOM_CENTER:
  201. {
  202. m_transformedArea.x = parentPosition.width * 0.5f + currentArea.x;
  203. m_transformedArea.y = parentPosition.height - currentArea.y - currentArea.height;
  204. }
  205. break;
  206. case MenuAnchor.BOTTOM_RIGHT:
  207. {
  208. m_transformedArea.x = parentPosition.width - currentArea.x - currentArea.width;
  209. m_transformedArea.y = parentPosition.height - currentArea.y - currentArea.height;
  210. }
  211. break;
  212. case MenuAnchor.NONE:
  213. {
  214. m_transformedArea.x = currentArea.x;
  215. m_transformedArea.y = currentArea.y;
  216. }
  217. break;
  218. }
  219. switch ( m_autoSize )
  220. {
  221. case MenuAutoSize.MATCH_HORIZONTAL:
  222. {
  223. m_transformedArea.width = parentPosition.width - m_transformedArea.x;
  224. m_transformedArea.height = currentArea.height;
  225. }
  226. break;
  227. case MenuAutoSize.MATCH_VERTICAL:
  228. {
  229. m_transformedArea.width = currentArea.width;
  230. m_transformedArea.height = parentPosition.height - m_transformedArea.y;
  231. }
  232. break;
  233. case MenuAutoSize.NONE:
  234. {
  235. m_transformedArea.width = currentArea.width;
  236. m_transformedArea.height = currentArea.height;
  237. }
  238. break;
  239. }
  240. }
  241. public virtual void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus )
  242. {
  243. InitDraw( parentPosition, mousePosition, mouseButtonId );
  244. if ( ParentWindow.CurrentEvent.type == EventType.MouseDrag && ParentWindow.CurrentEvent.button > 0 /*catches both middle and right mouse button*/ )
  245. {
  246. m_isMouseInside = IsInside( mousePosition );
  247. if ( m_isMouseInside )
  248. {
  249. m_currentScrollPos.x += Constants.MenuDragSpeed * ParentWindow.CurrentEvent.delta.x;
  250. if ( m_currentScrollPos.x < 0 )
  251. m_currentScrollPos.x = 0;
  252. m_currentScrollPos.y += Constants.MenuDragSpeed * ParentWindow.CurrentEvent.delta.y;
  253. if ( m_currentScrollPos.y < 0 )
  254. m_currentScrollPos.y = 0;
  255. }
  256. }
  257. }
  258. public void PostDraw()
  259. {
  260. if ( !m_isMaximized )
  261. {
  262. m_transformedArea.height = 35;
  263. GUI.Label( m_transformedArea, m_content, m_style );
  264. }
  265. Color colorBuffer = GUI.color;
  266. GUI.color = EditorGUIUtility.isProSkin ? Color.white : Color.black;
  267. bool guiEnabledBuffer = GUI.enabled;
  268. GUI.enabled = !m_lockOnMinimize;
  269. Rect buttonArea = m_minimizeButtonPos;
  270. buttonArea.x -= MinimizeCollisionAdjust;
  271. buttonArea.width += 2 * MinimizeCollisionAdjust;
  272. buttonArea.y -= MinimizeCollisionAdjust;
  273. buttonArea.height += 2 * MinimizeCollisionAdjust;
  274. if ( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.Repaint )
  275. GUI.Label( m_minimizeButtonPos, string.Empty, UIUtils.GetCustomStyle( m_isMaximized ? CustomStyle.MinimizeButton : CustomStyle.MaximizeButton ) );
  276. if( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.MouseDown && buttonArea.Contains( m_parentWindow.CameraDrawInfo.MousePosition ) )
  277. //if ( GUI.Button( buttonArea, string.Empty, m_empty ) )
  278. {
  279. m_isMaximized = !m_isMaximized;
  280. m_resizeDelta = 0;
  281. }
  282. if ( m_resizable && m_isMaximized )
  283. {
  284. EditorGUIUtility.AddCursorRect( m_resizeArea, MouseCursor.ResizeHorizontal );
  285. if ( !m_isResizing && GUI.RepeatButton( m_resizeArea, string.Empty, m_resizeAreaStyle ) )
  286. {
  287. m_isResizing = true;
  288. }
  289. else
  290. {
  291. if ( m_isResizing )
  292. {
  293. if ( ParentWindow.CurrentEvent.isMouse && ParentWindow.CurrentEvent.type != EventType.MouseDrag )
  294. {
  295. m_isResizing = false;
  296. }
  297. }
  298. }
  299. if ( m_realWidth < buttonArea.width )
  300. {
  301. // Auto-minimize
  302. m_isMaximized = false;
  303. m_resizeDelta = 0;
  304. m_isResizing = false;
  305. }
  306. else
  307. {
  308. float halfSizeWindow = 0.5f * ParentWindow.position.width;
  309. if ( m_realWidth > halfSizeWindow )
  310. {
  311. m_realWidth = 0.5f * ParentWindow.position.width;
  312. if ( m_resizeDelta > 0 )
  313. {
  314. m_resizeDelta = m_realWidth - m_maximizedArea.width;
  315. }
  316. else
  317. {
  318. m_resizeDelta = m_maximizedArea.width - m_realWidth;
  319. }
  320. }
  321. }
  322. }
  323. GUI.enabled = guiEnabledBuffer;
  324. GUI.color = colorBuffer;
  325. }
  326. public void OnLostFocus()
  327. {
  328. if ( m_isResizing )
  329. {
  330. m_isResizing = false;
  331. }
  332. }
  333. virtual public void Destroy()
  334. {
  335. m_empty = null;
  336. m_resizeAreaStyle = null;
  337. }
  338. public float InitialX
  339. {
  340. get { return m_maximizedArea.x; }
  341. set { m_maximizedArea.x = value; }
  342. }
  343. public float Width
  344. {
  345. get { return m_maximizedArea.width; }
  346. set { m_maximizedArea.width = value; }
  347. }
  348. public float RealWidth
  349. {
  350. get { return m_realWidth; }
  351. }
  352. public float Height
  353. {
  354. get { return m_maximizedArea.height; }
  355. set { m_maximizedArea.height = value; }
  356. }
  357. public Rect Size
  358. {
  359. get { return m_maximizedArea; }
  360. }
  361. public virtual bool IsInside( Vector2 position )
  362. {
  363. if ( !m_isActive )
  364. return false;
  365. return m_transformedArea.Contains( position );
  366. }
  367. public bool IsMaximized
  368. {
  369. get { return m_isMaximized; }
  370. set { m_isMaximized = value; }
  371. }
  372. public Rect TransformedArea
  373. {
  374. get { return m_transformedArea; }
  375. }
  376. public bool Resizable { set { m_resizable = value; } }
  377. public bool IsResizing { get { return m_isResizing; } }
  378. public bool LockOnMinimize
  379. {
  380. set
  381. {
  382. if ( m_lockOnMinimize == value )
  383. return;
  384. m_lockOnMinimize = value;
  385. if ( value )
  386. {
  387. m_preLockState = m_isMaximized;
  388. m_isMaximized = false;
  389. }
  390. else
  391. {
  392. m_isMaximized = m_preLockState;
  393. }
  394. }
  395. }
  396. public bool IsActive
  397. {
  398. get { return m_isActive; }
  399. }
  400. public AmplifyShaderEditorWindow ParentWindow { get { return m_parentWindow; } set { m_parentWindow = value; } }
  401. }
  402. }