Sin descripción
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.

SGBlackboard.cs 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEditor.Experimental.GraphView;
  6. using UnityEditor.ShaderGraph.Drawing.Views;
  7. using UnityEngine;
  8. using UnityEngine.UIElements;
  9. using UnityEditor.ShaderGraph;
  10. namespace UnityEditor.ShaderGraph.Drawing
  11. {
  12. class BlackboardGroupInfo
  13. {
  14. [SerializeField]
  15. SerializableGuid m_Guid = new SerializableGuid();
  16. internal Guid guid => m_Guid.guid;
  17. [SerializeField]
  18. string m_GroupName;
  19. internal string GroupName
  20. {
  21. get => m_GroupName;
  22. set => m_GroupName = value;
  23. }
  24. BlackboardGroupInfo()
  25. {
  26. }
  27. }
  28. class SGBlackboard : GraphSubWindow, ISGControlledElement<BlackboardController>
  29. {
  30. VisualElement m_ScrollBoundaryTop;
  31. VisualElement m_ScrollBoundaryBottom;
  32. VisualElement m_BottomResizer;
  33. TextField m_PathLabelTextField;
  34. public VisualElement m_VariantExceededHelpBox;
  35. // --- Begin ISGControlledElement implementation
  36. public void OnControllerChanged(ref SGControllerChangedEvent e)
  37. {
  38. }
  39. public void OnControllerEvent(SGControllerEvent e)
  40. {
  41. }
  42. public void SetCurrentVariantUsage(int currentVariantCount, int maxVariantCount)
  43. {
  44. if (currentVariantCount < maxVariantCount && m_VariantExceededHelpBox != null)
  45. {
  46. RemoveAt(0);
  47. m_VariantExceededHelpBox = null;
  48. }
  49. else if (maxVariantCount <= currentVariantCount && m_VariantExceededHelpBox == null)
  50. {
  51. var helpBox = HelpBoxRow.CreateVariantLimitHelpBox(currentVariantCount, maxVariantCount);
  52. m_VariantExceededHelpBox = helpBox;
  53. Insert(0, helpBox);
  54. }
  55. }
  56. public BlackboardController controller
  57. {
  58. get => m_Controller;
  59. set
  60. {
  61. if (m_Controller != value)
  62. {
  63. if (m_Controller != null)
  64. {
  65. m_Controller.UnregisterHandler(this);
  66. }
  67. m_Controller = value;
  68. if (m_Controller != null)
  69. {
  70. m_Controller.RegisterHandler(this);
  71. }
  72. }
  73. }
  74. }
  75. SGController ISGControlledElement.controller => m_Controller;
  76. // --- ISGControlledElement implementation
  77. BlackboardController m_Controller;
  78. BlackboardViewModel m_ViewModel;
  79. BlackboardViewModel ViewModel
  80. {
  81. get => m_ViewModel;
  82. set => m_ViewModel = value;
  83. }
  84. // List of user-made blackboard category views
  85. IList<SGBlackboardCategory> m_BlackboardCategories = new List<SGBlackboardCategory>();
  86. bool m_ScrollToTop = false;
  87. bool m_ScrollToBottom = false;
  88. bool m_EditPathCancelled = false;
  89. bool m_IsUserDraggingItems = false;
  90. int m_InsertIndex = -1;
  91. const int k_DraggedPropertyScrollSpeed = 6;
  92. public override string windowTitle => "Blackboard";
  93. public override string elementName => "SGBlackboard";
  94. public override string styleName => "SGBlackboard";
  95. public override string UxmlName => "Blackboard/SGBlackboard";
  96. public override string layoutKey => "UnityEditor.ShaderGraph.Blackboard";
  97. Action addItemRequested { get; set; }
  98. internal Action hideDragIndicatorAction { get; set; }
  99. GenericMenu m_AddBlackboardItemMenu;
  100. internal GenericMenu addBlackboardItemMenu => m_AddBlackboardItemMenu;
  101. VisualElement m_DragIndicator;
  102. public SGBlackboard(BlackboardViewModel viewModel, BlackboardController controller) : base(viewModel)
  103. {
  104. ViewModel = viewModel;
  105. this.controller = controller;
  106. InitializeAddBlackboardItemMenu();
  107. // By default dock blackboard to left of graph window
  108. windowDockingLayout.dockingLeft = true;
  109. if (m_MainContainer.Q(name: "addButton") is Button addButton)
  110. addButton.clickable.clicked += () =>
  111. {
  112. InitializeAddBlackboardItemMenu();
  113. addItemRequested?.Invoke();
  114. ShowAddPropertyMenu();
  115. };
  116. ParentView.RegisterCallback<FocusOutEvent>(evt => OnDragExitedEvent(new DragExitedEvent()));
  117. m_TitleLabel.text = ViewModel.title;
  118. m_SubTitleLabel.RegisterCallback<MouseDownEvent>(OnMouseDownEvent);
  119. m_SubTitleLabel.text = ViewModel.subtitle;
  120. m_PathLabelTextField = this.Q<TextField>("subTitleTextField");
  121. m_PathLabelTextField.value = ViewModel.subtitle;
  122. m_PathLabelTextField.visible = false;
  123. m_PathLabelTextField.Q("unity-text-input").RegisterCallback<FocusOutEvent>(e => { OnEditPathTextFinished(); }, TrickleDown.TrickleDown);
  124. m_PathLabelTextField.Q("unity-text-input").RegisterCallback<KeyDownEvent>(OnPathTextFieldKeyPressed, TrickleDown.TrickleDown);
  125. // These callbacks make sure the scroll boundary regions and drag indicator don't show up user is not dragging/dropping properties/categories
  126. RegisterCallback<MouseUpEvent>(OnMouseUpEvent);
  127. RegisterCallback<DragExitedEvent>(OnDragExitedEvent);
  128. // Register drag callbacks
  129. RegisterCallback<DragUpdatedEvent>(OnDragUpdatedEvent);
  130. RegisterCallback<DragPerformEvent>(OnDragPerformEvent);
  131. RegisterCallback<DragLeaveEvent>(OnDragLeaveEvent);
  132. RegisterCallback<DragExitedEvent>(OnDragExitedEvent);
  133. // This callback makes sure the drag indicator is shown again if user exits and then re-enters blackboard while dragging
  134. RegisterCallback<MouseEnterEvent>(OnMouseEnterEvent);
  135. m_ScrollBoundaryTop = m_MainContainer.Q(name: "scrollBoundaryTop");
  136. m_ScrollBoundaryTop.RegisterCallback<MouseEnterEvent>(ScrollRegionTopEnter);
  137. m_ScrollBoundaryTop.RegisterCallback<DragUpdatedEvent>(OnFieldDragUpdate);
  138. m_ScrollBoundaryTop.RegisterCallback<MouseLeaveEvent>(ScrollRegionTopLeave);
  139. m_ScrollBoundaryBottom = m_MainContainer.Q(name: "scrollBoundaryBottom");
  140. m_ScrollBoundaryBottom.RegisterCallback<MouseEnterEvent>(ScrollRegionBottomEnter);
  141. m_ScrollBoundaryBottom.RegisterCallback<DragUpdatedEvent>(OnFieldDragUpdate);
  142. m_ScrollBoundaryBottom.RegisterCallback<MouseLeaveEvent>(ScrollRegionBottomLeave);
  143. m_BottomResizer = m_MainContainer.Q("bottom-resize");
  144. HideScrollBoundaryRegions();
  145. // Sets delegate association so scroll boundary regions are hidden when a blackboard property is dropped into graph
  146. if (ParentView is MaterialGraphView materialGraphView)
  147. materialGraphView.blackboardFieldDropDelegate = HideScrollBoundaryRegions;
  148. isWindowScrollable = true;
  149. isWindowResizable = true;
  150. focusable = true;
  151. m_DragIndicator = new VisualElement();
  152. m_DragIndicator.name = "categoryDragIndicator";
  153. m_DragIndicator.style.position = Position.Absolute;
  154. hierarchy.Add(m_DragIndicator);
  155. SetCategoryDragIndicatorVisible(false);
  156. }
  157. void SetCategoryDragIndicatorVisible(bool visible)
  158. {
  159. if (visible && (m_DragIndicator.parent == null))
  160. {
  161. hierarchy.Add(m_DragIndicator);
  162. m_DragIndicator.visible = true;
  163. }
  164. else if ((visible == false) && (m_DragIndicator.parent != null))
  165. {
  166. hierarchy.Remove(m_DragIndicator);
  167. }
  168. }
  169. public void OnDragEnterEvent(DragEnterEvent evt)
  170. {
  171. if (!m_IsUserDraggingItems)
  172. {
  173. m_IsUserDraggingItems = true;
  174. if (scrollableHeight > 0)
  175. {
  176. // Interferes with scrolling functionality of properties with the bottom scroll boundary
  177. m_BottomResizer.style.visibility = Visibility.Hidden;
  178. var contentElement = m_MainContainer.Q(name: "content");
  179. scrollViewIndex = contentElement.IndexOf(m_ScrollView);
  180. contentElement.Insert(scrollViewIndex, m_ScrollBoundaryTop);
  181. scrollViewIndex = contentElement.IndexOf(m_ScrollView);
  182. contentElement.Insert(scrollViewIndex + 1, m_ScrollBoundaryBottom);
  183. }
  184. // If there are any categories in the selection, show drag indicator, otherwise hide
  185. SetCategoryDragIndicatorVisible(selection.OfType<SGBlackboardCategory>().Any());
  186. }
  187. }
  188. public void OnDragExitedEvent(DragExitedEvent evt)
  189. {
  190. SetCategoryDragIndicatorVisible(false);
  191. HideScrollBoundaryRegions();
  192. }
  193. void OnMouseEnterEvent(MouseEnterEvent evt)
  194. {
  195. if (m_IsUserDraggingItems && selection.OfType<SGBlackboardCategory>().Any())
  196. SetCategoryDragIndicatorVisible(true);
  197. }
  198. void HideScrollBoundaryRegions()
  199. {
  200. m_BottomResizer.style.visibility = Visibility.Visible;
  201. m_IsUserDraggingItems = false;
  202. m_ScrollBoundaryTop.RemoveFromHierarchy();
  203. m_ScrollBoundaryBottom.RemoveFromHierarchy();
  204. }
  205. int InsertionIndex(Vector2 pos)
  206. {
  207. VisualElement owner = contentContainer != null ? contentContainer : this;
  208. Vector2 localPos = this.ChangeCoordinatesTo(owner, pos);
  209. int index = BlackboardUtils.GetInsertionIndex(owner, localPos, Children());
  210. // Clamps the index between the min and max of the child indices based on the mouse position relative to the categories on the y-axis (up/down)
  211. // Checking for at least 2 children to make sure Children.First() and Children.Last() don't throw an exception
  212. if (index == -1 && childCount >= 2)
  213. {
  214. index = localPos.y < Children().First().layout.yMin ? 0 :
  215. localPos.y > Children().Last().layout.yMax ? childCount : -1;
  216. }
  217. // Don't allow the default category to be displaced
  218. return Mathf.Clamp(index, 1, index);
  219. }
  220. void OnDragUpdatedEvent(DragUpdatedEvent evt)
  221. {
  222. var selection = DragAndDrop.GetGenericData("DragSelection") as List<ISelectable>;
  223. if (selection == null)
  224. {
  225. SetCategoryDragIndicatorVisible(false);
  226. return;
  227. }
  228. foreach (ISelectable selectedElement in selection)
  229. {
  230. var sourceItem = selectedElement as VisualElement;
  231. // Don't allow user to move the default category
  232. if (sourceItem is SGBlackboardCategory blackboardCategory && blackboardCategory.controller.Model.IsNamedCategory() == false)
  233. {
  234. DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
  235. return;
  236. }
  237. }
  238. Vector2 localPosition = evt.localMousePosition;
  239. m_InsertIndex = InsertionIndex(localPosition);
  240. if (m_InsertIndex != -1)
  241. {
  242. float indicatorY = 0;
  243. if (m_InsertIndex == childCount)
  244. {
  245. if (childCount > 0)
  246. {
  247. VisualElement lastChild = this[childCount - 1];
  248. indicatorY = lastChild.ChangeCoordinatesTo(this, new Vector2(0, lastChild.layout.height + lastChild.resolvedStyle.marginBottom)).y;
  249. }
  250. else
  251. {
  252. indicatorY = this.contentRect.height;
  253. }
  254. }
  255. else
  256. {
  257. VisualElement childAtInsertIndex = this[m_InsertIndex];
  258. indicatorY = childAtInsertIndex.ChangeCoordinatesTo(this, new Vector2(0, -childAtInsertIndex.resolvedStyle.marginTop)).y;
  259. }
  260. m_DragIndicator.style.top = indicatorY - m_DragIndicator.resolvedStyle.height * 0.5f;
  261. DragAndDrop.visualMode = DragAndDropVisualMode.Move;
  262. }
  263. else
  264. {
  265. SetCategoryDragIndicatorVisible(false);
  266. }
  267. evt.StopPropagation();
  268. }
  269. void OnDragPerformEvent(DragPerformEvent evt)
  270. {
  271. // Don't bubble up drop operations onto blackboard upto the graph view, as it leads to nodes being created without users knowledge behind the blackboard
  272. evt.StopPropagation();
  273. var selection = DragAndDrop.GetGenericData("DragSelection") as List<ISelectable>;
  274. if (selection == null || selection.Count == 0)
  275. {
  276. SetCategoryDragIndicatorVisible(false);
  277. return;
  278. }
  279. // Hide the category drag indicator if no categories in selection
  280. if (!selection.OfType<SGBlackboardCategory>().Any())
  281. {
  282. SetCategoryDragIndicatorVisible(false);
  283. }
  284. Vector2 localPosition = evt.localMousePosition;
  285. m_InsertIndex = InsertionIndex(localPosition);
  286. // Any categories in the selection that are from other graphs, would have to be copied as opposed to moving the categories within the same graph
  287. foreach (var item in selection.ToList())
  288. {
  289. if (item is SGBlackboardCategory category)
  290. {
  291. var selectedCategoryData = category.controller.Model;
  292. bool doesCategoryExistInGraph = controller.Model.ContainsCategory(selectedCategoryData);
  293. if (doesCategoryExistInGraph == false)
  294. {
  295. var copyCategoryAction = new CopyCategoryAction();
  296. copyCategoryAction.categoryToCopyReference = selectedCategoryData;
  297. ViewModel.requestModelChangeAction(copyCategoryAction);
  298. selection.Remove(item);
  299. // Remove any child inputs that belong to this category from the selection, to prevent duplicates from being copied onto the graph
  300. foreach (var otherItem in selection.ToList())
  301. {
  302. if (otherItem is SGBlackboardField blackboardField && category.Contains(blackboardField))
  303. selection.Remove(otherItem);
  304. }
  305. }
  306. }
  307. }
  308. // Same as above, but for blackboard items (properties, keywords, dropdowns)
  309. foreach (var item in selection.ToList())
  310. {
  311. if (item is SGBlackboardField blackboardField)
  312. {
  313. var selectedBlackboardItem = blackboardField.controller.Model;
  314. bool doesInputExistInGraph = controller.Model.ContainsInput(selectedBlackboardItem);
  315. if (doesInputExistInGraph == false)
  316. {
  317. var copyShaderInputAction = new CopyShaderInputAction();
  318. copyShaderInputAction.shaderInputToCopy = selectedBlackboardItem;
  319. ViewModel.requestModelChangeAction(copyShaderInputAction);
  320. selection.Remove(item);
  321. }
  322. }
  323. }
  324. var moveCategoryAction = new MoveCategoryAction();
  325. moveCategoryAction.newIndexValue = m_InsertIndex;
  326. moveCategoryAction.categoryGuids = selection.OfType<SGBlackboardCategory>().OrderBy(sgcat => sgcat.GetPosition().y).Select(cat => cat.viewModel.associatedCategoryGuid).ToList();
  327. ViewModel.requestModelChangeAction(moveCategoryAction);
  328. SetCategoryDragIndicatorVisible(false);
  329. }
  330. void OnDragLeaveEvent(DragLeaveEvent evt)
  331. {
  332. DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
  333. SetCategoryDragIndicatorVisible(false);
  334. m_InsertIndex = -1;
  335. }
  336. int scrollViewIndex { get; set; }
  337. void ScrollRegionTopEnter(MouseEnterEvent mouseEnterEvent)
  338. {
  339. if (m_IsUserDraggingItems)
  340. {
  341. SetCategoryDragIndicatorVisible(false);
  342. m_ScrollToTop = true;
  343. m_ScrollToBottom = false;
  344. }
  345. }
  346. void ScrollRegionTopLeave(MouseLeaveEvent mouseLeaveEvent)
  347. {
  348. if (m_IsUserDraggingItems)
  349. {
  350. m_ScrollToTop = false;
  351. // If there are any categories in the selection, show drag indicator, otherwise hide
  352. SetCategoryDragIndicatorVisible(selection.OfType<SGBlackboardCategory>().Any());
  353. }
  354. }
  355. void ScrollRegionBottomEnter(MouseEnterEvent mouseEnterEvent)
  356. {
  357. if (m_IsUserDraggingItems)
  358. {
  359. SetCategoryDragIndicatorVisible(false);
  360. m_ScrollToBottom = true;
  361. m_ScrollToTop = false;
  362. }
  363. }
  364. void ScrollRegionBottomLeave(MouseLeaveEvent mouseLeaveEvent)
  365. {
  366. if (m_IsUserDraggingItems)
  367. {
  368. m_ScrollToBottom = false;
  369. // If there are any categories in the selection, show drag indicator, otherwise hide
  370. SetCategoryDragIndicatorVisible(selection.OfType<SGBlackboardCategory>().Any());
  371. }
  372. }
  373. void OnFieldDragUpdate(DragUpdatedEvent dragUpdatedEvent)
  374. {
  375. // how far is the mouse into the drag boundary.
  376. float dragCoeff
  377. = m_ScrollToTop ? 1 - dragUpdatedEvent.localMousePosition.y / m_ScrollBoundaryBottom.contentRect.height
  378. : m_ScrollToBottom ? dragUpdatedEvent.localMousePosition.y / m_ScrollBoundaryBottom.contentRect.height
  379. : 0;
  380. dragCoeff = Mathf.Clamp(dragCoeff, .15f, .85f);
  381. // factor in fixed base speed and relative to % of total scrollable height.
  382. float dragSpeed = dragCoeff * k_DraggedPropertyScrollSpeed * (scrollableHeight / 100f);
  383. // Lastly, make sure the drag speed can't ever get too slow.
  384. dragSpeed = Mathf.Max(dragSpeed, k_DraggedPropertyScrollSpeed);
  385. if (m_ScrollToTop)
  386. m_ScrollView.scrollOffset = new Vector2(m_ScrollView.scrollOffset.x, Mathf.Clamp(m_ScrollView.scrollOffset.y - dragSpeed, 0, scrollableHeight));
  387. else if (m_ScrollToBottom)
  388. m_ScrollView.scrollOffset = new Vector2(m_ScrollView.scrollOffset.x, Mathf.Clamp(m_ScrollView.scrollOffset.y + dragSpeed, 0, scrollableHeight));
  389. }
  390. void InitializeAddBlackboardItemMenu()
  391. {
  392. m_AddBlackboardItemMenu = new GenericMenu();
  393. if (ViewModel == null)
  394. {
  395. AssertHelpers.Fail("SGBlackboard: View Model is null.");
  396. return;
  397. }
  398. // Add category at top, followed by separator
  399. m_AddBlackboardItemMenu.AddItem(new GUIContent("Category"), false, () => ViewModel.requestModelChangeAction(ViewModel.addCategoryAction));
  400. m_AddBlackboardItemMenu.AddSeparator($"/");
  401. var selectedCategoryGuid = controller.GetFirstSelectedCategoryGuid();
  402. foreach (var nameToAddActionTuple in ViewModel.propertyNameToAddActionMap)
  403. {
  404. string propertyName = nameToAddActionTuple.Key;
  405. AddShaderInputAction addAction = nameToAddActionTuple.Value as AddShaderInputAction;
  406. addAction.categoryToAddItemToGuid = selectedCategoryGuid;
  407. m_AddBlackboardItemMenu.AddItem(new GUIContent(propertyName), false, () => ViewModel.requestModelChangeAction(addAction));
  408. }
  409. m_AddBlackboardItemMenu.AddSeparator($"/");
  410. foreach (var nameToAddActionTuple in ViewModel.defaultKeywordNameToAddActionMap)
  411. {
  412. string defaultKeywordName = nameToAddActionTuple.Key;
  413. AddShaderInputAction addAction = nameToAddActionTuple.Value as AddShaderInputAction;
  414. addAction.categoryToAddItemToGuid = selectedCategoryGuid;
  415. m_AddBlackboardItemMenu.AddItem(new GUIContent($"Keyword/{defaultKeywordName}"), false, () => ViewModel.requestModelChangeAction(addAction));
  416. }
  417. m_AddBlackboardItemMenu.AddSeparator($"Keyword/");
  418. foreach (var nameToAddActionTuple in ViewModel.builtInKeywordNameToAddActionMap)
  419. {
  420. string builtInKeywordName = nameToAddActionTuple.Key;
  421. AddShaderInputAction addAction = nameToAddActionTuple.Value as AddShaderInputAction;
  422. addAction.categoryToAddItemToGuid = selectedCategoryGuid;
  423. m_AddBlackboardItemMenu.AddItem(new GUIContent($"Keyword/{builtInKeywordName}"), false, () => ViewModel.requestModelChangeAction(addAction));
  424. }
  425. foreach (string disabledKeywordName in ViewModel.disabledKeywordNameList)
  426. {
  427. m_AddBlackboardItemMenu.AddDisabledItem(new GUIContent($"Keyword/{disabledKeywordName}"));
  428. }
  429. if (ViewModel.defaultDropdownNameToAdd != null)
  430. {
  431. string defaultDropdownName = ViewModel.defaultDropdownNameToAdd.Item1;
  432. AddShaderInputAction addAction = ViewModel.defaultDropdownNameToAdd.Item2 as AddShaderInputAction;
  433. addAction.categoryToAddItemToGuid = selectedCategoryGuid;
  434. m_AddBlackboardItemMenu.AddItem(new GUIContent($"{defaultDropdownName}"), false, () => ViewModel.requestModelChangeAction(addAction));
  435. }
  436. foreach (string disabledDropdownName in ViewModel.disabledDropdownNameList)
  437. {
  438. m_AddBlackboardItemMenu.AddDisabledItem(new GUIContent(disabledDropdownName));
  439. }
  440. }
  441. void ShowAddPropertyMenu()
  442. {
  443. m_AddBlackboardItemMenu.ShowAsContext();
  444. }
  445. void OnMouseUpEvent(MouseUpEvent evt)
  446. {
  447. this.HideScrollBoundaryRegions();
  448. }
  449. void OnMouseDownEvent(MouseDownEvent evt)
  450. {
  451. if (evt.clickCount == 2 && evt.button == (int)MouseButton.LeftMouse)
  452. {
  453. StartEditingPath();
  454. evt.StopPropagation();
  455. }
  456. }
  457. void StartEditingPath()
  458. {
  459. m_SubTitleLabel.visible = false;
  460. m_PathLabelTextField.visible = true;
  461. m_PathLabelTextField.value = m_SubTitleLabel.text;
  462. m_PathLabelTextField.Q("unity-text-input").Focus();
  463. m_PathLabelTextField.SelectAll();
  464. }
  465. void OnPathTextFieldKeyPressed(KeyDownEvent evt)
  466. {
  467. switch (evt.keyCode)
  468. {
  469. case KeyCode.Escape:
  470. m_EditPathCancelled = true;
  471. m_PathLabelTextField.Q("unity-text-input").Blur();
  472. break;
  473. case KeyCode.Return:
  474. case KeyCode.KeypadEnter:
  475. m_PathLabelTextField.Q("unity-text-input").Blur();
  476. break;
  477. default:
  478. break;
  479. }
  480. }
  481. void OnEditPathTextFinished()
  482. {
  483. m_SubTitleLabel.visible = true;
  484. m_PathLabelTextField.visible = false;
  485. var newPath = m_PathLabelTextField.text;
  486. if (!m_EditPathCancelled && (newPath != m_SubTitleLabel.text))
  487. {
  488. newPath = BlackboardUtils.SanitizePath(newPath);
  489. }
  490. // Request graph path change action
  491. var pathChangeAction = new ChangeGraphPathAction();
  492. pathChangeAction.NewGraphPath = newPath;
  493. ViewModel.requestModelChangeAction(pathChangeAction);
  494. m_SubTitleLabel.text = BlackboardUtils.FormatPath(newPath);
  495. m_EditPathCancelled = false;
  496. }
  497. public override void Dispose()
  498. {
  499. m_PathLabelTextField.Q("unity-text-input").UnregisterCallback<FocusOutEvent>(e => { OnEditPathTextFinished(); }, TrickleDown.TrickleDown);
  500. m_PathLabelTextField.Q("unity-text-input").UnregisterCallback<KeyDownEvent>(OnPathTextFieldKeyPressed, TrickleDown.TrickleDown);
  501. UnregisterCallback<MouseUpEvent>(OnMouseUpEvent);
  502. UnregisterCallback<DragExitedEvent>(OnDragExitedEvent);
  503. UnregisterCallback<DragUpdatedEvent>(OnDragUpdatedEvent);
  504. UnregisterCallback<DragPerformEvent>(OnDragPerformEvent);
  505. UnregisterCallback<DragLeaveEvent>(OnDragLeaveEvent);
  506. UnregisterCallback<DragExitedEvent>(OnDragExitedEvent);
  507. UnregisterCallback<MouseEnterEvent>(OnMouseEnterEvent);
  508. m_ScrollBoundaryTop.UnregisterCallback<MouseEnterEvent>(ScrollRegionTopEnter);
  509. m_ScrollBoundaryTop.UnregisterCallback<DragUpdatedEvent>(OnFieldDragUpdate);
  510. m_ScrollBoundaryTop.UnregisterCallback<MouseLeaveEvent>(ScrollRegionTopLeave);
  511. m_ScrollBoundaryBottom.UnregisterCallback<MouseEnterEvent>(ScrollRegionBottomEnter);
  512. m_ScrollBoundaryBottom.UnregisterCallback<DragUpdatedEvent>(OnFieldDragUpdate);
  513. m_ScrollBoundaryBottom.UnregisterCallback<MouseLeaveEvent>(ScrollRegionBottomLeave);
  514. m_BlackboardCategories.Clear();
  515. m_ViewModel = null;
  516. m_DragIndicator = null;
  517. m_Controller = null;
  518. m_AddBlackboardItemMenu = null;
  519. addItemRequested = null;
  520. m_BottomResizer = null;
  521. m_ScrollBoundaryBottom = null;
  522. m_ScrollBoundaryTop = null;
  523. m_PathLabelTextField = null;
  524. }
  525. }
  526. }