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.

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