Tim Cooper
8 年前
当前提交
c565a8d4
共有 27 个文件被更改,包括 1282 次插入 和 1293 次删除
-
496MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/CopySelected.cs
-
120MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/DeleteSelected.cs
-
420MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/DrawableNode.cs
-
484MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphDataSource.cs
-
50MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs
-
1MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/IGraphElementView.cs
-
94MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphDataSource.cs
-
46MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphElementView.cs
-
7MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphNode.cs
-
186MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphView.cs
-
50MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeAnchorData.cs
-
1MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeData.cs
-
134MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/NullInputProxy.cs
-
4MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/IGraph.cs
-
12MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/INode.cs
-
7MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/AbstractMaterialNodeUI.cs
-
32MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/PropertyNodeTests.cs
-
402MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/ShaderGenerationTest.cs
-
2MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/PropertyGeneratorTests.cs
-
1MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/PropertyNodeTests.cs
-
1MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/ShaderGeneratorTests.cs
-
2MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Graphs/MaterialGraph.cs
-
1MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Graphs/PixelGraph.cs
-
4MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/TextureNode.cs
-
10MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphInputNode.cs
-
6MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphNode.cs
-
2MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Util/ShaderGenerator.cs
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
/* |
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
internal class CopyPasteGraph : ISerializationCallbackReceiver |
|||
{ |
|||
[NonSerialized] |
|||
private HashSet<IEdge> m_Edges = new HashSet<IEdge>(); |
|||
|
|||
[NonSerialized] |
|||
private HashSet<INode> m_Nodes = new HashSet<INode>(); |
|||
|
|||
[SerializeField] |
|||
List<SerializationHelper.JSONSerializedElement> m_SerializableNodes = new List<SerializationHelper.JSONSerializedElement>(); |
|||
|
|||
[SerializeField] |
|||
List<SerializationHelper.JSONSerializedElement> m_SerializableEdges = new List<SerializationHelper.JSONSerializedElement>(); |
|||
|
|||
public virtual void AddNode(INode node) |
|||
{ |
|||
m_Nodes.Add(node); |
|||
} |
|||
|
|||
public void AddEdge(IEdge edge) |
|||
{ |
|||
m_Edges.Add(edge); |
|||
} |
|||
|
|||
public IEnumerable<T> GetNodes<T>() where T : INode |
|||
{ |
|||
return m_Nodes.OfType<T>(); |
|||
} |
|||
|
|||
public IEnumerable<IEdge> edges |
|||
{ |
|||
get { return m_Edges; } |
|||
} |
|||
|
|||
public virtual void OnBeforeSerialize() |
|||
{ |
|||
m_SerializableNodes = SerializationHelper.Serialize<INode>(m_Nodes); |
|||
m_SerializableEdges = SerializationHelper.Serialize<IEdge>(m_Edges); |
|||
} |
|||
|
|||
public virtual void OnAfterDeserialize() |
|||
{ |
|||
var nodes = SerializationHelper.Deserialize<INode>(m_SerializableNodes); |
|||
m_Nodes.Clear(); |
|||
foreach (var node in nodes) |
|||
m_Nodes.Add(node); |
|||
m_SerializableNodes = null; |
|||
|
|||
var edges = SerializationHelper.Deserialize<IEdge>(m_SerializableEdges); |
|||
m_Edges.Clear(); |
|||
foreach (var edge in edges) |
|||
m_Edges.Add(edge); |
|||
m_SerializableEdges = null; |
|||
} |
|||
} |
|||
|
|||
internal class CopySelected : IManipulate |
|||
{ |
|||
public delegate void CopyElements(List<CanvasElement> elements); |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ValidateCommand += Validate; |
|||
element.ExecuteCommand += CopyPaste; |
|||
} |
|||
|
|||
private bool Validate(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Copy" && e.commandName != "Paste" && e.commandName != "Duplicate") |
|||
return false; |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool CopyPaste(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Copy" && e.commandName != "Paste" && e.commandName != "Duplicate") |
|||
return false; |
|||
|
|||
if (e.commandName == "Copy" || e.commandName == "Duplicate") |
|||
DoCopy(parent); |
|||
|
|||
if (e.commandName == "Paste" || e.commandName == "Duplicate") |
|||
DoPaste(parent); |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private static void DoCopy(Canvas2D parent) |
|||
{ |
|||
EditorGUIUtility.systemCopyBuffer = SerializeSelectedElements(parent); |
|||
} |
|||
|
|||
public static string SerializeSelectedElements(Canvas2D parent) |
|||
{ |
|||
var selectedElements = parent.selection; |
|||
|
|||
// build a graph to serialize (will just contain the
|
|||
// nodes and edges we are interested in.
|
|||
var graph = new CopyPasteGraph(); |
|||
foreach (var thing in selectedElements) |
|||
{ |
|||
var dNode = thing as DrawableNode; |
|||
if (dNode != null) |
|||
{ |
|||
graph.AddNode(dNode.m_Node); |
|||
foreach (var edge in NodeUtils.GetAllEdges(dNode.m_Node)) |
|||
graph.AddEdge(edge); |
|||
} |
|||
|
|||
var dEdge = thing as DrawableEdge<NodeAnchor>; |
|||
if (dEdge != null) |
|||
{ |
|||
graph.AddEdge(dEdge.m_Edge); |
|||
} |
|||
} |
|||
// serialize then break references
|
|||
var serialized = JsonUtility.ToJson(graph, true); |
|||
return serialized; |
|||
} |
|||
|
|||
public static CopyPasteGraph DeserializeSelectedElements(string toDeserialize) |
|||
{ |
|||
try |
|||
{ |
|||
return JsonUtility.FromJson<CopyPasteGraph>(toDeserialize); |
|||
} |
|||
catch |
|||
{ |
|||
// ignored. just means copy buffer was not a graph :(
|
|||
return null; |
|||
} |
|||
} |
|||
|
|||
private static void DoPaste(Canvas2D parent) |
|||
{ |
|||
var copyText = EditorGUIUtility.systemCopyBuffer; |
|||
if (string.IsNullOrEmpty(copyText)) |
|||
return; |
|||
|
|||
var pastedGraph = DeserializeSelectedElements(copyText); |
|||
if (pastedGraph == null) |
|||
return; |
|||
|
|||
if (parent.dataSource == null) |
|||
return; |
|||
|
|||
var dataSource = parent.dataSource as GraphDataSource; |
|||
if (dataSource == null) |
|||
return; |
|||
|
|||
var asset = dataSource.graphAsset; |
|||
if (asset == null) |
|||
return; |
|||
|
|||
var graph = asset.graph; |
|||
if (graph == null) |
|||
return; |
|||
|
|||
var addedNodes = new List<INode>(); |
|||
|
|||
var nodeGuidMap = new Dictionary<Guid, Guid>(); |
|||
foreach (var node in pastedGraph.GetNodes<INode>()) |
|||
{ |
|||
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; |
|||
graph.AddNode(node); |
|||
addedNodes.Add(node); |
|||
} |
|||
|
|||
// only connect edges within pasted elements, discard
|
|||
// external edges.
|
|||
var addedEdges = new List<IEdge>(); |
|||
|
|||
foreach (var edge in pastedGraph.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); |
|||
addedEdges.Add(graph.Connect(outputSlotRef, inputSlotRef)); |
|||
} |
|||
} |
|||
|
|||
graph.ValidateGraph(); |
|||
parent.ReloadData(); |
|||
parent.Invalidate(); |
|||
|
|||
parent.selection.Clear(); |
|||
foreach (var element in parent.elements) |
|||
{ |
|||
var drawableNode = element as DrawableNode; |
|||
if (drawableNode != null && addedNodes.Any(x => x == drawableNode.m_Node)) |
|||
{ |
|||
drawableNode.selected = true; |
|||
parent.selection.Add(drawableNode); |
|||
continue; |
|||
} |
|||
|
|||
var drawableEdge = element as DrawableEdge<NodeAnchor>; |
|||
if (drawableEdge != null && addedEdges.Any(x => x == drawableEdge.m_Edge)) |
|||
{ |
|||
drawableEdge.selected = true; |
|||
parent.selection.Add(drawableEdge); |
|||
} |
|||
} |
|||
|
|||
parent.Repaint(); |
|||
} |
|||
} |
|||
}*/ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
/* |
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
internal class CopyPasteGraph : ISerializationCallbackReceiver |
|||
{ |
|||
[NonSerialized] |
|||
private HashSet<IEdge> m_Edges = new HashSet<IEdge>(); |
|||
|
|||
[NonSerialized] |
|||
private HashSet<INode> m_Nodes = new HashSet<INode>(); |
|||
|
|||
[SerializeField] |
|||
List<SerializationHelper.JSONSerializedElement> m_SerializableNodes = new List<SerializationHelper.JSONSerializedElement>(); |
|||
|
|||
[SerializeField] |
|||
List<SerializationHelper.JSONSerializedElement> m_SerializableEdges = new List<SerializationHelper.JSONSerializedElement>(); |
|||
|
|||
public virtual void AddNode(INode node) |
|||
{ |
|||
m_Nodes.Add(node); |
|||
} |
|||
|
|||
public void AddEdge(IEdge edge) |
|||
{ |
|||
m_Edges.Add(edge); |
|||
} |
|||
|
|||
public IEnumerable<T> GetNodes<T>() where T : INode |
|||
{ |
|||
return m_Nodes.OfType<T>(); |
|||
} |
|||
|
|||
public IEnumerable<IEdge> edges |
|||
{ |
|||
get { return m_Edges; } |
|||
} |
|||
|
|||
public virtual void OnBeforeSerialize() |
|||
{ |
|||
m_SerializableNodes = SerializationHelper.Serialize<INode>(m_Nodes); |
|||
m_SerializableEdges = SerializationHelper.Serialize<IEdge>(m_Edges); |
|||
} |
|||
|
|||
public virtual void OnAfterDeserialize() |
|||
{ |
|||
var nodes = SerializationHelper.Deserialize<INode>(m_SerializableNodes); |
|||
m_Nodes.Clear(); |
|||
foreach (var node in nodes) |
|||
m_Nodes.Add(node); |
|||
m_SerializableNodes = null; |
|||
|
|||
var edges = SerializationHelper.Deserialize<IEdge>(m_SerializableEdges); |
|||
m_Edges.Clear(); |
|||
foreach (var edge in edges) |
|||
m_Edges.Add(edge); |
|||
m_SerializableEdges = null; |
|||
} |
|||
} |
|||
|
|||
internal class CopySelected : IManipulate |
|||
{ |
|||
public delegate void CopyElements(List<CanvasElement> elements); |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ValidateCommand += Validate; |
|||
element.ExecuteCommand += CopyPaste; |
|||
} |
|||
|
|||
private bool Validate(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Copy" && e.commandName != "Paste" && e.commandName != "Duplicate") |
|||
return false; |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool CopyPaste(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Copy" && e.commandName != "Paste" && e.commandName != "Duplicate") |
|||
return false; |
|||
|
|||
if (e.commandName == "Copy" || e.commandName == "Duplicate") |
|||
DoCopy(parent); |
|||
|
|||
if (e.commandName == "Paste" || e.commandName == "Duplicate") |
|||
DoPaste(parent); |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private static void DoCopy(Canvas2D parent) |
|||
{ |
|||
EditorGUIUtility.systemCopyBuffer = SerializeSelectedElements(parent); |
|||
} |
|||
|
|||
public static string SerializeSelectedElements(Canvas2D parent) |
|||
{ |
|||
var selectedElements = parent.selection; |
|||
|
|||
// build a graph to serialize (will just contain the
|
|||
// nodes and edges we are interested in.
|
|||
var graph = new CopyPasteGraph(); |
|||
foreach (var thing in selectedElements) |
|||
{ |
|||
var dNode = thing as DrawableNode; |
|||
if (dNode != null) |
|||
{ |
|||
graph.AddNode(dNode.m_Node); |
|||
foreach (var edge in NodeUtils.GetAllEdges(dNode.m_Node)) |
|||
graph.AddEdge(edge); |
|||
} |
|||
|
|||
var dEdge = thing as DrawableEdge<NodeAnchor>; |
|||
if (dEdge != null) |
|||
{ |
|||
graph.AddEdge(dEdge.m_Edge); |
|||
} |
|||
} |
|||
// serialize then break references
|
|||
var serialized = JsonUtility.ToJson(graph, true); |
|||
return serialized; |
|||
} |
|||
|
|||
public static CopyPasteGraph DeserializeSelectedElements(string toDeserialize) |
|||
{ |
|||
try |
|||
{ |
|||
return JsonUtility.FromJson<CopyPasteGraph>(toDeserialize); |
|||
} |
|||
catch |
|||
{ |
|||
// ignored. just means copy buffer was not a graph :(
|
|||
return null; |
|||
} |
|||
} |
|||
|
|||
private static void DoPaste(Canvas2D parent) |
|||
{ |
|||
var copyText = EditorGUIUtility.systemCopyBuffer; |
|||
if (string.IsNullOrEmpty(copyText)) |
|||
return; |
|||
|
|||
var pastedGraph = DeserializeSelectedElements(copyText); |
|||
if (pastedGraph == null) |
|||
return; |
|||
|
|||
if (parent.dataSource == null) |
|||
return; |
|||
|
|||
var dataSource = parent.dataSource as GraphDataSource; |
|||
if (dataSource == null) |
|||
return; |
|||
|
|||
var asset = dataSource.graphAsset; |
|||
if (asset == null) |
|||
return; |
|||
|
|||
var graph = asset.graph; |
|||
if (graph == null) |
|||
return; |
|||
|
|||
var addedNodes = new List<INode>(); |
|||
|
|||
var nodeGuidMap = new Dictionary<Guid, Guid>(); |
|||
foreach (var node in pastedGraph.GetNodes<INode>()) |
|||
{ |
|||
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; |
|||
graph.AddNode(node); |
|||
addedNodes.Add(node); |
|||
} |
|||
|
|||
// only connect edges within pasted elements, discard
|
|||
// external edges.
|
|||
var addedEdges = new List<IEdge>(); |
|||
|
|||
foreach (var edge in pastedGraph.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); |
|||
addedEdges.Add(graph.Connect(outputSlotRef, inputSlotRef)); |
|||
} |
|||
} |
|||
|
|||
graph.ValidateGraph(); |
|||
parent.ReloadData(); |
|||
parent.Invalidate(); |
|||
|
|||
parent.selection.Clear(); |
|||
foreach (var element in parent.elements) |
|||
{ |
|||
var drawableNode = element as DrawableNode; |
|||
if (drawableNode != null && addedNodes.Any(x => x == drawableNode.m_Node)) |
|||
{ |
|||
drawableNode.selected = true; |
|||
parent.selection.Add(drawableNode); |
|||
continue; |
|||
} |
|||
|
|||
var drawableEdge = element as DrawableEdge<NodeAnchor>; |
|||
if (drawableEdge != null && addedEdges.Any(x => x == drawableEdge.m_Edge)) |
|||
{ |
|||
drawableEdge.selected = true; |
|||
parent.selection.Add(drawableEdge); |
|||
} |
|||
} |
|||
|
|||
parent.Repaint(); |
|||
} |
|||
} |
|||
}*/ |
|
|||
/*using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
internal class DeleteSelected : IManipulate |
|||
{ |
|||
public delegate void DeleteElements(List<CanvasElement> elements); |
|||
|
|||
private readonly DeleteElements m_DeletionCallback; |
|||
|
|||
public DeleteSelected(DeleteElements deletionCallback) |
|||
{ |
|||
m_DeletionCallback = deletionCallback; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ValidateCommand += Validate; |
|||
element.ExecuteCommand += Delete; |
|||
} |
|||
|
|||
private bool Validate(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Delete" && e.commandName != "SoftDelete") |
|||
return false; |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool Delete(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Delete" && e.commandName != "SoftDelete") |
|||
return false; |
|||
|
|||
|
|||
if (m_DeletionCallback != null) |
|||
{ |
|||
m_DeletionCallback(parent.selection); |
|||
parent.ReloadData(); |
|||
parent.Repaint(); |
|||
} |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
*/ |
|||
/*using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
internal class DeleteSelected : IManipulate |
|||
{ |
|||
public delegate void DeleteElements(List<CanvasElement> elements); |
|||
|
|||
private readonly DeleteElements m_DeletionCallback; |
|||
|
|||
public DeleteSelected(DeleteElements deletionCallback) |
|||
{ |
|||
m_DeletionCallback = deletionCallback; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ValidateCommand += Validate; |
|||
element.ExecuteCommand += Delete; |
|||
} |
|||
|
|||
private bool Validate(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Delete" && e.commandName != "SoftDelete") |
|||
return false; |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool Delete(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.commandName != "Delete" && e.commandName != "SoftDelete") |
|||
return false; |
|||
|
|||
|
|||
if (m_DeletionCallback != null) |
|||
{ |
|||
m_DeletionCallback(parent.selection); |
|||
parent.ReloadData(); |
|||
parent.Repaint(); |
|||
} |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
*/ |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
/* |
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
public class DrawableNode : CanvasElement |
|||
{ |
|||
private readonly GraphDataSource m_Data; |
|||
|
|||
private readonly Rect m_CustomUiRect; |
|||
public readonly INode m_Node; |
|||
private readonly ICustomNodeUi m_Ui; |
|||
|
|||
private const int kDefaultWidth = 200; |
|||
|
|||
public DrawableNode(INode node, ICustomNodeUi ui, GraphDataSource data) |
|||
{ |
|||
var drawData = node.drawState; |
|||
translation = drawData.position.min; |
|||
var width = ui != null ? ui.GetNodeWidth() : kDefaultWidth; |
|||
scale = new Vector2(width, width); |
|||
|
|||
m_Node = node; |
|||
m_Ui = ui; |
|||
m_Data = data; |
|||
|
|||
const float yStart = 10.0f; |
|||
var vector3 = new Vector3(5.0f, yStart, 0.0f); |
|||
Vector3 pos = vector3; |
|||
|
|||
// input slots
|
|||
foreach (var slot in node.GetInputSlots<ISlot>().OrderBy(x => x.priority)) |
|||
{ |
|||
pos.y += 22; |
|||
AddChild(new NodeAnchor(pos, typeof(Vector4), node, slot, data, Direction.Input)); |
|||
} |
|||
var inputYMax = pos.y + 22; |
|||
|
|||
// output port
|
|||
pos.x = width; |
|||
pos.y = yStart; |
|||
bool first = true; |
|||
foreach (var slot in node.GetOutputSlots<ISlot>().OrderBy(x => x.priority).ThenBy(x => x.id)) |
|||
{ |
|||
var edges = node.owner.GetEdges(node.GetSlotReference(slot.id)); |
|||
// don't show empty output slots in collapsed mode
|
|||
if (!node.drawState.expanded && !edges.Any() && !first) |
|||
continue; |
|||
|
|||
pos.y += 22; |
|||
AddChild(new NodeAnchor(pos, typeof(Vector4), node, slot, data, Direction.Output)); |
|||
first = false; |
|||
} |
|||
pos.y += 22; |
|||
|
|||
pos.y = Mathf.Max(pos.y, inputYMax); |
|||
|
|||
if (ui != null) |
|||
{ |
|||
var customUiHeight = ui.GetNodeUiHeight(width); |
|||
m_CustomUiRect = new Rect(10, pos.y, width - 20, customUiHeight); |
|||
pos.y += customUiHeight; |
|||
} |
|||
|
|||
scale = new Vector3(pos.x, pos.y + 10.0f, 0.0f); |
|||
|
|||
OnWidget += InvalidateUIIfNeedsTime; |
|||
|
|||
AddManipulator(new ImguiContainer()); |
|||
AddManipulator(new Draggable()); |
|||
} |
|||
|
|||
private bool InvalidateUIIfNeedsTime(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
var childrenNodes = ListPool<INode>.Get(); |
|||
NodeUtils.DepthFirstCollectNodesFromNode(childrenNodes, m_Node); |
|||
if (childrenNodes.OfType<IRequiresTime>().Any()) |
|||
Invalidate(); |
|||
ListPool<INode>.Release(childrenNodes); |
|||
return true; |
|||
} |
|||
|
|||
public override void UpdateModel(UpdateType t) |
|||
{ |
|||
base.UpdateModel(t); |
|||
var drawState = m_Node.drawState; |
|||
var pos = drawState.position; |
|||
pos.min = translation; |
|||
drawState.position = pos; |
|||
m_Node.drawState = drawState; |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.7f); |
|||
Color selectedColor = new Color(1.0f, 0.7f, 0.0f, 0.7f); |
|||
EditorGUI.DrawRect(new Rect(0, 0, scale.x, scale.y), m_Node.hasError ? Color.red : selected ? selectedColor : backgroundColor); |
|||
GUI.Label(new Rect(0, 0, scale.x, 26f), GUIContent.none, new GUIStyle("preToolbar")); |
|||
GUI.Label(new Rect(10, 2, scale.x - 20.0f, 16.0f), m_Node.name, EditorStyles.toolbarTextField); |
|||
var drawState = m_Node.drawState; |
|||
if (GUI.Button(new Rect(scale.x - 20f, 3f, 14f, 14f), drawState.expanded ? "-" : "+")) |
|||
{ |
|||
drawState.expanded = !drawState.expanded; |
|||
m_Node.drawState = drawState; |
|||
ParentCanvas().ReloadData(); |
|||
ParentCanvas().Repaint(); |
|||
return; |
|||
} |
|||
|
|||
if (m_Ui != null) |
|||
{ |
|||
var modificationType = m_Ui.Render(m_CustomUiRect); |
|||
|
|||
if (modificationType != GUIModificationType.None) |
|||
m_Data.MarkDirty(); |
|||
|
|||
if (modificationType == GUIModificationType.ModelChanged) |
|||
{ |
|||
m_Node.owner.ValidateGraph(); |
|||
ParentCanvas().Invalidate(); |
|||
ParentCanvas().ReloadData(); |
|||
ParentCanvas().Repaint(); |
|||
return; |
|||
} |
|||
|
|||
if (modificationType == GUIModificationType.DataChanged) |
|||
{ |
|||
ValidateDependentNodes(m_Node); |
|||
RepaintDependentNodes(m_Node); |
|||
} |
|||
else if (modificationType == GUIModificationType.Repaint) |
|||
{ |
|||
// if we were changed, we need to redraw all the
|
|||
// dependent nodes.
|
|||
RepaintDependentNodes(m_Node); |
|||
} |
|||
} |
|||
base.Render(parentRect, canvas); |
|||
} |
|||
|
|||
private void RepaintDependentNodes(INode theNode) |
|||
{ |
|||
var dependentNodes = new List<INode>(); |
|||
NodeUtils.CollectNodesNodeFeedsInto(dependentNodes, theNode); |
|||
foreach (var node in dependentNodes) |
|||
{ |
|||
foreach (var drawableNode in m_Data.lastGeneratedNodes.Where(x => x.m_Node == node)) |
|||
drawableNode.Invalidate(); |
|||
} |
|||
} |
|||
|
|||
private void ValidateDependentNodes(INode theNode) |
|||
{ |
|||
var dependentNodes = new List<INode>(); |
|||
NodeUtils.CollectNodesNodeFeedsInto(dependentNodes, theNode); |
|||
foreach (var node in dependentNodes) |
|||
node.ValidateNode(); |
|||
} |
|||
|
|||
/* |
|||
public static void OnGUI(List<CanvasElement> selection) |
|||
{ |
|||
var drawableMaterialNode = selection.OfType<DrawableMaterialNode>().FirstOrDefault(); |
|||
if (drawableMaterialNode != null && drawableMaterialNode.m_Node.OnGUI()) |
|||
{ |
|||
// if we were changed, we need to redraw all the
|
|||
// dependent nodes.
|
|||
RepaintDependentNodes(drawableMaterialNode.m_Node); |
|||
} |
|||
}*/ |
|||
|
|||
/* public virtual GUIModificationType NodeUI(Rect drawArea) |
|||
{ |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public virtual bool OnGUI() |
|||
{ |
|||
GUILayout.Label("MaterialSlot Defaults", EditorStyles.boldLabel); |
|||
var modified = false; |
|||
foreach (var slot in inputSlots) |
|||
{ |
|||
if (!owner.GetEdges(GetSlotReference(slot.name)).Any()) |
|||
modified |= DoSlotUI(this, slot); |
|||
} |
|||
|
|||
return modified; |
|||
} |
|||
|
|||
public static bool DoSlotUI(SerializableNode node, ISlot slot) |
|||
{ |
|||
GUILayout.BeginHorizontal( /*EditorStyles.inspectorBig*); |
|||
GUILayout.BeginVertical(); |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label("MaterialSlot " + slot.name, EditorStyles.largeLabel); |
|||
GUILayout.FlexibleSpace(); |
|||
GUILayout.EndHorizontal(); |
|||
GUILayout.EndVertical(); |
|||
GUILayout.EndHorizontal(); |
|||
|
|||
//TODO: fix this
|
|||
return false; |
|||
//return slot.OnGUI();
|
|||
}* |
|||
} |
|||
}*/ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
/* |
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
public class DrawableNode : CanvasElement |
|||
{ |
|||
private readonly GraphDataSource m_Data; |
|||
|
|||
private readonly Rect m_CustomUiRect; |
|||
public readonly INode m_Node; |
|||
private readonly ICustomNodeUi m_Ui; |
|||
|
|||
private const int kDefaultWidth = 200; |
|||
|
|||
public DrawableNode(INode node, ICustomNodeUi ui, GraphDataSource data) |
|||
{ |
|||
var drawData = node.drawState; |
|||
translation = drawData.position.min; |
|||
var width = ui != null ? ui.GetNodeWidth() : kDefaultWidth; |
|||
scale = new Vector2(width, width); |
|||
|
|||
m_Node = node; |
|||
m_Ui = ui; |
|||
m_Data = data; |
|||
|
|||
const float yStart = 10.0f; |
|||
var vector3 = new Vector3(5.0f, yStart, 0.0f); |
|||
Vector3 pos = vector3; |
|||
|
|||
// input slots
|
|||
foreach (var slot in node.GetInputSlots<ISlot>().OrderBy(x => x.priority)) |
|||
{ |
|||
pos.y += 22; |
|||
AddChild(new NodeAnchor(pos, typeof(Vector4), node, slot, data, Direction.Input)); |
|||
} |
|||
var inputYMax = pos.y + 22; |
|||
|
|||
// output port
|
|||
pos.x = width; |
|||
pos.y = yStart; |
|||
bool first = true; |
|||
foreach (var slot in node.GetOutputSlots<ISlot>().OrderBy(x => x.priority).ThenBy(x => x.id)) |
|||
{ |
|||
var edges = node.owner.GetEdges(node.GetSlotReference(slot.id)); |
|||
// don't show empty output slots in collapsed mode
|
|||
if (!node.drawState.expanded && !edges.Any() && !first) |
|||
continue; |
|||
|
|||
pos.y += 22; |
|||
AddChild(new NodeAnchor(pos, typeof(Vector4), node, slot, data, Direction.Output)); |
|||
first = false; |
|||
} |
|||
pos.y += 22; |
|||
|
|||
pos.y = Mathf.Max(pos.y, inputYMax); |
|||
|
|||
if (ui != null) |
|||
{ |
|||
var customUiHeight = ui.GetNodeUiHeight(width); |
|||
m_CustomUiRect = new Rect(10, pos.y, width - 20, customUiHeight); |
|||
pos.y += customUiHeight; |
|||
} |
|||
|
|||
scale = new Vector3(pos.x, pos.y + 10.0f, 0.0f); |
|||
|
|||
OnWidget += InvalidateUIIfNeedsTime; |
|||
|
|||
AddManipulator(new ImguiContainer()); |
|||
AddManipulator(new Draggable()); |
|||
} |
|||
|
|||
private bool InvalidateUIIfNeedsTime(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
var childrenNodes = ListPool<INode>.Get(); |
|||
NodeUtils.DepthFirstCollectNodesFromNode(childrenNodes, m_Node); |
|||
if (childrenNodes.OfType<IRequiresTime>().Any()) |
|||
Invalidate(); |
|||
ListPool<INode>.Release(childrenNodes); |
|||
return true; |
|||
} |
|||
|
|||
public override void UpdateModel(UpdateType t) |
|||
{ |
|||
base.UpdateModel(t); |
|||
var drawState = m_Node.drawState; |
|||
var pos = drawState.position; |
|||
pos.min = translation; |
|||
drawState.position = pos; |
|||
m_Node.drawState = drawState; |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.7f); |
|||
Color selectedColor = new Color(1.0f, 0.7f, 0.0f, 0.7f); |
|||
EditorGUI.DrawRect(new Rect(0, 0, scale.x, scale.y), m_Node.hasError ? Color.red : selected ? selectedColor : backgroundColor); |
|||
GUI.Label(new Rect(0, 0, scale.x, 26f), GUIContent.none, new GUIStyle("preToolbar")); |
|||
GUI.Label(new Rect(10, 2, scale.x - 20.0f, 16.0f), m_Node.name, EditorStyles.toolbarTextField); |
|||
var drawState = m_Node.drawState; |
|||
if (GUI.Button(new Rect(scale.x - 20f, 3f, 14f, 14f), drawState.expanded ? "-" : "+")) |
|||
{ |
|||
drawState.expanded = !drawState.expanded; |
|||
m_Node.drawState = drawState; |
|||
ParentCanvas().ReloadData(); |
|||
ParentCanvas().Repaint(); |
|||
return; |
|||
} |
|||
|
|||
if (m_Ui != null) |
|||
{ |
|||
var modificationType = m_Ui.Render(m_CustomUiRect); |
|||
|
|||
if (modificationType != GUIModificationType.None) |
|||
m_Data.MarkDirty(); |
|||
|
|||
if (modificationType == GUIModificationType.ModelChanged) |
|||
{ |
|||
m_Node.owner.ValidateGraph(); |
|||
ParentCanvas().Invalidate(); |
|||
ParentCanvas().ReloadData(); |
|||
ParentCanvas().Repaint(); |
|||
return; |
|||
} |
|||
|
|||
if (modificationType == GUIModificationType.DataChanged) |
|||
{ |
|||
ValidateDependentNodes(m_Node); |
|||
RepaintDependentNodes(m_Node); |
|||
} |
|||
else if (modificationType == GUIModificationType.Repaint) |
|||
{ |
|||
// if we were changed, we need to redraw all the
|
|||
// dependent nodes.
|
|||
RepaintDependentNodes(m_Node); |
|||
} |
|||
} |
|||
base.Render(parentRect, canvas); |
|||
} |
|||
|
|||
private void RepaintDependentNodes(INode theNode) |
|||
{ |
|||
var dependentNodes = new List<INode>(); |
|||
NodeUtils.CollectNodesNodeFeedsInto(dependentNodes, theNode); |
|||
foreach (var node in dependentNodes) |
|||
{ |
|||
foreach (var drawableNode in m_Data.lastGeneratedNodes.Where(x => x.m_Node == node)) |
|||
drawableNode.Invalidate(); |
|||
} |
|||
} |
|||
|
|||
private void ValidateDependentNodes(INode theNode) |
|||
{ |
|||
var dependentNodes = new List<INode>(); |
|||
NodeUtils.CollectNodesNodeFeedsInto(dependentNodes, theNode); |
|||
foreach (var node in dependentNodes) |
|||
node.ValidateNode(); |
|||
} |
|||
|
|||
/* |
|||
public static void OnGUI(List<CanvasElement> selection) |
|||
{ |
|||
var drawableMaterialNode = selection.OfType<DrawableMaterialNode>().FirstOrDefault(); |
|||
if (drawableMaterialNode != null && drawableMaterialNode.m_Node.OnGUI()) |
|||
{ |
|||
// if we were changed, we need to redraw all the
|
|||
// dependent nodes.
|
|||
RepaintDependentNodes(drawableMaterialNode.m_Node); |
|||
} |
|||
}*/ |
|||
|
|||
/* public virtual GUIModificationType NodeUI(Rect drawArea) |
|||
{ |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public virtual bool OnGUI() |
|||
{ |
|||
GUILayout.Label("MaterialSlot Defaults", EditorStyles.boldLabel); |
|||
var modified = false; |
|||
foreach (var slot in inputSlots) |
|||
{ |
|||
if (!owner.GetEdges(GetSlotReference(slot.name)).Any()) |
|||
modified |= DoSlotUI(this, slot); |
|||
} |
|||
|
|||
return modified; |
|||
} |
|||
|
|||
public static bool DoSlotUI(SerializableNode node, ISlot slot) |
|||
{ |
|||
GUILayout.BeginHorizontal( /*EditorStyles.inspectorBig*); |
|||
GUILayout.BeginVertical(); |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label("MaterialSlot " + slot.name, EditorStyles.largeLabel); |
|||
GUILayout.FlexibleSpace(); |
|||
GUILayout.EndHorizontal(); |
|||
GUILayout.EndVertical(); |
|||
GUILayout.EndHorizontal(); |
|||
|
|||
//TODO: fix this
|
|||
return false; |
|||
//return slot.OnGUI();
|
|||
}* |
|||
} |
|||
}*/ |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Class)] |
|||
sealed class CustomNodeUI : Attribute |
|||
{ |
|||
private Type m_ModeToDrawFor; |
|||
|
|||
public CustomNodeUI(Type nodeToDrawFor) |
|||
{ |
|||
m_ModeToDrawFor = nodeToDrawFor; |
|||
} |
|||
|
|||
public Type nodeToDrawFor |
|||
{ |
|||
get { return m_ModeToDrawFor; } } |
|||
} |
|||
/* |
|||
public class GraphDataSource : ICanvasDataSource |
|||
{ |
|||
readonly List<DrawableNode> m_DrawableNodes = new List<DrawableNode>(); |
|||
|
|||
public IGraphAsset graphAsset { get; set; } |
|||
|
|||
public ICollection<DrawableNode> lastGeneratedNodes |
|||
{ |
|||
get { return m_DrawableNodes; } |
|||
} |
|||
|
|||
private static Type[] GetTypesFromAssembly(Assembly assembly) |
|||
{ |
|||
if (assembly == null) |
|||
return new Type[] {}; |
|||
try |
|||
{ |
|||
return assembly.GetTypes(); |
|||
} |
|||
catch (ReflectionTypeLoadException) |
|||
{ |
|||
return new Type[] {}; |
|||
} |
|||
} |
|||
|
|||
private static Dictionary<Type, Type> s_DrawerUI; |
|||
|
|||
private static Dictionary<Type, Type> drawerUI |
|||
{ |
|||
get |
|||
{ |
|||
if (s_DrawerUI == null) |
|||
{ |
|||
s_DrawerUI = new Dictionary<Type, Type>(); |
|||
var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => GetTypesFromAssembly(x)); |
|||
|
|||
foreach (var type in loadedTypes) |
|||
{ |
|||
var attribute = type.GetCustomAttributes(true).OfType<CustomNodeUI>().FirstOrDefault(); |
|||
if (attribute != null && typeof(ICustomNodeUi).IsAssignableFrom(type)) |
|||
s_DrawerUI.Add(attribute.nodeToDrawFor, type); |
|||
} |
|||
} |
|||
return s_DrawerUI; |
|||
} |
|||
} |
|||
|
|||
public CanvasElement[] FetchElements() |
|||
{ |
|||
m_DrawableNodes.Clear(); |
|||
var graph = graphAsset.graph; |
|||
Debug.LogFormat("Trying to convert: {0}", graphAsset.graph); |
|||
foreach (var node in graph.GetNodes<INode>()) |
|||
{ |
|||
var nodeType = node.GetType(); |
|||
Type draweruiType = null; |
|||
|
|||
while (draweruiType == null && nodeType != null) |
|||
{ |
|||
draweruiType = drawerUI.FirstOrDefault(x => x.Key == nodeType).Value; |
|||
nodeType = nodeType.BaseType; |
|||
} |
|||
|
|||
ICustomNodeUi customUI = null; |
|||
if (draweruiType != null) |
|||
{ |
|||
try |
|||
{ |
|||
customUI = Activator.CreateInstance(draweruiType) as ICustomNodeUi; |
|||
customUI.node = node; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Debug.LogWarningFormat("Could not construct instance of: {0} - {1}", draweruiType, e); |
|||
} |
|||
} |
|||
|
|||
// add the nodes
|
|||
m_DrawableNodes.Add(new DrawableNode(node, customUI, this)); |
|||
} |
|||
|
|||
// Add the edges now
|
|||
var drawableEdges = new List<DrawableEdge<NodeAnchor>>(); |
|||
foreach (var drawableMaterialNode in m_DrawableNodes) |
|||
{ |
|||
var baseNode = drawableMaterialNode.m_Node; |
|||
foreach (var slot in baseNode.GetOutputSlots<ISlot>()) |
|||
{ |
|||
var sourceAnchor = (NodeAnchor)drawableMaterialNode.Children().FirstOrDefault(x => x is NodeAnchor && ((NodeAnchor)x).m_Slot == slot); |
|||
|
|||
var edges = baseNode.owner.GetEdges(new SlotReference(baseNode.guid, slot.id)); |
|||
foreach (var edge in edges) |
|||
{ |
|||
var toNode = baseNode.owner.GetNodeFromGuid(edge.inputSlot.nodeGuid); |
|||
var toSlot = toNode.FindInputSlot<ISlot>(edge.inputSlot.slotId); |
|||
var targetNode = m_DrawableNodes.FirstOrDefault(x => x.m_Node == toNode); |
|||
var targetAnchor = (NodeAnchor)targetNode.Children().FirstOrDefault(x => x is NodeAnchor && ((NodeAnchor)x).m_Slot == toSlot); |
|||
drawableEdges.Add(new DrawableEdge<NodeAnchor>(edge, this, sourceAnchor, targetAnchor)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Add proxy inputs for when edges are not connect
|
|||
var nullInputSlots = new List<NullInputProxy>(); |
|||
foreach (var drawableMaterialNode in m_DrawableNodes) |
|||
{ |
|||
var baseNode = drawableMaterialNode.m_Node; |
|||
// grab the input slots where there are no edges
|
|||
foreach (var slot in baseNode.GetInputsWithNoConnection()) |
|||
{ |
|||
// if there is no anchor, continue
|
|||
// this can happen if we are in collapsed mode
|
|||
var sourceAnchor = (NodeAnchor)drawableMaterialNode.Children().FirstOrDefault(x => x is NodeAnchor && ((NodeAnchor)x).m_Slot == slot); |
|||
if (sourceAnchor == null) |
|||
continue; |
|||
|
|||
nullInputSlots.Add(new NullInputProxy(baseNode, slot, sourceAnchor)); |
|||
} |
|||
} |
|||
var toReturn = new List<CanvasElement>(); |
|||
toReturn.AddRange(m_DrawableNodes.Select(x => (CanvasElement)x)); |
|||
toReturn.AddRange(drawableEdges.Select(x => (CanvasElement)x)); |
|||
toReturn.AddRange(nullInputSlots.Select(x => (CanvasElement)x)); |
|||
|
|||
//toReturn.Add(new FloatingPreview(new Rect(Screen.width - 300, Screen.height - 300, 300, 300), pixelGraph.nodes.FirstOrDefault(x => x is PixelShaderNode)));
|
|||
|
|||
Debug.LogFormat("Returning {0} nodes", m_DrawableNodes.Count); |
|||
Debug.LogFormat("Returning {0} drawableEdges", drawableEdges.Count); |
|||
Debug.LogFormat("Returning {0} nullInputSlots", nullInputSlots.Count); |
|||
return toReturn.ToArray(); |
|||
} |
|||
|
|||
public void DeleteElement(CanvasElement e) |
|||
{ |
|||
// do nothing here, we want to use delete elements.
|
|||
// delete elements ensures that edges are deleted before nodes.
|
|||
} |
|||
|
|||
public void DeleteElements(List<CanvasElement> elements) |
|||
{ |
|||
var graph = graphAsset.graph; |
|||
var toRemoveEdge = new List<IEdge>(); |
|||
// delete selected edges first
|
|||
foreach (var e in elements.OfType<Edge<NodeAnchor>>()) |
|||
{ |
|||
//find the edge
|
|||
var edge = graph.edges.FirstOrDefault(x => graph.GetNodeFromGuid(x.outputSlot.nodeGuid).FindOutputSlot<ISlot>(x.outputSlot.slotId) == e.Left.m_Slot |
|||
&& graph.GetNodeFromGuid(x.inputSlot.nodeGuid).FindInputSlot<ISlot>(x.inputSlot.slotId) == e.Right.m_Slot); |
|||
|
|||
toRemoveEdge.Add(edge); |
|||
} |
|||
|
|||
var toRemoveNode = new List<INode>(); |
|||
// now delete the nodes
|
|||
foreach (var e in elements.OfType<DrawableNode>()) |
|||
{ |
|||
if (!e.m_Node.canDeleteNode) |
|||
continue; |
|||
toRemoveNode.Add(e.m_Node); |
|||
} |
|||
graph.RemoveElements(toRemoveNode, toRemoveEdge); |
|||
MarkDirty(); |
|||
} |
|||
|
|||
public void Connect(NodeAnchor a, NodeAnchor b) |
|||
{ |
|||
var graph = graphAsset.graph; |
|||
graph.Connect(a.m_Node.GetSlotReference(a.m_Slot.id), b.m_Node.GetSlotReference(b.m_Slot.id)); |
|||
MarkDirty(); |
|||
} |
|||
|
|||
public void Addnode(INode node) |
|||
{ |
|||
var graph = graphAsset.graph; |
|||
graph.AddNode(node); |
|||
MarkDirty(); |
|||
} |
|||
|
|||
public void MarkDirty() |
|||
{ |
|||
EditorUtility.SetDirty(graphAsset.GetScriptableObject()); |
|||
} |
|||
|
|||
/* |
|||
} |
|||
|
|||
public class FloatingPreview : CanvasElement |
|||
{ |
|||
private AbstractMaterialNode m_Node; |
|||
|
|||
public FloatingPreview(Rect position, AbstractMaterialNode node) |
|||
{ |
|||
m_Node = node as AbstractMaterialNode; |
|||
m_Translation = new Vector2(position.x, position.y); |
|||
m_Scale = new Vector3(position.width, position.height, 1); |
|||
m_Caps |= Capabilities.Floating | Capabilities.Unselectable; |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
var drawArea = new Rect(0, 0, scale.x, scale.y); |
|||
Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.7f); |
|||
EditorGUI.DrawRect(drawArea, backgroundColor); |
|||
|
|||
drawArea.width -= 10; |
|||
drawArea.height -= 10; |
|||
drawArea.x += 5; |
|||
drawArea.y += 5; |
|||
|
|||
GL.sRGBWrite = (QualitySettings.activeColorSpace == ColorSpace.Linear); |
|||
GUI.DrawTexture(drawArea, m_Node.RenderPreview(new Rect(0, 0, drawArea.width, drawArea.height)), ScaleMode.StretchToFill, false); |
|||
GL.sRGBWrite = false; |
|||
|
|||
Invalidate(); |
|||
canvas.Repaint(); |
|||
}* |
|||
}*/ |
|||
} |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Class)] |
|||
sealed class CustomNodeUI : Attribute |
|||
{ |
|||
private Type m_ModeToDrawFor; |
|||
|
|||
public CustomNodeUI(Type nodeToDrawFor) |
|||
{ |
|||
m_ModeToDrawFor = nodeToDrawFor; |
|||
} |
|||
|
|||
public Type nodeToDrawFor |
|||
{ |
|||
get { return m_ModeToDrawFor; } } |
|||
} |
|||
/* |
|||
public class GraphDataSource : ICanvasDataSource |
|||
{ |
|||
readonly List<DrawableNode> m_DrawableNodes = new List<DrawableNode>(); |
|||
|
|||
public IGraphAsset graphAsset { get; set; } |
|||
|
|||
public ICollection<DrawableNode> lastGeneratedNodes |
|||
{ |
|||
get { return m_DrawableNodes; } |
|||
} |
|||
|
|||
private static Type[] GetTypesFromAssembly(Assembly assembly) |
|||
{ |
|||
if (assembly == null) |
|||
return new Type[] {}; |
|||
try |
|||
{ |
|||
return assembly.GetTypes(); |
|||
} |
|||
catch (ReflectionTypeLoadException) |
|||
{ |
|||
return new Type[] {}; |
|||
} |
|||
} |
|||
|
|||
private static Dictionary<Type, Type> s_DrawerUI; |
|||
|
|||
private static Dictionary<Type, Type> drawerUI |
|||
{ |
|||
get |
|||
{ |
|||
if (s_DrawerUI == null) |
|||
{ |
|||
s_DrawerUI = new Dictionary<Type, Type>(); |
|||
var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => GetTypesFromAssembly(x)); |
|||
|
|||
foreach (var type in loadedTypes) |
|||
{ |
|||
var attribute = type.GetCustomAttributes(true).OfType<CustomNodeUI>().FirstOrDefault(); |
|||
if (attribute != null && typeof(ICustomNodeUi).IsAssignableFrom(type)) |
|||
s_DrawerUI.Add(attribute.nodeToDrawFor, type); |
|||
} |
|||
} |
|||
return s_DrawerUI; |
|||
} |
|||
} |
|||
|
|||
public CanvasElement[] FetchElements() |
|||
{ |
|||
m_DrawableNodes.Clear(); |
|||
var graph = graphAsset.graph; |
|||
Debug.LogFormat("Trying to convert: {0}", graphAsset.graph); |
|||
foreach (var node in graph.GetNodes<INode>()) |
|||
{ |
|||
var nodeType = node.GetType(); |
|||
Type draweruiType = null; |
|||
|
|||
while (draweruiType == null && nodeType != null) |
|||
{ |
|||
draweruiType = drawerUI.FirstOrDefault(x => x.Key == nodeType).Value; |
|||
nodeType = nodeType.BaseType; |
|||
} |
|||
|
|||
ICustomNodeUi customUI = null; |
|||
if (draweruiType != null) |
|||
{ |
|||
try |
|||
{ |
|||
customUI = Activator.CreateInstance(draweruiType) as ICustomNodeUi; |
|||
customUI.node = node; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Debug.LogWarningFormat("Could not construct instance of: {0} - {1}", draweruiType, e); |
|||
} |
|||
} |
|||
|
|||
// add the nodes
|
|||
m_DrawableNodes.Add(new DrawableNode(node, customUI, this)); |
|||
} |
|||
|
|||
// Add the edges now
|
|||
var drawableEdges = new List<DrawableEdge<NodeAnchor>>(); |
|||
foreach (var drawableMaterialNode in m_DrawableNodes) |
|||
{ |
|||
var baseNode = drawableMaterialNode.m_Node; |
|||
foreach (var slot in baseNode.GetOutputSlots<ISlot>()) |
|||
{ |
|||
var sourceAnchor = (NodeAnchor)drawableMaterialNode.Children().FirstOrDefault(x => x is NodeAnchor && ((NodeAnchor)x).m_Slot == slot); |
|||
|
|||
var edges = baseNode.owner.GetEdges(new SlotReference(baseNode.guid, slot.id)); |
|||
foreach (var edge in edges) |
|||
{ |
|||
var toNode = baseNode.owner.GetNodeFromGuid(edge.inputSlot.nodeGuid); |
|||
var toSlot = toNode.FindInputSlot<ISlot>(edge.inputSlot.slotId); |
|||
var targetNode = m_DrawableNodes.FirstOrDefault(x => x.m_Node == toNode); |
|||
var targetAnchor = (NodeAnchor)targetNode.Children().FirstOrDefault(x => x is NodeAnchor && ((NodeAnchor)x).m_Slot == toSlot); |
|||
drawableEdges.Add(new DrawableEdge<NodeAnchor>(edge, this, sourceAnchor, targetAnchor)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Add proxy inputs for when edges are not connect
|
|||
var nullInputSlots = new List<NullInputProxy>(); |
|||
foreach (var drawableMaterialNode in m_DrawableNodes) |
|||
{ |
|||
var baseNode = drawableMaterialNode.m_Node; |
|||
// grab the input slots where there are no edges
|
|||
foreach (var slot in baseNode.GetInputsWithNoConnection()) |
|||
{ |
|||
// if there is no anchor, continue
|
|||
// this can happen if we are in collapsed mode
|
|||
var sourceAnchor = (NodeAnchor)drawableMaterialNode.Children().FirstOrDefault(x => x is NodeAnchor && ((NodeAnchor)x).m_Slot == slot); |
|||
if (sourceAnchor == null) |
|||
continue; |
|||
|
|||
nullInputSlots.Add(new NullInputProxy(baseNode, slot, sourceAnchor)); |
|||
} |
|||
} |
|||
var toReturn = new List<CanvasElement>(); |
|||
toReturn.AddRange(m_DrawableNodes.Select(x => (CanvasElement)x)); |
|||
toReturn.AddRange(drawableEdges.Select(x => (CanvasElement)x)); |
|||
toReturn.AddRange(nullInputSlots.Select(x => (CanvasElement)x)); |
|||
|
|||
//toReturn.Add(new FloatingPreview(new Rect(Screen.width - 300, Screen.height - 300, 300, 300), pixelGraph.nodes.FirstOrDefault(x => x is PixelShaderNode)));
|
|||
|
|||
Debug.LogFormat("Returning {0} nodes", m_DrawableNodes.Count); |
|||
Debug.LogFormat("Returning {0} drawableEdges", drawableEdges.Count); |
|||
Debug.LogFormat("Returning {0} nullInputSlots", nullInputSlots.Count); |
|||
return toReturn.ToArray(); |
|||
} |
|||
|
|||
public void DeleteElement(CanvasElement e) |
|||
{ |
|||
// do nothing here, we want to use delete elements.
|
|||
// delete elements ensures that edges are deleted before nodes.
|
|||
} |
|||
|
|||
public void DeleteElements(List<CanvasElement> elements) |
|||
{ |
|||
var graph = graphAsset.graph; |
|||
var toRemoveEdge = new List<IEdge>(); |
|||
// delete selected edges first
|
|||
foreach (var e in elements.OfType<Edge<NodeAnchor>>()) |
|||
{ |
|||
//find the edge
|
|||
var edge = graph.edges.FirstOrDefault(x => graph.GetNodeFromGuid(x.outputSlot.nodeGuid).FindOutputSlot<ISlot>(x.outputSlot.slotId) == e.Left.m_Slot |
|||
&& graph.GetNodeFromGuid(x.inputSlot.nodeGuid).FindInputSlot<ISlot>(x.inputSlot.slotId) == e.Right.m_Slot); |
|||
|
|||
toRemoveEdge.Add(edge); |
|||
} |
|||
|
|||
var toRemoveNode = new List<INode>(); |
|||
// now delete the nodes
|
|||
foreach (var e in elements.OfType<DrawableNode>()) |
|||
{ |
|||
if (!e.m_Node.canDeleteNode) |
|||
continue; |
|||
toRemoveNode.Add(e.m_Node); |
|||
} |
|||
graph.RemoveElements(toRemoveNode, toRemoveEdge); |
|||
MarkDirty(); |
|||
} |
|||
|
|||
public void Connect(NodeAnchor a, NodeAnchor b) |
|||
{ |
|||
var graph = graphAsset.graph; |
|||
graph.Connect(a.m_Node.GetSlotReference(a.m_Slot.id), b.m_Node.GetSlotReference(b.m_Slot.id)); |
|||
MarkDirty(); |
|||
} |
|||
|
|||
public void Addnode(INode node) |
|||
{ |
|||
var graph = graphAsset.graph; |
|||
graph.AddNode(node); |
|||
MarkDirty(); |
|||
} |
|||
|
|||
public void MarkDirty() |
|||
{ |
|||
EditorUtility.SetDirty(graphAsset.GetScriptableObject()); |
|||
} |
|||
|
|||
/* |
|||
} |
|||
|
|||
public class FloatingPreview : CanvasElement |
|||
{ |
|||
private AbstractMaterialNode m_Node; |
|||
|
|||
public FloatingPreview(Rect position, AbstractMaterialNode node) |
|||
{ |
|||
m_Node = node as AbstractMaterialNode; |
|||
m_Translation = new Vector2(position.x, position.y); |
|||
m_Scale = new Vector3(position.width, position.height, 1); |
|||
m_Caps |= Capabilities.Floating | Capabilities.Unselectable; |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
var drawArea = new Rect(0, 0, scale.x, scale.y); |
|||
Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.7f); |
|||
EditorGUI.DrawRect(drawArea, backgroundColor); |
|||
|
|||
drawArea.width -= 10; |
|||
drawArea.height -= 10; |
|||
drawArea.x += 5; |
|||
drawArea.y += 5; |
|||
|
|||
GL.sRGBWrite = (QualitySettings.activeColorSpace == ColorSpace.Linear); |
|||
GUI.DrawTexture(drawArea, m_Node.RenderPreview(new Rect(0, 0, drawArea.width, drawArea.height)), ScaleMode.StretchToFill, false); |
|||
GL.sRGBWrite = false; |
|||
|
|||
Invalidate(); |
|||
canvas.Repaint(); |
|||
}* |
|||
}*/ |
|||
} |
|
|||
|
|
|||
using System; |
|||
using System.Reflection; |
|||
using RMGUI.GraphView; |
|||
using RMGUI.GraphView.Demo; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
using UnityEngine.RMGUI; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[StyleSheet("Assets/UnityShaderEditor/Editor/Styles/NodalView.uss")] |
|||
//[StyleSheet("Assets/UnityShaderEditor/Editor/Styles/MatGraph.uss")]
|
|||
public class MaterialGraphView : GraphView |
|||
{ |
|||
public MaterialGraphView() |
|||
{ |
|||
AddManipulator(new ContentZoomer()); |
|||
AddManipulator(new ContentDragger()); |
|||
AddManipulator(new RectangleSelector()); |
|||
AddManipulator(new SelectionDragger()); |
|||
AddManipulator(new ClickSelector()); |
|||
AddManipulator(new ContextualMenu(DoContextMenu)); |
|||
AddDecorator(new GridBackground(contentViewContainer)); |
|||
} |
|||
|
|||
public virtual bool CanAddToNodeMenu(Type type) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
protected EventPropagation DoContextMenu(Event evt, Object customData) |
|||
{ |
|||
var gm = new GenericMenu(); |
|||
foreach (Type type in Assembly.GetAssembly(typeof(AbstractMaterialNode)).GetTypes()) |
|||
{ |
|||
if (type.IsClass && !type.IsAbstract && (type.IsSubclassOf(typeof(AbstractMaterialNode)))) |
|||
{ |
|||
var attrs = type.GetCustomAttributes(typeof(TitleAttribute), false) as TitleAttribute[]; |
|||
if (attrs != null && attrs.Length > 0 && CanAddToNodeMenu(type)) |
|||
{ |
|||
gm.AddItem(new GUIContent(attrs[0].m_Title), false, AddNode, new AddNodeCreationObject(type, evt.mousePosition)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
//gm.AddSeparator("");
|
|||
// gm.AddItem(new GUIContent("Convert To/SubGraph"), true, ConvertSelectionToSubGraph);
|
|||
gm.ShowAsContext(); |
|||
return EventPropagation.Stop; |
|||
} |
|||
|
|||
private class AddNodeCreationObject : object |
|||
{ |
|||
public Vector2 m_Pos; |
|||
public readonly Type m_Type; |
|||
|
|||
public AddNodeCreationObject(Type t, Vector2 p) |
|||
{ |
|||
m_Type = t; |
|||
m_Pos = p; |
|||
} |
|||
}; |
|||
|
|||
private void AddNode(object obj) |
|||
{ |
|||
var posObj = obj as AddNodeCreationObject; |
|||
if (posObj == null) |
|||
return; |
|||
|
|||
INode node; |
|||
try |
|||
{ |
|||
node = Activator.CreateInstance(posObj.m_Type) as INode; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Debug.LogWarningFormat("Could not construct instance of: {0} - {1}", posObj.m_Type, e); |
|||
return; |
|||
} |
|||
|
|||
if (node == null) |
|||
return; |
|||
var drawstate = node.drawState; |
|||
drawstate.position = new Rect(posObj.m_Pos.x, posObj.m_Pos.y, drawstate.position.width, drawstate.position.height); |
|||
node.drawState = drawstate; |
|||
/*m_DataSource.Addnode(node); |
|||
Rebuild(); |
|||
Repaint();*/ |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
using System.Reflection; |
|||
using RMGUI.GraphView; |
|||
using RMGUI.GraphView.Demo; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
using UnityEngine.RMGUI; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[StyleSheet("Assets/UnityShaderEditor/Editor/Styles/NodalView.uss")] |
|||
//[StyleSheet("Assets/UnityShaderEditor/Editor/Styles/MatGraph.uss")]
|
|||
public class MaterialGraphView : GraphView |
|||
{ |
|||
public MaterialGraphView() |
|||
{ |
|||
AddManipulator(new ContentZoomer()); |
|||
AddManipulator(new ContentDragger()); |
|||
AddManipulator(new RectangleSelector()); |
|||
AddManipulator(new SelectionDragger()); |
|||
AddManipulator(new ClickSelector()); |
|||
AddManipulator(new ContextualMenu(DoContextMenu)); |
|||
AddDecorator(new GridBackground(contentViewContainer)); |
|||
} |
|||
|
|||
public virtual bool CanAddToNodeMenu(Type type) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
protected EventPropagation DoContextMenu(Event evt, Object customData) |
|||
{ |
|||
var gm = new GenericMenu(); |
|||
foreach (Type type in Assembly.GetAssembly(typeof(AbstractMaterialNode)).GetTypes()) |
|||
{ |
|||
if (type.IsClass && !type.IsAbstract && (type.IsSubclassOf(typeof(AbstractMaterialNode)))) |
|||
{ |
|||
var attrs = type.GetCustomAttributes(typeof(TitleAttribute), false) as TitleAttribute[]; |
|||
if (attrs != null && attrs.Length > 0 && CanAddToNodeMenu(type)) |
|||
{ |
|||
gm.AddItem(new GUIContent(attrs[0].m_Title), false, AddNode, new AddNodeCreationObject(type, evt.mousePosition)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
//gm.AddSeparator("");
|
|||
// gm.AddItem(new GUIContent("Convert To/SubGraph"), true, ConvertSelectionToSubGraph);
|
|||
gm.ShowAsContext(); |
|||
return EventPropagation.Stop; |
|||
} |
|||
|
|||
private class AddNodeCreationObject : object |
|||
{ |
|||
public Vector2 m_Pos; |
|||
public readonly Type m_Type; |
|||
|
|||
public AddNodeCreationObject(Type t, Vector2 p) |
|||
{ |
|||
m_Type = t; |
|||
m_Pos = p; |
|||
} |
|||
}; |
|||
|
|||
private void AddNode(object obj) |
|||
{ |
|||
var posObj = obj as AddNodeCreationObject; |
|||
if (posObj == null) |
|||
return; |
|||
|
|||
INode node; |
|||
try |
|||
{ |
|||
node = Activator.CreateInstance(posObj.m_Type) as INode; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Debug.LogWarningFormat("Could not construct instance of: {0} - {1}", posObj.m_Type, e); |
|||
return; |
|||
} |
|||
|
|||
if (node == null) |
|||
return; |
|||
var drawstate = node.drawState; |
|||
drawstate.position = new Rect(posObj.m_Pos.x, posObj.m_Pos.y, drawstate.position.width, drawstate.position.height); |
|||
node.drawState = drawstate; |
|||
/*m_DataSource.Addnode(node); |
|||
Rebuild(); |
|||
Repaint();*/ |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using RMGUI.GraphView; |
|||
using RMGUI.GraphView.Demo; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
public class MaterialNodeAnchorData : NodeAnchorData |
|||
{ |
|||
protected MaterialNodeAnchorData() |
|||
{} |
|||
|
|||
public ISlot slot { get; private set; } |
|||
|
|||
public void Initialize(ISlot slot) |
|||
{ |
|||
this.slot = slot; |
|||
name = slot.displayName; |
|||
type = typeof(Vector4); |
|||
direction = slot.isInputSlot ? Direction.Input : Direction.Output; |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
using RMGUI.GraphView; |
|||
using RMGUI.GraphView.Demo; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
public class MaterialNodeAnchorData : NodeAnchorData |
|||
{ |
|||
protected MaterialNodeAnchorData() |
|||
{} |
|||
|
|||
public ISlot slot { get; private set; } |
|||
|
|||
public void Initialize(ISlot slot) |
|||
{ |
|||
this.slot = slot; |
|||
name = slot.displayName; |
|||
type = typeof(Vector4); |
|||
direction = slot.isInputSlot ? Direction.Input : Direction.Output; |
|||
} |
|||
} |
|||
} |
|
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
/* |
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
public class NullInputProxy : CanvasElement |
|||
{ |
|||
private ISlot m_InputSlot; |
|||
private INode m_Node; |
|||
private NodeAnchor m_NodeAnchor; |
|||
|
|||
private const int kWidth = 180; |
|||
|
|||
public NullInputProxy(INode node, ISlot inputSlot, NodeAnchor nodeAnchor) |
|||
{ |
|||
m_InputSlot = inputSlot; |
|||
m_Node = node; |
|||
m_NodeAnchor = nodeAnchor; |
|||
|
|||
var size = m_NodeAnchor.scale; |
|||
size.x = kWidth; |
|||
scale = size; |
|||
|
|||
nodeAnchor.AddDependency(this); |
|||
UpdateModel(UpdateType.Update); |
|||
|
|||
var position = m_NodeAnchor.canvasBoundingRect.min; |
|||
position.x -= kWidth; |
|||
translation = position; |
|||
AddManipulator(new ImguiContainer()); |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
base.Render(parentRect, canvas); |
|||
|
|||
var size = m_NodeAnchor.scale; |
|||
size.x = kWidth; |
|||
scale = size; |
|||
|
|||
var position = m_NodeAnchor.canvasBoundingRect.min; |
|||
position.x -= kWidth; |
|||
translation = position; |
|||
|
|||
var rect = new Rect(0, 0, scale.x, scale.y); |
|||
EditorGUI.DrawRect(rect, new Color(0.0f, 0.0f, 0.0f, 0.7f)); |
|||
|
|||
//TODO: FIX
|
|||
/*var changed = m_Node.DrawSlotDefaultInput(rect, m_InputSlot); |
|||
if (changed) |
|||
DrawableMaterialNode.RepaintDependentNodes(m_Node);* |
|||
} |
|||
|
|||
public override void UpdateModel(UpdateType t) |
|||
{ |
|||
var size = m_NodeAnchor.scale; |
|||
size.x = kWidth; |
|||
scale = size; |
|||
|
|||
var position = m_NodeAnchor.canvasBoundingRect.min; |
|||
position.x -= kWidth; |
|||
translation = position; |
|||
|
|||
base.UpdateModel(t); |
|||
} |
|||
|
|||
}*/ |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
/* |
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
public class NullInputProxy : CanvasElement |
|||
{ |
|||
private ISlot m_InputSlot; |
|||
private INode m_Node; |
|||
private NodeAnchor m_NodeAnchor; |
|||
|
|||
private const int kWidth = 180; |
|||
|
|||
public NullInputProxy(INode node, ISlot inputSlot, NodeAnchor nodeAnchor) |
|||
{ |
|||
m_InputSlot = inputSlot; |
|||
m_Node = node; |
|||
m_NodeAnchor = nodeAnchor; |
|||
|
|||
var size = m_NodeAnchor.scale; |
|||
size.x = kWidth; |
|||
scale = size; |
|||
|
|||
nodeAnchor.AddDependency(this); |
|||
UpdateModel(UpdateType.Update); |
|||
|
|||
var position = m_NodeAnchor.canvasBoundingRect.min; |
|||
position.x -= kWidth; |
|||
translation = position; |
|||
AddManipulator(new ImguiContainer()); |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
base.Render(parentRect, canvas); |
|||
|
|||
var size = m_NodeAnchor.scale; |
|||
size.x = kWidth; |
|||
scale = size; |
|||
|
|||
var position = m_NodeAnchor.canvasBoundingRect.min; |
|||
position.x -= kWidth; |
|||
translation = position; |
|||
|
|||
var rect = new Rect(0, 0, scale.x, scale.y); |
|||
EditorGUI.DrawRect(rect, new Color(0.0f, 0.0f, 0.0f, 0.7f)); |
|||
|
|||
//TODO: FIX
|
|||
/*var changed = m_Node.DrawSlotDefaultInput(rect, m_InputSlot); |
|||
if (changed) |
|||
DrawableMaterialNode.RepaintDependentNodes(m_Node);* |
|||
} |
|||
|
|||
public override void UpdateModel(UpdateType t) |
|||
{ |
|||
var size = m_NodeAnchor.scale; |
|||
size.x = kWidth; |
|||
scale = size; |
|||
|
|||
var position = m_NodeAnchor.canvasBoundingRect.min; |
|||
position.x -= kWidth; |
|||
translation = position; |
|||
|
|||
base.UpdateModel(t); |
|||
} |
|||
|
|||
}*/ |
|
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
|
|||
namespace UnityEditor.MaterialGraph.IntegrationTests |
|||
{ |
|||
public class ShaderGenerationTest |
|||
{ |
|||
private static readonly string[] s_Path = |
|||
{ |
|||
"UnityShaderEditor", |
|||
"Editor", |
|||
"Testing", |
|||
"IntegrationTests", |
|||
"Graphs" |
|||
}; |
|||
|
|||
public struct TestInfo |
|||
{ |
|||
public string name; |
|||
public FileInfo info; |
|||
public float threshold; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return name; |
|||
} |
|||
} |
|||
|
|||
public static class CollectGraphs |
|||
{ |
|||
public static IEnumerable graphs |
|||
{ |
|||
get |
|||
{ |
|||
var absoluteGraphsPath = s_Path.Aggregate(Application.dataPath, Path.Combine); |
|||
var filePaths = Directory.GetFiles(absoluteGraphsPath).Select(x => new FileInfo(x)).Where(x => x.Extension == ".ShaderGraph"); |
|||
|
|||
foreach (var p in filePaths) |
|||
{ |
|||
yield return new TestInfo |
|||
{ |
|||
name = p.Name, |
|||
info = p, |
|||
threshold = 0.02f |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Shader m_Shader; |
|||
private Material m_PreviewMaterial; |
|||
private Texture2D m_Captured; |
|||
private Texture2D m_FromDisk; |
|||
|
|||
[TearDown] |
|||
public void CleanUp() |
|||
{ |
|||
if (m_Shader != null) |
|||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Shader)); |
|||
|
|||
if (m_PreviewMaterial != null) |
|||
Object.DestroyImmediate(m_PreviewMaterial); |
|||
|
|||
if (m_Captured != null) |
|||
Object.DestroyImmediate(m_Captured); |
|||
|
|||
if (m_FromDisk != null) |
|||
Object.DestroyImmediate(m_FromDisk); |
|||
} |
|||
|
|||
[Test, TestCaseSource(typeof(CollectGraphs), "graphs")] |
|||
public void ShaderGeneratorOutput(TestInfo testInfo) |
|||
{ |
|||
var file = testInfo.info; |
|||
var prjRelativeGraphsPath = s_Path.Aggregate("Assets", Path.Combine); |
|||
var filePath = Path.Combine(prjRelativeGraphsPath, file.Name); |
|||
|
|||
var graphAsset = AssetDatabase.LoadAssetAtPath<MaterialGraphAsset>(filePath); |
|||
|
|||
Assert.IsNotNull(graphAsset, "Graph asset not found"); |
|||
|
|||
var materialGraph = graphAsset.graph as PixelGraph; |
|||
Assert.IsNotNull(materialGraph); |
|||
|
|||
// Generate the shader
|
|||
List<PropertyGenerator.TextureInfo> configuredTextures; |
|||
var shaderString = ShaderGenerator.GenerateSurfaceShader(materialGraph.pixelMasterNode, graphAsset.options, materialGraph.name, false, out configuredTextures); |
|||
m_Shader = ShaderUtil.CreateShaderAsset(shaderString); |
|||
m_Shader.hideFlags = HideFlags.HideAndDontSave; |
|||
Assert.IsNotNull(m_Shader, "Shader Generation Failed"); |
|||
//Assert.IsFalse(AbstractMaterialNodeUI.ShaderHasError(m_Shader), "Shader has error");
|
|||
|
|||
m_PreviewMaterial = new Material(m_Shader) |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave |
|||
}; |
|||
|
|||
foreach (var textureInfo in configuredTextures) |
|||
{ |
|||
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture; |
|||
if (texture == null) |
|||
continue; |
|||
m_PreviewMaterial.SetTexture(textureInfo.name, texture); |
|||
} |
|||
|
|||
Assert.IsNotNull(m_PreviewMaterial, "preview material could not be created"); |
|||
|
|||
const int res = 256; |
|||
var generator = new MaterialGraphPreviewGenerator(); |
|||
var rendered = generator.DoRenderPreview(m_PreviewMaterial, PreviewMode.Preview3D, new Rect(0, 0, res, res), 10) as RenderTexture; |
|||
|
|||
Assert.IsNotNull(rendered, "Render failed"); |
|||
|
|||
RenderTexture.active = rendered; |
|||
m_Captured = new Texture2D(rendered.width, rendered.height, TextureFormat.ARGB32, false); |
|||
m_Captured.ReadPixels(new Rect(0, 0, rendered.width, rendered.height), 0, 0); |
|||
RenderTexture.active = null; //can help avoid errors
|
|||
|
|||
var rootPath = Directory.GetParent(Directory.GetParent(Application.dataPath).ToString()); |
|||
var templatePath = Path.Combine(rootPath.ToString(), "ImageTemplates"); |
|||
|
|||
// find the reference image
|
|||
var dumpFileLocation = Path.Combine(templatePath, string.Format("{0}.{1}", file.Name, "png")); |
|||
if (!File.Exists(dumpFileLocation)) |
|||
{ |
|||
// no reference exists, create it
|
|||
Directory.CreateDirectory(templatePath); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(dumpFileLocation, generated); |
|||
Assert.Fail("Template file not found for {0}, creating it.", file); |
|||
} |
|||
|
|||
var template = File.ReadAllBytes(dumpFileLocation); |
|||
m_FromDisk = new Texture2D(2,2); |
|||
m_FromDisk.LoadImage(template, false); |
|||
|
|||
var areEqual = CompareTextures(m_FromDisk, m_Captured, testInfo.threshold); |
|||
|
|||
if (!areEqual) |
|||
{ |
|||
var failedPath = Path.Combine(rootPath.ToString(), "Failed"); |
|||
Directory.CreateDirectory(failedPath); |
|||
var misMatchLocationResult = Path.Combine(failedPath, string.Format("{0}.{1}", file.Name, "png")); |
|||
var misMatchLocationTemplate = Path.Combine(failedPath, string.Format("{0}.template.{1}", file.Name, "png")); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(misMatchLocationResult, generated); |
|||
File.WriteAllBytes(misMatchLocationTemplate, template); |
|||
} |
|||
|
|||
Assert.IsTrue(areEqual, "Shader from graph {0}, did not match .template file.", file); |
|||
} |
|||
|
|||
private bool CompareTextures(Texture2D fromDisk, Texture2D captured, float threshold) |
|||
{ |
|||
if (fromDisk == null || captured == null) |
|||
return false; |
|||
|
|||
if (fromDisk.width != captured.width |
|||
|| fromDisk.height != captured.height) |
|||
return false; |
|||
|
|||
var pixels1 = fromDisk.GetPixels(); |
|||
var pixels2 = captured.GetPixels(); |
|||
|
|||
if (pixels1.Length != pixels2.Length) |
|||
return false; |
|||
|
|||
for (int i = 0; i < pixels1.Length; i++) |
|||
{ |
|||
if (!CompareColor(pixels1[i], pixels2[i], threshold)) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private bool CompareColor(Vector4 left, Vector4 right, float threshold) |
|||
{ |
|||
Vector4 diff = left - right; |
|||
|
|||
if (Mathf.Abs(diff.x) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.y) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.z) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.w) > threshold) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
|
|||
namespace UnityEditor.MaterialGraph.IntegrationTests |
|||
{ |
|||
public class ShaderGenerationTest |
|||
{ |
|||
private static readonly string[] s_Path = |
|||
{ |
|||
"UnityShaderEditor", |
|||
"Editor", |
|||
"Testing", |
|||
"IntegrationTests", |
|||
"Graphs" |
|||
}; |
|||
|
|||
public struct TestInfo |
|||
{ |
|||
public string name; |
|||
public FileInfo info; |
|||
public float threshold; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return name; |
|||
} |
|||
} |
|||
|
|||
public static class CollectGraphs |
|||
{ |
|||
public static IEnumerable graphs |
|||
{ |
|||
get |
|||
{ |
|||
var absoluteGraphsPath = s_Path.Aggregate(Application.dataPath, Path.Combine); |
|||
var filePaths = Directory.GetFiles(absoluteGraphsPath).Select(x => new FileInfo(x)).Where(x => x.Extension == ".ShaderGraph"); |
|||
|
|||
foreach (var p in filePaths) |
|||
{ |
|||
yield return new TestInfo |
|||
{ |
|||
name = p.Name, |
|||
info = p, |
|||
threshold = 0.02f |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Shader m_Shader; |
|||
private Material m_PreviewMaterial; |
|||
private Texture2D m_Captured; |
|||
private Texture2D m_FromDisk; |
|||
|
|||
[TearDown] |
|||
public void CleanUp() |
|||
{ |
|||
if (m_Shader != null) |
|||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Shader)); |
|||
|
|||
if (m_PreviewMaterial != null) |
|||
Object.DestroyImmediate(m_PreviewMaterial); |
|||
|
|||
if (m_Captured != null) |
|||
Object.DestroyImmediate(m_Captured); |
|||
|
|||
if (m_FromDisk != null) |
|||
Object.DestroyImmediate(m_FromDisk); |
|||
} |
|||
|
|||
[Test, TestCaseSource(typeof(CollectGraphs), "graphs")] |
|||
public void ShaderGeneratorOutput(TestInfo testInfo) |
|||
{ |
|||
var file = testInfo.info; |
|||
var prjRelativeGraphsPath = s_Path.Aggregate("Assets", Path.Combine); |
|||
var filePath = Path.Combine(prjRelativeGraphsPath, file.Name); |
|||
|
|||
var graphAsset = AssetDatabase.LoadAssetAtPath<MaterialGraphAsset>(filePath); |
|||
|
|||
Assert.IsNotNull(graphAsset, "Graph asset not found"); |
|||
|
|||
var materialGraph = graphAsset.graph as PixelGraph; |
|||
Assert.IsNotNull(materialGraph); |
|||
|
|||
// Generate the shader
|
|||
List<PropertyGenerator.TextureInfo> configuredTextures; |
|||
var shaderString = ShaderGenerator.GenerateSurfaceShader(materialGraph.pixelMasterNode, graphAsset.options, materialGraph.name, false, out configuredTextures); |
|||
m_Shader = ShaderUtil.CreateShaderAsset(shaderString); |
|||
m_Shader.hideFlags = HideFlags.HideAndDontSave; |
|||
Assert.IsNotNull(m_Shader, "Shader Generation Failed"); |
|||
//Assert.IsFalse(AbstractMaterialNodeUI.ShaderHasError(m_Shader), "Shader has error");
|
|||
|
|||
m_PreviewMaterial = new Material(m_Shader) |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave |
|||
}; |
|||
|
|||
foreach (var textureInfo in configuredTextures) |
|||
{ |
|||
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture; |
|||
if (texture == null) |
|||
continue; |
|||
m_PreviewMaterial.SetTexture(textureInfo.name, texture); |
|||
} |
|||
|
|||
Assert.IsNotNull(m_PreviewMaterial, "preview material could not be created"); |
|||
|
|||
const int res = 256; |
|||
var generator = new MaterialGraphPreviewGenerator(); |
|||
var rendered = generator.DoRenderPreview(m_PreviewMaterial, PreviewMode.Preview3D, new Rect(0, 0, res, res), 10) as RenderTexture; |
|||
|
|||
Assert.IsNotNull(rendered, "Render failed"); |
|||
|
|||
RenderTexture.active = rendered; |
|||
m_Captured = new Texture2D(rendered.width, rendered.height, TextureFormat.ARGB32, false); |
|||
m_Captured.ReadPixels(new Rect(0, 0, rendered.width, rendered.height), 0, 0); |
|||
RenderTexture.active = null; //can help avoid errors
|
|||
|
|||
var rootPath = Directory.GetParent(Directory.GetParent(Application.dataPath).ToString()); |
|||
var templatePath = Path.Combine(rootPath.ToString(), "ImageTemplates"); |
|||
|
|||
// find the reference image
|
|||
var dumpFileLocation = Path.Combine(templatePath, string.Format("{0}.{1}", file.Name, "png")); |
|||
if (!File.Exists(dumpFileLocation)) |
|||
{ |
|||
// no reference exists, create it
|
|||
Directory.CreateDirectory(templatePath); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(dumpFileLocation, generated); |
|||
Assert.Fail("Template file not found for {0}, creating it.", file); |
|||
} |
|||
|
|||
var template = File.ReadAllBytes(dumpFileLocation); |
|||
m_FromDisk = new Texture2D(2, 2); |
|||
m_FromDisk.LoadImage(template, false); |
|||
|
|||
var areEqual = CompareTextures(m_FromDisk, m_Captured, testInfo.threshold); |
|||
|
|||
if (!areEqual) |
|||
{ |
|||
var failedPath = Path.Combine(rootPath.ToString(), "Failed"); |
|||
Directory.CreateDirectory(failedPath); |
|||
var misMatchLocationResult = Path.Combine(failedPath, string.Format("{0}.{1}", file.Name, "png")); |
|||
var misMatchLocationTemplate = Path.Combine(failedPath, string.Format("{0}.template.{1}", file.Name, "png")); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(misMatchLocationResult, generated); |
|||
File.WriteAllBytes(misMatchLocationTemplate, template); |
|||
} |
|||
|
|||
Assert.IsTrue(areEqual, "Shader from graph {0}, did not match .template file.", file); |
|||
} |
|||
|
|||
private bool CompareTextures(Texture2D fromDisk, Texture2D captured, float threshold) |
|||
{ |
|||
if (fromDisk == null || captured == null) |
|||
return false; |
|||
|
|||
if (fromDisk.width != captured.width |
|||
|| fromDisk.height != captured.height) |
|||
return false; |
|||
|
|||
var pixels1 = fromDisk.GetPixels(); |
|||
var pixels2 = captured.GetPixels(); |
|||
|
|||
if (pixels1.Length != pixels2.Length) |
|||
return false; |
|||
|
|||
for (int i = 0; i < pixels1.Length; i++) |
|||
{ |
|||
if (!CompareColor(pixels1[i], pixels2[i], threshold)) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private bool CompareColor(Vector4 left, Vector4 right, float threshold) |
|||
{ |
|||
Vector4 diff = left - right; |
|||
|
|||
if (Mathf.Abs(diff.x) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.y) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.z) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.w) > threshold) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue