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.

562 lines
20 KiB

  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using UnityEngine;
  4. using System.Collections.Generic;
  5. using UnityEditor;
  6. using System;
  7. namespace AmplifyShaderEditor
  8. {
  9. public class PaletteFilterData
  10. {
  11. public bool Visible;
  12. public bool HasCommunityData;
  13. public List<ContextMenuItem> Contents;
  14. public PaletteFilterData( bool visible )
  15. {
  16. Visible = visible;
  17. Contents = new List<ContextMenuItem>();
  18. }
  19. }
  20. public class PaletteParent : MenuParent
  21. {
  22. private const float ItemSize = 18;
  23. public delegate void OnPaletteNodeCreate( System.Type type, string name, AmplifyShaderFunction function );
  24. public event OnPaletteNodeCreate OnPaletteNodeCreateEvt;
  25. private string m_searchFilterStr = "Search";
  26. protected string m_searchFilterControl = "SHADERNAMETEXTFIELDCONTROLNAME";
  27. protected bool m_focusOnSearch = false;
  28. protected bool m_defaultCategoryVisible = false;
  29. //protected List<ContextMenuItem> m_allItems;
  30. protected List<ContextMenuItem> m_currentItems;
  31. protected Dictionary<string, PaletteFilterData> m_currentCategories;
  32. private bool m_forceUpdate = true;
  33. protected string m_searchFilter = string.Empty;
  34. private float m_searchLabelSize = -1;
  35. private GUIStyle m_buttonStyle;
  36. private GUIStyle m_foldoutStyle;
  37. protected bool m_previousWindowIsFunction = false;
  38. protected int m_validButtonId = 0;
  39. protected int m_initialSeparatorAmount = 1;
  40. private Vector2 m_currScrollBarDims = new Vector2( 1, 1 );
  41. public PaletteParent( AmplifyShaderEditorWindow parentWindow, float x, float y, float width, float height, string name, MenuAnchor anchor = MenuAnchor.NONE, MenuAutoSize autoSize = MenuAutoSize.NONE ) : base( parentWindow, x, y, width, height, name, anchor, autoSize )
  42. {
  43. m_searchFilter = string.Empty;
  44. m_currentCategories = new Dictionary<string, PaletteFilterData>();
  45. //m_allItems = items;
  46. m_currentItems = new List<ContextMenuItem>();
  47. }
  48. public virtual void OnEnterPressed( int index = 0 ) { }
  49. public virtual void OnEscapePressed() { }
  50. public void FireNodeCreateEvent( System.Type type, string name, AmplifyShaderFunction function )
  51. {
  52. OnPaletteNodeCreateEvt( type, name, function );
  53. }
  54. public override void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus )
  55. {
  56. base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboadFocus );
  57. if( m_previousWindowIsFunction != ParentWindow.IsShaderFunctionWindow )
  58. {
  59. m_forceUpdate = true;
  60. }
  61. m_previousWindowIsFunction = ParentWindow.IsShaderFunctionWindow;
  62. List<ContextMenuItem> allItems = ParentWindow.ContextMenuInstance.MenuItems;
  63. if( m_searchLabelSize < 0 )
  64. {
  65. m_searchLabelSize = GUI.skin.label.CalcSize( new GUIContent( m_searchFilterStr ) ).x;
  66. }
  67. if( m_foldoutStyle == null )
  68. {
  69. m_foldoutStyle = new GUIStyle( GUI.skin.GetStyle( "foldout" ) );
  70. m_foldoutStyle.fontStyle = FontStyle.Bold;
  71. }
  72. if( m_buttonStyle == null )
  73. {
  74. m_buttonStyle = UIUtils.Label;
  75. }
  76. Event currenEvent = Event.current;
  77. GUILayout.BeginArea( m_transformedArea, m_content, m_style );
  78. {
  79. for( int i = 0; i < m_initialSeparatorAmount; i++ )
  80. {
  81. EditorGUILayout.Separator();
  82. }
  83. if( currenEvent.type == EventType.KeyDown )
  84. {
  85. KeyCode key = currenEvent.keyCode;
  86. //if ( key == KeyCode.Return || key == KeyCode.KeypadEnter )
  87. // OnEnterPressed();
  88. if( ( currenEvent.keyCode == KeyCode.KeypadEnter || currenEvent.keyCode == KeyCode.Return ) && currenEvent.type == EventType.KeyDown )
  89. {
  90. int index = m_currentItems.FindIndex( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) );
  91. if( index > -1 )
  92. OnEnterPressed( index );
  93. else
  94. OnEnterPressed();
  95. }
  96. if( key == KeyCode.Escape )
  97. OnEscapePressed();
  98. if( m_isMouseInside || hasKeyboadFocus )
  99. {
  100. if( key == ShortcutsManager.ScrollUpKey )
  101. {
  102. m_currentScrollPos.y -= 10;
  103. if( m_currentScrollPos.y < 0 )
  104. {
  105. m_currentScrollPos.y = 0;
  106. }
  107. currenEvent.Use();
  108. }
  109. if( key == ShortcutsManager.ScrollDownKey )
  110. {
  111. m_currentScrollPos.y += 10;
  112. currenEvent.Use();
  113. }
  114. }
  115. }
  116. float width = EditorGUIUtility.labelWidth;
  117. EditorGUIUtility.labelWidth = m_searchLabelSize;
  118. EditorGUI.BeginChangeCheck();
  119. {
  120. GUI.SetNextControlName( m_searchFilterControl + m_resizable );
  121. m_searchFilter = EditorGUILayout.TextField( m_searchFilterStr, m_searchFilter );
  122. if( m_focusOnSearch )
  123. {
  124. m_focusOnSearch = false;
  125. EditorGUI.FocusTextInControl( m_searchFilterControl + m_resizable );
  126. }
  127. }
  128. if( EditorGUI.EndChangeCheck() )
  129. m_forceUpdate = true;
  130. EditorGUIUtility.labelWidth = width;
  131. bool usingSearchFilter = ( m_searchFilter.Length == 0 );
  132. m_currScrollBarDims.x = m_transformedArea.width;
  133. m_currScrollBarDims.y = m_transformedArea.height - 2 - 16 - 2 - 7 * m_initialSeparatorAmount - 2;
  134. m_currentScrollPos = EditorGUILayout.BeginScrollView( m_currentScrollPos/*, GUILayout.Width( 242 ), GUILayout.Height( 250 - 2 - 16 - 2 - 7 - 2) */);
  135. {
  136. if( m_forceUpdate )
  137. {
  138. m_forceUpdate = false;
  139. //m_currentItems.Clear();
  140. m_currentCategories.Clear();
  141. if( usingSearchFilter )
  142. {
  143. for( int i = 0; i < allItems.Count; i++ )
  144. {
  145. //m_currentItems.Add( allItems[ i ] );
  146. if( !m_currentCategories.ContainsKey( allItems[ i ].Category ) )
  147. {
  148. m_currentCategories.Add( allItems[ i ].Category, new PaletteFilterData( m_defaultCategoryVisible ) );
  149. //m_currentCategories[ allItems[ i ].Category ].HasCommunityData = allItems[ i ].NodeAttributes.FromCommunity || m_currentCategories[ allItems[ i ].Category ].HasCommunityData;
  150. }
  151. m_currentCategories[ allItems[ i ].Category ].Contents.Add( allItems[ i ] );
  152. }
  153. }
  154. else
  155. {
  156. for( int i = 0; i < allItems.Count; i++ )
  157. {
  158. if( allItems[ i ].Name.IndexOf( m_searchFilter, StringComparison.InvariantCultureIgnoreCase ) >= 0 ||
  159. allItems[ i ].Category.IndexOf( m_searchFilter, StringComparison.InvariantCultureIgnoreCase ) >= 0
  160. )
  161. {
  162. //m_currentItems.Add( allItems[ i ] );
  163. if( !m_currentCategories.ContainsKey( allItems[ i ].Category ) )
  164. {
  165. m_currentCategories.Add( allItems[ i ].Category, new PaletteFilterData( m_defaultCategoryVisible ) );
  166. //m_currentCategories[ allItems[ i ].Category ].HasCommunityData = allItems[ i ].NodeAttributes.FromCommunity || m_currentCategories[ allItems[ i ].Category ].HasCommunityData;
  167. }
  168. m_currentCategories[ allItems[ i ].Category ].Contents.Add( allItems[ i ] );
  169. }
  170. }
  171. }
  172. var categoryEnumerator = m_currentCategories.GetEnumerator();
  173. while( categoryEnumerator.MoveNext() )
  174. {
  175. categoryEnumerator.Current.Value.Contents.Sort( ( x, y ) => x.CompareTo( y, usingSearchFilter ) );
  176. }
  177. //sort current list respecting categories
  178. m_currentItems.Clear();
  179. foreach( var item in m_currentCategories )
  180. {
  181. for( int i = 0; i < item.Value.Contents.Count; i++ )
  182. {
  183. m_currentItems.Add( item.Value.Contents[ i ] );
  184. }
  185. }
  186. }
  187. string watching = string.Empty;
  188. // unselect the main search field so it can focus list elements next
  189. if( ( currenEvent.keyCode == KeyCode.DownArrow || currenEvent.keyCode == KeyCode.UpArrow ) && m_searchFilter.Length > 0 )
  190. {
  191. if( GUI.GetNameOfFocusedControl().Equals( m_searchFilterControl + m_resizable ) )
  192. {
  193. EditorGUI.FocusTextInControl( null );
  194. }
  195. }
  196. if( currenEvent.keyCode == KeyCode.DownArrow && currenEvent.type == EventType.KeyDown )
  197. {
  198. currenEvent.Use();
  199. int nextIndex = m_currentItems.FindIndex( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) ) + 1;
  200. if( nextIndex == m_currentItems.Count )
  201. nextIndex = 0;
  202. watching = m_currentItems[ nextIndex ].ItemUIContent.text + m_resizable;
  203. GUI.FocusControl( watching );
  204. }
  205. if( currenEvent.keyCode == KeyCode.UpArrow && currenEvent.type == EventType.KeyDown )
  206. {
  207. currenEvent.Use();
  208. int nextIndex = m_currentItems.FindIndex( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) ) - 1;
  209. if( nextIndex < 0 )
  210. nextIndex = m_currentItems.Count - 1;
  211. watching = m_currentItems[ nextIndex ].ItemUIContent.text + m_resizable;
  212. GUI.FocusControl( watching );
  213. }
  214. if( currenEvent.keyCode == KeyCode.Tab )
  215. {
  216. ContextMenuItem item = m_currentItems.Find( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) );
  217. if( item != null )
  218. {
  219. watching = item.ItemUIContent.text + m_resizable;
  220. }
  221. }
  222. float currPos = 0;
  223. var enumerator = m_currentCategories.GetEnumerator();
  224. float cache = EditorGUIUtility.labelWidth;
  225. while( enumerator.MoveNext() )
  226. {
  227. var current = enumerator.Current;
  228. bool visible = GUILayout.Toggle( current.Value.Visible, current.Key, m_foldoutStyle );
  229. if( m_validButtonId == mouseButtonId )
  230. {
  231. current.Value.Visible = visible;
  232. }
  233. currPos += ItemSize;
  234. if( m_searchFilter.Length > 0 || current.Value.Visible )
  235. {
  236. for( int i = 0; i < current.Value.Contents.Count; i++ )
  237. {
  238. //if ( !IsItemVisible( currPos ) )
  239. //{
  240. // // Invisible
  241. // GUILayout.Space( ItemSize );
  242. //}
  243. //else
  244. {
  245. currPos += ItemSize;
  246. // Visible
  247. EditorGUILayout.BeginHorizontal();
  248. GUILayout.Space( 16 );
  249. //if ( m_isMouseInside )
  250. //{
  251. // //GUI.SetNextControlName( current.Value.Contents[ i ].ItemUIContent.text );
  252. // if ( CheckButton( current.Value.Contents[ i ].ItemUIContent, m_buttonStyle, mouseButtonId ) )
  253. // {
  254. // int controlID = GUIUtility.GetControlID( FocusType.Passive );
  255. // GUIUtility.hotControl = controlID;
  256. // OnPaletteNodeCreateEvt( current.Value.Contents[ i ].NodeType, current.Value.Contents[ i ].Name, current.Value.Contents[ i ].Function );
  257. // }
  258. //}
  259. //else
  260. {
  261. Rect thisRect = EditorGUILayout.GetControlRect( false, 16f, EditorStyles.label );
  262. //if ( m_resizable )
  263. {
  264. if( GUI.RepeatButton( thisRect, string.Empty, EditorStyles.label ) )
  265. {
  266. int controlID = GUIUtility.GetControlID( FocusType.Passive );
  267. GUIUtility.hotControl = controlID;
  268. OnPaletteNodeCreateEvt( current.Value.Contents[ i ].NodeType, current.Value.Contents[ i ].Name, current.Value.Contents[ i ].Function );
  269. //unfocus to make it focus the next text field correctly
  270. GUI.FocusControl( null );
  271. }
  272. }
  273. GUI.SetNextControlName( current.Value.Contents[ i ].ItemUIContent.text + m_resizable );
  274. //EditorGUI.SelectableLabel( thisRect, current.Value.Contents[ i ].ItemUIContent.text, EditorStyles.label );
  275. //float cache = EditorGUIUtility.labelWidth;
  276. EditorGUIUtility.labelWidth = thisRect.width;
  277. EditorGUI.Toggle( thisRect, current.Value.Contents[ i ].ItemUIContent.text, false, EditorStyles.label );
  278. EditorGUIUtility.labelWidth = cache;
  279. if( watching == current.Value.Contents[ i ].ItemUIContent.text + m_resizable )
  280. {
  281. bool boundBottom = currPos - m_currentScrollPos.y > m_currScrollBarDims.y;
  282. bool boundTop = currPos - m_currentScrollPos.y - 4 <= 0;
  283. if( boundBottom )
  284. m_currentScrollPos.y = currPos - m_currScrollBarDims.y + 2;
  285. else if( boundTop )
  286. m_currentScrollPos.y = currPos - 18;
  287. //else if ( boundBottom && !downDirection )
  288. // m_currentScrollPos.y = currPos - m_currScrollBarDims.y + 2;
  289. //else if ( boundTop && downDirection )
  290. // m_currentScrollPos.y = currPos - 18;
  291. }
  292. }
  293. EditorGUILayout.EndHorizontal();
  294. }
  295. //currPos += ItemSize;
  296. }
  297. }
  298. }
  299. EditorGUIUtility.labelWidth = cache;
  300. }
  301. EditorGUILayout.EndScrollView();
  302. }
  303. GUILayout.EndArea();
  304. }
  305. public void CheckCommunityNodes()
  306. {
  307. var enumerator = m_currentCategories.GetEnumerator();
  308. while( enumerator.MoveNext() )
  309. {
  310. var current = enumerator.Current;
  311. current.Value.HasCommunityData = false;
  312. int count = current.Value.Contents.Count;
  313. for( int i = 0; i < count; i++ )
  314. {
  315. if( current.Value.Contents[ i ].NodeAttributes.FromCommunity )
  316. {
  317. current.Value.HasCommunityData = true;
  318. break;
  319. }
  320. }
  321. }
  322. }
  323. public void DumpAvailableNodes( bool fromCommunity, string pathname )
  324. {
  325. string noTOCHeader = "__NOTOC__\n";
  326. string nodesHeader = "== Available Node Categories ==\n";
  327. string InitialCategoriesFormat = "[[#{0}|{0}]]<br>\n";
  328. string InitialCategories = string.Empty;
  329. string CurrentCategoryFormat = "\n== {0} ==\n\n";
  330. //string NodesFootFormat = "[[Unity Products:Amplify Shader Editor/{0} | Learn More]] -\n[[#Top|Back to Categories]]\n";
  331. string NodesFootFormatSep = "[[#Top|Back to Top]]\n----\n";
  332. string OverallFoot = "[[Category:Nodes]]";
  333. string NodeInfoBeginFormat = "<div class=\"nodecard\">\n";
  334. string nodeInfoBodyFormat = "{{| id=\"{2}\" class=\"wikitable\" |\n" +
  335. "|- \n" +
  336. "| <div>[[Unity Products:Amplify Shader Editor/{1}|<img class=\"responsive-img\" src=\"http://amplify.pt/Nodes/{0}.jpg\">]]</div>\n" +
  337. "<div>\n" +
  338. "{{| style=\"width: 100%; height: 150px;\"\n" +
  339. "|-\n" +
  340. "| [[Unity Products:Amplify Shader Editor/{1}|'''{2}''']]\n" +
  341. "|- style=\"vertical-align:top; height: 100%;\" |\n" +
  342. "|<p class=\"cardtext\">{3}</p>\n" +
  343. "|- style=\"text-align:right;\" |\n" +
  344. "|{4}[[Unity Products:Amplify Shader Editor/{1} | Learn More]]\n" +
  345. "|}}</div>\n" +
  346. "|}}\n";
  347. string NodeInfoEndFormat = "</div>\n";
  348. //string NodeInfoBeginFormat = "<span style=\"color:#c00;display:block;\">This page is under construction!</span>\n\n";
  349. //string nodeInfoBodyFormat = "<img style=\"float:left; margin-right:10px;\" src=\"http://amplify.pt/Nodes/{0}.jpg\">\n[[Unity Products:Amplify Shader Editor/{1}|'''{2}''']]\n\n{3}";
  350. //string NodeInfoEndFormat = "\n\n[[Unity_Products:Amplify_Shader_Editor/Nodes | Back to Node List ]]\n[[Category:Nodes]][[Category:{0}]]\n\n\n";
  351. //string NodeInfoBeginFormat = "{| cellpadding=\"10\"\n";
  352. //string nodeInfoBodyFormat = "|- style=\"vertical-align:top;\"\n| http://amplify.pt/Nodes/{0}.jpg\n| [[Unity Products:Amplify Shader Editor/{1} | <span style=\"font-size: 120%;\"><span id=\"{2}\"></span>'''{2}'''<span> ]] <br> {3}\n";
  353. //string NodeInfoEndFormat = "|}\n";
  354. string nodesInfo = string.Empty;
  355. BuildFullList( true );
  356. CheckCommunityNodes();
  357. var enumerator = m_currentCategories.GetEnumerator();
  358. while( enumerator.MoveNext() )
  359. {
  360. var current = enumerator.Current;
  361. if( fromCommunity && current.Value.HasCommunityData || !fromCommunity )
  362. {
  363. InitialCategories += string.Format( InitialCategoriesFormat, current.Key );
  364. nodesInfo += string.Format( CurrentCategoryFormat, current.Key );
  365. int count = current.Value.Contents.Count;
  366. for( int i = 0; i < count; i++ )
  367. {
  368. if( ( fromCommunity && current.Value.Contents[ i ].NodeAttributes.FromCommunity )
  369. || !fromCommunity
  370. //|| ( !fromCommunity && !current.Value.Contents[ i ].NodeAttributes.FromCommunity )
  371. )
  372. {
  373. string nodeFullName = current.Value.Contents[ i ].Name;
  374. string pictureFilename = UIUtils.ReplaceInvalidStrings( nodeFullName );
  375. string pageFilename = UIUtils.RemoveWikiInvalidCharacters( pictureFilename );
  376. pictureFilename = UIUtils.RemoveInvalidCharacters( pictureFilename );
  377. string nodeDescription = current.Value.Contents[ i ].ItemUIContent.tooltip;
  378. string communityText = string.Empty;
  379. if( current.Value.Contents[ i ].NodeAttributes.FromCommunity )
  380. communityText = "<small class=\"cardauthor\">( originally by "+ current.Value.Contents[ i ].NodeAttributes.Community + " )</small> ";
  381. string nodeInfoBody = string.Format( nodeInfoBodyFormat, pictureFilename, pageFilename, nodeFullName, nodeDescription, communityText );
  382. //string nodeInfoFoot = string.Format( NodesFootFormat, pageFilename );
  383. nodesInfo += ( NodeInfoBeginFormat + nodeInfoBody + NodeInfoEndFormat );
  384. //nodesInfo += ( NodeInfoBeginFormat + nodeInfoBody + string.Format( NodeInfoEndFormat, current.Key ) );
  385. //if ( i != ( count - 1 ) )
  386. //{
  387. // nodesInfo += NodesFootFormatSep;
  388. //}
  389. }
  390. }
  391. nodesInfo += NodesFootFormatSep;
  392. }
  393. }
  394. string finalText = noTOCHeader + nodesHeader + InitialCategories + nodesInfo + OverallFoot;
  395. if( !System.IO.Directory.Exists( pathname ) )
  396. {
  397. System.IO.Directory.CreateDirectory( pathname );
  398. }
  399. // Save file
  400. string nodesPathname = pathname + ( fromCommunity ? "AvailableNodesFromCommunity.txt" : "AvailableNodes.txt" );
  401. Debug.Log( " Creating nodes file at " + nodesPathname );
  402. IOUtils.SaveTextfileToDisk( finalText, nodesPathname, false );
  403. BuildFullList( false );
  404. }
  405. public virtual bool CheckButton( GUIContent content, GUIStyle style, int buttonId )
  406. {
  407. if( buttonId != m_validButtonId )
  408. {
  409. GUILayout.Label( content, style );
  410. return false;
  411. }
  412. return GUILayout.RepeatButton( content, style );
  413. }
  414. public void FillList( ref List<ContextMenuItem> list, bool forceAllItems )
  415. {
  416. List<ContextMenuItem> allList = forceAllItems ? ParentWindow.ContextMenuInstance.ItemFunctions : ParentWindow.ContextMenuInstance.MenuItems;
  417. list.Clear();
  418. int count = allList.Count;
  419. for( int i = 0; i < count; i++ )
  420. {
  421. list.Add( allList[ i ] );
  422. }
  423. }
  424. public Dictionary<string, PaletteFilterData> BuildFullList( bool forceAllNodes = false )
  425. {
  426. //Only need to build if search filter is active and list is set according to it
  427. if( m_searchFilter.Length > 0 || !m_isActive || m_currentCategories.Count == 0 )
  428. {
  429. m_currentItems.Clear();
  430. m_currentCategories.Clear();
  431. List<ContextMenuItem> allItems = forceAllNodes ? ParentWindow.ContextMenuInstance.ItemFunctions : ParentWindow.ContextMenuInstance.MenuItems;
  432. for( int i = 0; i < allItems.Count; i++ )
  433. {
  434. if( allItems[ i ].Name.IndexOf( m_searchFilter, StringComparison.InvariantCultureIgnoreCase ) >= 0 ||
  435. allItems[ i ].Category.IndexOf( m_searchFilter, StringComparison.InvariantCultureIgnoreCase ) >= 0
  436. )
  437. {
  438. m_currentItems.Add( allItems[ i ] );
  439. if( !m_currentCategories.ContainsKey( allItems[ i ].Category ) )
  440. {
  441. m_currentCategories.Add( allItems[ i ].Category, new PaletteFilterData( m_defaultCategoryVisible ) );
  442. //m_currentCategories[ allItems[ i ].Category ].HasCommunityData = allItems[ i ].NodeAttributes.FromCommunity || m_currentCategories[ allItems[ i ].Category ].HasCommunityData;
  443. }
  444. m_currentCategories[ allItems[ i ].Category ].Contents.Add( allItems[ i ] );
  445. }
  446. }
  447. var categoryEnumerator = m_currentCategories.GetEnumerator();
  448. while( categoryEnumerator.MoveNext() )
  449. {
  450. categoryEnumerator.Current.Value.Contents.Sort( ( x, y ) => x.CompareTo( y, false ) );
  451. }
  452. //mark to force update and take search filter into account
  453. m_forceUpdate = true;
  454. }
  455. return m_currentCategories;
  456. }
  457. private bool IsItemVisible( float currPos )
  458. {
  459. if( ( currPos < m_currentScrollPos.y && ( currPos + ItemSize ) < m_currentScrollPos.y ) ||
  460. ( currPos > ( m_currentScrollPos.y + m_currScrollBarDims.y ) &&
  461. ( currPos + ItemSize ) > ( m_currentScrollPos.y + m_currScrollBarDims.y ) ) )
  462. {
  463. return false;
  464. }
  465. return true;
  466. }
  467. public override void Destroy()
  468. {
  469. base.Destroy();
  470. //m_allItems = null;
  471. m_currentItems.Clear();
  472. m_currentItems = null;
  473. m_currentCategories.Clear();
  474. m_currentCategories = null;
  475. OnPaletteNodeCreateEvt = null;
  476. m_buttonStyle = null;
  477. m_foldoutStyle = null;
  478. }
  479. //public void Clear() {
  480. // m_allItems.Clear();
  481. // m_allItems = new List<ContextMenuItem>();
  482. //}
  483. public bool ForceUpdate { get { return m_forceUpdate; } set { m_forceUpdate = value; } }
  484. }
  485. }