Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

PropertyNodeView.cs 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. using System;
  2. using System.Linq;
  3. using UnityEditor.Experimental.GraphView;
  4. using UnityEditor.Graphing;
  5. using UnityEditor.Rendering;
  6. using UnityEditor.ShaderGraph.Drawing;
  7. using UnityEditor.ShaderGraph.Drawing.Controls;
  8. using UnityEditor.ShaderGraph.Internal;
  9. using UnityEngine;
  10. using UnityEngine.UIElements;
  11. using UnityEditor.ShaderGraph.Drawing.Inspector.PropertyDrawers;
  12. using ContextualMenuManipulator = UnityEngine.UIElements.ContextualMenuManipulator;
  13. namespace UnityEditor.ShaderGraph
  14. {
  15. sealed class PropertyNodeView : TokenNode, IShaderNodeView, IInspectable, IShaderInputObserver
  16. {
  17. static readonly Texture2D exposedIcon = Resources.Load<Texture2D>("GraphView/Nodes/BlackboardFieldExposed");
  18. public static StyleSheet styleSheet;
  19. // When the properties are changed, this delegate is used to trigger an update in the view that represents those properties
  20. Action m_TriggerInspectorUpdate;
  21. Action m_ResetReferenceNameAction;
  22. public PropertyNodeView(PropertyNode node, EdgeConnectorListener edgeConnectorListener)
  23. : base(null, ShaderPort.Create(node.GetOutputSlots<MaterialSlot>().First(), edgeConnectorListener))
  24. {
  25. if (styleSheet == null)
  26. styleSheet = Resources.Load<StyleSheet>("Styles/PropertyNodeView");
  27. styleSheets.Add(styleSheet);
  28. this.node = node;
  29. viewDataKey = node.objectId.ToString();
  30. userData = node;
  31. // Getting the generatePropertyBlock property to see if it is exposed or not
  32. UpdateIcon();
  33. // Setting the position of the node, otherwise it ends up in the center of the canvas
  34. SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));
  35. // Removing the title label since it is not used and taking up space
  36. this.Q("title-label").RemoveFromHierarchy();
  37. // Add disabled overlay
  38. Add(new VisualElement() { name = "disabledOverlay", pickingMode = PickingMode.Ignore });
  39. // Update active state
  40. SetActive(node.isActive);
  41. // Registering the hovering callbacks for highlighting
  42. RegisterCallback<MouseEnterEvent>(OnMouseHover);
  43. RegisterCallback<MouseLeaveEvent>(OnMouseHover);
  44. // add the right click context menu
  45. IManipulator contextMenuManipulator = new ContextualMenuManipulator(AddContextMenuOptions);
  46. this.AddManipulator(contextMenuManipulator);
  47. }
  48. // Updating the text label of the output slot
  49. void UpdateDisplayName()
  50. {
  51. var slot = node.GetSlots<MaterialSlot>().ToList().First();
  52. this.Q<Label>("type").text = slot.displayName;
  53. }
  54. public Node gvNode => this;
  55. public AbstractMaterialNode node { get; }
  56. public VisualElement colorElement => null;
  57. public string inspectorTitle => $"{property.displayName} (Node)";
  58. [Inspectable("ShaderInput", null)]
  59. AbstractShaderProperty property => (node as PropertyNode)?.property;
  60. public object GetObjectToInspect()
  61. {
  62. return property;
  63. }
  64. public void SupplyDataToPropertyDrawer(IPropertyDrawer propertyDrawer, Action inspectorUpdateDelegate)
  65. {
  66. if (propertyDrawer is ShaderInputPropertyDrawer shaderInputPropertyDrawer)
  67. {
  68. var propNode = node as PropertyNode;
  69. var graph = node.owner as GraphData;
  70. var shaderInputViewModel = new ShaderInputViewModel()
  71. {
  72. model = property,
  73. parentView = null,
  74. isSubGraph = graph.isSubGraph,
  75. isInputExposed = property.isExposed,
  76. inputName = property.displayName,
  77. inputTypeName = property.GetPropertyTypeString(),
  78. requestModelChangeAction = this.RequestModelChange
  79. };
  80. shaderInputPropertyDrawer.GetViewModel(shaderInputViewModel, node.owner, this.OnDisplayNameUpdated);
  81. this.m_TriggerInspectorUpdate = inspectorUpdateDelegate;
  82. this.m_ResetReferenceNameAction = shaderInputPropertyDrawer.ResetReferenceName;
  83. }
  84. }
  85. void RequestModelChange(IGraphDataAction changeAction)
  86. {
  87. node.owner?.owner.graphDataStore.Dispatch(changeAction);
  88. }
  89. internal static void AddMainColorMenuOptions(ContextualMenuPopulateEvent evt, ColorShaderProperty colorProp, GraphData graphData, Action inspectorUpdateAction)
  90. {
  91. if (!graphData.isSubGraph)
  92. {
  93. if (!colorProp.isMainColor)
  94. {
  95. evt.menu.AppendAction(
  96. "Set as Main Color",
  97. e =>
  98. {
  99. ColorShaderProperty col = graphData.GetMainColor();
  100. if (col != null)
  101. {
  102. if (EditorUtility.DisplayDialog("Change Main Color Action", $"Are you sure you want to change the Main Color from {col.displayName} to {colorProp.displayName}?", "Yes", "Cancel"))
  103. {
  104. graphData.owner.RegisterCompleteObjectUndo("Change Main Color");
  105. col.isMainColor = false;
  106. colorProp.isMainColor = true;
  107. inspectorUpdateAction();
  108. }
  109. return;
  110. }
  111. graphData.owner.RegisterCompleteObjectUndo("Set Main Color");
  112. colorProp.isMainColor = true;
  113. inspectorUpdateAction();
  114. });
  115. }
  116. else
  117. {
  118. evt.menu.AppendAction(
  119. "Clear Main Color",
  120. e =>
  121. {
  122. graphData.owner.RegisterCompleteObjectUndo("Clear Main Color");
  123. colorProp.isMainColor = false;
  124. inspectorUpdateAction();
  125. });
  126. }
  127. }
  128. }
  129. internal static void AddMainTextureMenuOptions(ContextualMenuPopulateEvent evt, Texture2DShaderProperty texProp, GraphData graphData, Action inspectorUpdateAction)
  130. {
  131. if (!graphData.isSubGraph)
  132. {
  133. if (!texProp.isMainTexture)
  134. {
  135. evt.menu.AppendAction(
  136. "Set as Main Texture",
  137. e =>
  138. {
  139. Texture2DShaderProperty tex = graphData.GetMainTexture();
  140. // There's already a main texture, ask the user if they want to change and toggle the old one to not be main
  141. if (tex != null)
  142. {
  143. if (EditorUtility.DisplayDialog("Change Main Texture Action", $"Are you sure you want to change the Main Texture from {tex.displayName} to {texProp.displayName}?", "Yes", "Cancel"))
  144. {
  145. graphData.owner.RegisterCompleteObjectUndo("Change Main Texture");
  146. tex.isMainTexture = false;
  147. texProp.isMainTexture = true;
  148. inspectorUpdateAction();
  149. }
  150. return;
  151. }
  152. graphData.owner.RegisterCompleteObjectUndo("Set Main Texture");
  153. texProp.isMainTexture = true;
  154. inspectorUpdateAction();
  155. });
  156. }
  157. else
  158. {
  159. evt.menu.AppendAction(
  160. "Clear Main Texture",
  161. e =>
  162. {
  163. graphData.owner.RegisterCompleteObjectUndo("Clear Main Texture");
  164. texProp.isMainTexture = false;
  165. inspectorUpdateAction();
  166. });
  167. }
  168. }
  169. }
  170. void AddContextMenuOptions(ContextualMenuPopulateEvent evt)
  171. {
  172. // Checks if the reference name has been overridden and appends menu action to reset it, if so
  173. if (property.isRenamable &&
  174. !string.IsNullOrEmpty(property.overrideReferenceName))
  175. {
  176. evt.menu.AppendAction(
  177. "Reset Reference",
  178. e =>
  179. {
  180. m_ResetReferenceNameAction();
  181. DirtyNodes(ModificationScope.Graph);
  182. },
  183. DropdownMenuAction.AlwaysEnabled);
  184. }
  185. if (property is ColorShaderProperty colorProp)
  186. {
  187. AddMainColorMenuOptions(evt, colorProp, node.owner, m_TriggerInspectorUpdate);
  188. }
  189. if (property is Texture2DShaderProperty texProp)
  190. {
  191. AddMainTextureMenuOptions(evt, texProp, node.owner, m_TriggerInspectorUpdate);
  192. }
  193. }
  194. void OnDisplayNameUpdated(bool triggerPropertyViewUpdate = false, ModificationScope modificationScope = ModificationScope.Node)
  195. {
  196. if (triggerPropertyViewUpdate)
  197. m_TriggerInspectorUpdate?.Invoke();
  198. UpdateDisplayName();
  199. }
  200. void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node)
  201. {
  202. var graph = node.owner as GraphData;
  203. var colorManager = GetFirstAncestorOfType<GraphEditorView>().colorManager;
  204. var nodes = GetFirstAncestorOfType<GraphEditorView>().graphView.Query<MaterialNodeView>().ToList();
  205. colorManager.SetNodesDirty(nodes);
  206. colorManager.UpdateNodeViews(nodes);
  207. foreach (var node in graph.GetNodes<PropertyNode>())
  208. {
  209. node.Dirty(modificationScope);
  210. }
  211. }
  212. public void SetColor(Color newColor)
  213. {
  214. // Nothing to do here yet
  215. }
  216. public void ResetColor()
  217. {
  218. // Nothing to do here yet
  219. }
  220. public void UpdatePortInputTypes()
  221. {
  222. }
  223. public void UpdateDropdownEntries()
  224. {
  225. }
  226. public bool FindPort(SlotReference slot, out ShaderPort port)
  227. {
  228. port = output as ShaderPort;
  229. return port != null && port.slot.slotReference.Equals(slot);
  230. }
  231. void UpdateIcon()
  232. {
  233. var graph = node?.owner as GraphData;
  234. if ((graph != null) && (property != null))
  235. icon = (graph.isSubGraph || property.isExposed) ? exposedIcon : null;
  236. else
  237. icon = null;
  238. }
  239. public void OnModified(ModificationScope scope)
  240. {
  241. //disconnected property nodes are always active
  242. if (!node.IsSlotConnected(PropertyNode.OutputSlotId))
  243. node.SetActive(true);
  244. SetActive(node.isActive);
  245. if (scope == ModificationScope.Graph)
  246. {
  247. UpdateIcon();
  248. }
  249. if (scope == ModificationScope.Topological || scope == ModificationScope.Node)
  250. {
  251. UpdateDisplayName();
  252. }
  253. }
  254. public void SetActive(bool state)
  255. {
  256. // Setup
  257. var disabledString = "disabled";
  258. if (!state)
  259. {
  260. // Add elements to disabled class list
  261. AddToClassList(disabledString);
  262. }
  263. else
  264. {
  265. // Remove elements from disabled class list
  266. RemoveFromClassList(disabledString);
  267. }
  268. }
  269. public void AttachMessage(string errString, ShaderCompilerMessageSeverity severity)
  270. {
  271. ClearMessage();
  272. IconBadge badge;
  273. if (severity == ShaderCompilerMessageSeverity.Error)
  274. {
  275. badge = IconBadge.CreateError(errString);
  276. }
  277. else
  278. {
  279. badge = IconBadge.CreateComment(errString);
  280. }
  281. Add(badge);
  282. badge.AttachTo(this, SpriteAlignment.RightCenter);
  283. }
  284. public void ClearMessage()
  285. {
  286. var badge = this.Q<IconBadge>();
  287. if (badge != null)
  288. {
  289. badge.Detach();
  290. badge.RemoveFromHierarchy();
  291. }
  292. }
  293. SGBlackboardRow GetAssociatedBlackboardRow()
  294. {
  295. var graphView = GetFirstAncestorOfType<GraphEditorView>();
  296. var blackboardController = graphView?.blackboardController;
  297. if (blackboardController == null)
  298. return null;
  299. var propNode = (PropertyNode)node;
  300. return blackboardController.GetBlackboardRow(propNode.property);
  301. }
  302. void OnMouseHover(EventBase evt)
  303. {
  304. var propRow = GetAssociatedBlackboardRow();
  305. if (propRow != null)
  306. {
  307. if (evt.eventTypeId == MouseEnterEvent.TypeId())
  308. {
  309. propRow.AddToClassList("hovered");
  310. }
  311. else
  312. {
  313. propRow.RemoveFromClassList("hovered");
  314. }
  315. }
  316. }
  317. public void Dispose()
  318. {
  319. var propRow = GetAssociatedBlackboardRow();
  320. // If this node view is deleted, remove highlighting from associated blackboard row
  321. if (propRow != null)
  322. {
  323. propRow.RemoveFromClassList("hovered");
  324. }
  325. styleSheets.Clear();
  326. m_TriggerInspectorUpdate = null;
  327. m_ResetReferenceNameAction = null;
  328. UnregisterCallback<MouseEnterEvent>(OnMouseHover);
  329. UnregisterCallback<MouseLeaveEvent>(OnMouseHover);
  330. }
  331. public void OnShaderInputUpdated(ModificationScope modificationScope)
  332. {
  333. if (modificationScope == ModificationScope.Layout)
  334. UpdateDisplayName();
  335. }
  336. }
  337. }