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