305 lines
9.6 KiB
C#
305 lines
9.6 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|