123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor.Graphing;
- using UnityEngine;
- using UnityEditor.ShaderGraph;
- using UnityEditor.ShaderGraph.Internal;
- using UnityEditor.ShaderGraph.Serialization;
-
- namespace UnityEditor.ShaderGraph
- {
- enum CopyPasteGraphSource
- {
- Default,
- Duplicate
- }
-
- [Serializable]
- sealed class CopyPasteGraph : JsonObject
- {
- CopyPasteGraphSource m_CopyPasteGraphSource;
-
- [SerializeField]
- List<Edge> m_Edges = new List<Edge>();
-
- [SerializeField]
- List<JsonData<AbstractMaterialNode>> m_Nodes = new List<JsonData<AbstractMaterialNode>>();
-
- [SerializeField]
- List<JsonData<GroupData>> m_Groups = new List<JsonData<GroupData>>();
-
- [SerializeField]
- List<JsonData<StickyNoteData>> m_StickyNotes = new List<JsonData<StickyNoteData>>();
-
- [SerializeField]
- List<JsonRef<ShaderInput>> m_Inputs = new List<JsonRef<ShaderInput>>();
-
- [SerializeField]
- List<JsonData<CategoryData>> m_Categories = new List<JsonData<CategoryData>>();
-
- // The meta properties are properties that are not copied into the target graph
- // but sent along to allow property nodes to still hvae the data from the original
- // property present.
- [SerializeField]
- List<JsonData<AbstractShaderProperty>> m_MetaProperties = new List<JsonData<AbstractShaderProperty>>();
-
- [SerializeField]
- List<string> m_MetaPropertyIds = new List<string>();
-
- // The meta keywords are keywords that are required by keyword nodes
- // These are copied into the target graph when there is no collision
- [SerializeField]
- List<JsonData<ShaderKeyword>> m_MetaKeywords = new List<JsonData<ShaderKeyword>>();
-
- [SerializeField]
- List<string> m_MetaKeywordIds = new List<string>();
-
- [SerializeField]
- List<JsonData<ShaderDropdown>> m_MetaDropdowns = new List<JsonData<ShaderDropdown>>();
-
- [SerializeField]
- List<string> m_MetaDropdownIds = new List<string>();
-
- public CopyPasteGraph() { }
-
- public CopyPasteGraph(IEnumerable<GroupData> groups,
- IEnumerable<AbstractMaterialNode> nodes,
- IEnumerable<Edge> edges,
- IEnumerable<ShaderInput> inputs,
- IEnumerable<CategoryData> categories,
- IEnumerable<AbstractShaderProperty> metaProperties,
- IEnumerable<ShaderKeyword> metaKeywords,
- IEnumerable<ShaderDropdown> metaDropdowns,
- IEnumerable<StickyNoteData> notes,
- bool keepOutputEdges = false,
- bool removeOrphanEdges = true,
- CopyPasteGraphSource copyPasteGraphSource = CopyPasteGraphSource.Default)
- {
- m_CopyPasteGraphSource = copyPasteGraphSource;
- if (groups != null)
- {
- foreach (var groupData in groups)
- AddGroup(groupData);
- }
-
- if (notes != null)
- {
- foreach (var stickyNote in notes)
- AddNote(stickyNote);
- }
-
- var nodeSet = new HashSet<AbstractMaterialNode>();
-
- if (nodes != null)
- {
- foreach (var node in nodes.Distinct())
- {
- if (!node.canCopyNode)
- {
- throw new InvalidOperationException($"Cannot copy node {node.name} ({node.objectId}).");
- }
-
- nodeSet.Add(node);
- AddNode(node);
- foreach (var edge in NodeUtils.GetAllEdges(node))
- AddEdge((Edge)edge);
- }
- }
-
- if (edges != null)
- {
- foreach (var edge in edges)
- AddEdge(edge);
- }
-
- if (inputs != null)
- {
- foreach (var input in inputs)
- AddInput(input);
- }
-
- if (categories != null)
- {
- foreach (var category in categories)
- AddCategory(category);
- }
-
- if (metaProperties != null)
- {
- foreach (var metaProperty in metaProperties.Distinct())
- AddMetaProperty(metaProperty);
- }
-
- if (metaKeywords != null)
- {
- foreach (var metaKeyword in metaKeywords.Distinct())
- AddMetaKeyword(metaKeyword);
- }
-
- if (metaDropdowns != null)
- {
- foreach (var metaDropdown in metaDropdowns.Distinct())
- AddMetaDropdown(metaDropdown);
- }
-
- var distinct = m_Edges.Distinct();
- if (removeOrphanEdges)
- {
- distinct = distinct.Where(edge => nodeSet.Contains(edge.inputSlot.node) || (keepOutputEdges && nodeSet.Contains(edge.outputSlot.node)));
- }
- m_Edges = distinct.ToList();
- }
-
- public bool IsInputCategorized(ShaderInput shaderInput)
- {
- foreach (var category in categories)
- {
- if (category.IsItemInCategory(shaderInput))
- return true;
- }
-
- return false;
- }
-
- // 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
- public bool IsInputDuplicatedFromCategory(ShaderInput shaderInput, CategoryData inputCategory, GraphData targetGraphData)
- {
- foreach (var child in inputCategory.Children)
- {
- if (child.referenceName.Equals(shaderInput.referenceName, StringComparison.Ordinal) && child.objectId != shaderInput.objectId)
- {
- return true;
- }
- }
-
- // Need to check if they share same graph owner as well, if not then we can early out
- bool inputBelongsToTargetGraph = targetGraphData.ContainsInput(shaderInput);
- if (inputBelongsToTargetGraph == false)
- return false;
-
- return false;
- }
-
- void AddGroup(GroupData group)
- {
- m_Groups.Add(group);
- }
-
- void AddNote(StickyNoteData stickyNote)
- {
- m_StickyNotes.Add(stickyNote);
- }
-
- void AddNode(AbstractMaterialNode node)
- {
- m_Nodes.Add(node);
- }
-
- void AddEdge(Edge edge)
- {
- m_Edges.Add(edge);
- }
-
- void AddInput(ShaderInput input)
- {
- m_Inputs.Add(input);
- }
-
- void AddCategory(CategoryData category)
- {
- m_Categories.Add(category);
- }
-
- void AddMetaProperty(AbstractShaderProperty metaProperty)
- {
- m_MetaProperties.Add(metaProperty);
- m_MetaPropertyIds.Add(metaProperty.objectId);
- }
-
- void AddMetaKeyword(ShaderKeyword metaKeyword)
- {
- m_MetaKeywords.Add(metaKeyword);
- m_MetaKeywordIds.Add(metaKeyword.objectId);
- }
-
- void AddMetaDropdown(ShaderDropdown metaDropdown)
- {
- m_MetaDropdowns.Add(metaDropdown);
- m_MetaDropdownIds.Add(metaDropdown.objectId);
- }
-
- public IEnumerable<T> GetNodes<T>()
- {
- return m_Nodes.SelectValue().OfType<T>();
- }
-
- public DataValueEnumerable<GroupData> groups => m_Groups.SelectValue();
-
- public DataValueEnumerable<StickyNoteData> stickyNotes => m_StickyNotes.SelectValue();
-
- public IEnumerable<Edge> edges
- {
- get { return m_Edges; }
- }
-
- public RefValueEnumerable<ShaderInput> inputs
- {
- get { return m_Inputs.SelectValue(); }
- }
-
- public DataValueEnumerable<CategoryData> categories
- {
- get { return m_Categories.SelectValue(); }
- }
-
- public DataValueEnumerable<AbstractShaderProperty> metaProperties
- {
- get { return m_MetaProperties.SelectValue(); }
- }
-
- public DataValueEnumerable<ShaderKeyword> metaKeywords
- {
- get { return m_MetaKeywords.SelectValue(); }
- }
-
- public DataValueEnumerable<ShaderDropdown> metaDropdowns
- {
- get { return m_MetaDropdowns.SelectValue(); }
- }
-
- public IEnumerable<string> metaPropertyIds => m_MetaPropertyIds;
-
- public IEnumerable<string> metaKeywordIds => m_MetaKeywordIds;
-
- public CopyPasteGraphSource copyPasteGraphSource => m_CopyPasteGraphSource;
-
- public override void OnAfterMultiDeserialize(string json)
- {
- // should we add support for versioning old CopyPasteGraphs from old versions of Unity?
- // so you can copy from old paste to new
-
- foreach (var node in m_Nodes.SelectValue())
- {
- node.UpdateNodeAfterDeserialization();
- node.SetupSlots();
- }
- }
-
- internal static CopyPasteGraph FromJson(string copyBuffer, GraphData targetGraph)
- {
- try
- {
- var graph = new CopyPasteGraph();
- MultiJson.Deserialize(graph, copyBuffer, targetGraph, true);
- return graph;
- }
- catch
- {
- // ignored. just means copy buffer was not a graph :(
- return null;
- }
- }
- }
- }
|