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.
304 lines
9.6 KiB
304 lines
9.6 KiB
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; |
|
} |
|
} |
|
} |
|
}
|
|
|