Ingen beskrivning
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.

CopyPasteGraph.cs 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.Graphing;
  5. using UnityEngine;
  6. using UnityEditor.ShaderGraph;
  7. using UnityEditor.ShaderGraph.Internal;
  8. using UnityEditor.ShaderGraph.Serialization;
  9. namespace UnityEditor.ShaderGraph
  10. {
  11. enum CopyPasteGraphSource
  12. {
  13. Default,
  14. Duplicate
  15. }
  16. [Serializable]
  17. sealed class CopyPasteGraph : JsonObject
  18. {
  19. CopyPasteGraphSource m_CopyPasteGraphSource;
  20. [SerializeField]
  21. List<Edge> m_Edges = new List<Edge>();
  22. [SerializeField]
  23. List<JsonData<AbstractMaterialNode>> m_Nodes = new List<JsonData<AbstractMaterialNode>>();
  24. [SerializeField]
  25. List<JsonData<GroupData>> m_Groups = new List<JsonData<GroupData>>();
  26. [SerializeField]
  27. List<JsonData<StickyNoteData>> m_StickyNotes = new List<JsonData<StickyNoteData>>();
  28. [SerializeField]
  29. List<JsonRef<ShaderInput>> m_Inputs = new List<JsonRef<ShaderInput>>();
  30. [SerializeField]
  31. List<JsonData<CategoryData>> m_Categories = new List<JsonData<CategoryData>>();
  32. // The meta properties are properties that are not copied into the target graph
  33. // but sent along to allow property nodes to still hvae the data from the original
  34. // property present.
  35. [SerializeField]
  36. List<JsonData<AbstractShaderProperty>> m_MetaProperties = new List<JsonData<AbstractShaderProperty>>();
  37. [SerializeField]
  38. List<string> m_MetaPropertyIds = new List<string>();
  39. // The meta keywords are keywords that are required by keyword nodes
  40. // These are copied into the target graph when there is no collision
  41. [SerializeField]
  42. List<JsonData<ShaderKeyword>> m_MetaKeywords = new List<JsonData<ShaderKeyword>>();
  43. [SerializeField]
  44. List<string> m_MetaKeywordIds = new List<string>();
  45. [SerializeField]
  46. List<JsonData<ShaderDropdown>> m_MetaDropdowns = new List<JsonData<ShaderDropdown>>();
  47. [SerializeField]
  48. List<string> m_MetaDropdownIds = new List<string>();
  49. public CopyPasteGraph() { }
  50. public CopyPasteGraph(IEnumerable<GroupData> groups,
  51. IEnumerable<AbstractMaterialNode> nodes,
  52. IEnumerable<Edge> edges,
  53. IEnumerable<ShaderInput> inputs,
  54. IEnumerable<CategoryData> categories,
  55. IEnumerable<AbstractShaderProperty> metaProperties,
  56. IEnumerable<ShaderKeyword> metaKeywords,
  57. IEnumerable<ShaderDropdown> metaDropdowns,
  58. IEnumerable<StickyNoteData> notes,
  59. bool keepOutputEdges = false,
  60. bool removeOrphanEdges = true,
  61. CopyPasteGraphSource copyPasteGraphSource = CopyPasteGraphSource.Default)
  62. {
  63. m_CopyPasteGraphSource = copyPasteGraphSource;
  64. if (groups != null)
  65. {
  66. foreach (var groupData in groups)
  67. AddGroup(groupData);
  68. }
  69. if (notes != null)
  70. {
  71. foreach (var stickyNote in notes)
  72. AddNote(stickyNote);
  73. }
  74. var nodeSet = new HashSet<AbstractMaterialNode>();
  75. if (nodes != null)
  76. {
  77. foreach (var node in nodes.Distinct())
  78. {
  79. if (!node.canCopyNode)
  80. {
  81. throw new InvalidOperationException($"Cannot copy node {node.name} ({node.objectId}).");
  82. }
  83. nodeSet.Add(node);
  84. AddNode(node);
  85. foreach (var edge in NodeUtils.GetAllEdges(node))
  86. AddEdge((Edge)edge);
  87. }
  88. }
  89. if (edges != null)
  90. {
  91. foreach (var edge in edges)
  92. AddEdge(edge);
  93. }
  94. if (inputs != null)
  95. {
  96. foreach (var input in inputs)
  97. AddInput(input);
  98. }
  99. if (categories != null)
  100. {
  101. foreach (var category in categories)
  102. AddCategory(category);
  103. }
  104. if (metaProperties != null)
  105. {
  106. foreach (var metaProperty in metaProperties.Distinct())
  107. AddMetaProperty(metaProperty);
  108. }
  109. if (metaKeywords != null)
  110. {
  111. foreach (var metaKeyword in metaKeywords.Distinct())
  112. AddMetaKeyword(metaKeyword);
  113. }
  114. if (metaDropdowns != null)
  115. {
  116. foreach (var metaDropdown in metaDropdowns.Distinct())
  117. AddMetaDropdown(metaDropdown);
  118. }
  119. var distinct = m_Edges.Distinct();
  120. if (removeOrphanEdges)
  121. {
  122. distinct = distinct.Where(edge => nodeSet.Contains(edge.inputSlot.node) || (keepOutputEdges && nodeSet.Contains(edge.outputSlot.node)));
  123. }
  124. m_Edges = distinct.ToList();
  125. }
  126. public bool IsInputCategorized(ShaderInput shaderInput)
  127. {
  128. foreach (var category in categories)
  129. {
  130. if (category.IsItemInCategory(shaderInput))
  131. return true;
  132. }
  133. return false;
  134. }
  135. // The only situation in which an input has an identical reference name to another input in a category, while not being the same instance, is if they are duplicates
  136. public bool IsInputDuplicatedFromCategory(ShaderInput shaderInput, CategoryData inputCategory, GraphData targetGraphData)
  137. {
  138. foreach (var child in inputCategory.Children)
  139. {
  140. if (child.referenceName.Equals(shaderInput.referenceName, StringComparison.Ordinal) && child.objectId != shaderInput.objectId)
  141. {
  142. return true;
  143. }
  144. }
  145. // Need to check if they share same graph owner as well, if not then we can early out
  146. bool inputBelongsToTargetGraph = targetGraphData.ContainsInput(shaderInput);
  147. if (inputBelongsToTargetGraph == false)
  148. return false;
  149. return false;
  150. }
  151. void AddGroup(GroupData group)
  152. {
  153. m_Groups.Add(group);
  154. }
  155. void AddNote(StickyNoteData stickyNote)
  156. {
  157. m_StickyNotes.Add(stickyNote);
  158. }
  159. void AddNode(AbstractMaterialNode node)
  160. {
  161. m_Nodes.Add(node);
  162. }
  163. void AddEdge(Edge edge)
  164. {
  165. m_Edges.Add(edge);
  166. }
  167. void AddInput(ShaderInput input)
  168. {
  169. m_Inputs.Add(input);
  170. }
  171. void AddCategory(CategoryData category)
  172. {
  173. m_Categories.Add(category);
  174. }
  175. void AddMetaProperty(AbstractShaderProperty metaProperty)
  176. {
  177. m_MetaProperties.Add(metaProperty);
  178. m_MetaPropertyIds.Add(metaProperty.objectId);
  179. }
  180. void AddMetaKeyword(ShaderKeyword metaKeyword)
  181. {
  182. m_MetaKeywords.Add(metaKeyword);
  183. m_MetaKeywordIds.Add(metaKeyword.objectId);
  184. }
  185. void AddMetaDropdown(ShaderDropdown metaDropdown)
  186. {
  187. m_MetaDropdowns.Add(metaDropdown);
  188. m_MetaDropdownIds.Add(metaDropdown.objectId);
  189. }
  190. public IEnumerable<T> GetNodes<T>()
  191. {
  192. return m_Nodes.SelectValue().OfType<T>();
  193. }
  194. public DataValueEnumerable<GroupData> groups => m_Groups.SelectValue();
  195. public DataValueEnumerable<StickyNoteData> stickyNotes => m_StickyNotes.SelectValue();
  196. public IEnumerable<Edge> edges
  197. {
  198. get { return m_Edges; }
  199. }
  200. public RefValueEnumerable<ShaderInput> inputs
  201. {
  202. get { return m_Inputs.SelectValue(); }
  203. }
  204. public DataValueEnumerable<CategoryData> categories
  205. {
  206. get { return m_Categories.SelectValue(); }
  207. }
  208. public DataValueEnumerable<AbstractShaderProperty> metaProperties
  209. {
  210. get { return m_MetaProperties.SelectValue(); }
  211. }
  212. public DataValueEnumerable<ShaderKeyword> metaKeywords
  213. {
  214. get { return m_MetaKeywords.SelectValue(); }
  215. }
  216. public DataValueEnumerable<ShaderDropdown> metaDropdowns
  217. {
  218. get { return m_MetaDropdowns.SelectValue(); }
  219. }
  220. public IEnumerable<string> metaPropertyIds => m_MetaPropertyIds;
  221. public IEnumerable<string> metaKeywordIds => m_MetaKeywordIds;
  222. public CopyPasteGraphSource copyPasteGraphSource => m_CopyPasteGraphSource;
  223. public override void OnAfterMultiDeserialize(string json)
  224. {
  225. // should we add support for versioning old CopyPasteGraphs from old versions of Unity?
  226. // so you can copy from old paste to new
  227. foreach (var node in m_Nodes.SelectValue())
  228. {
  229. node.UpdateNodeAfterDeserialization();
  230. node.SetupSlots();
  231. }
  232. }
  233. internal static CopyPasteGraph FromJson(string copyBuffer, GraphData targetGraph)
  234. {
  235. try
  236. {
  237. var graph = new CopyPasteGraph();
  238. MultiJson.Deserialize(graph, copyBuffer, targetGraph, true);
  239. return graph;
  240. }
  241. catch
  242. {
  243. // ignored. just means copy buffer was not a graph :(
  244. return null;
  245. }
  246. }
  247. }
  248. }