using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEditor.ShaderGraph; namespace UnityEditor.Graphing.Util { [Serializable] sealed class CopyPasteGraph : ISerializationCallbackReceiver { [NonSerialized] HashSet m_Edges = new HashSet(); [NonSerialized] HashSet m_Nodes = new HashSet(); [SerializeField] List m_SerializableNodes = new List(); [SerializeField] List m_SerializableEdges = new List(); public CopyPasteGraph() {} public CopyPasteGraph(IEnumerable nodes, IEnumerable edges) { foreach (var node in nodes) { AddNode(node); foreach (var edge in NodeUtils.GetAllEdges(node)) AddEdge(edge); } foreach (var edge in edges) AddEdge(edge); } public void AddNode(INode node) { m_Nodes.Add(node); } public void AddEdge(IEdge edge) { m_Edges.Add(edge); } public IEnumerable GetNodes() where T : INode { return m_Nodes.OfType(); } public IEnumerable edges { get { return m_Edges; } } public void InsertInGraph(IGraph graph, List remappedNodes, List remappedEdges) { var nodeGuidMap = new Dictionary(); foreach (var node in GetNodes()) { var oldGuid = node.guid; var newGuid = node.RewriteGuid(); nodeGuidMap[oldGuid] = newGuid; var drawState = node.drawState; var position = drawState.position; position.x += 30; position.y += 30; drawState.position = position; node.drawState = drawState; remappedNodes.Add(node); graph.AddNode(node); } // only connect edges within pasted elements, discard // external edges. foreach (var edge in edges) { var outputSlot = edge.outputSlot; var inputSlot = edge.inputSlot; Guid remappedOutputNodeGuid; Guid remappedInputNodeGuid; if (nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid) && nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid)) { var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId); var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId); remappedEdges.Add(graph.Connect(outputSlotRef, inputSlotRef)); } } m_Nodes.Clear(); m_Edges.Clear(); graph.ValidateGraph(); } public void OnBeforeSerialize() { m_SerializableNodes = SerializationHelper.Serialize(m_Nodes); m_SerializableEdges = SerializationHelper.Serialize(m_Edges); } public void OnAfterDeserialize() { var nodes = SerializationHelper.Deserialize(m_SerializableNodes, GraphUtil.GetLegacyTypeRemapping()); m_Nodes.Clear(); foreach (var node in nodes) m_Nodes.Add(node); m_SerializableNodes = null; var edges = SerializationHelper.Deserialize(m_SerializableEdges, GraphUtil.GetLegacyTypeRemapping()); m_Edges.Clear(); foreach (var edge in edges) m_Edges.Add(edge); m_SerializableEdges = null; } internal static CopyPasteGraph FromJson(string copyBuffer) { try { return JsonUtility.FromJson(copyBuffer); } catch { // ignored. just means copy buffer was not a graph :( return null; } } } }