浏览代码

[material graph]Convert slots from being a string into being an int that can be referenced from the node.

/main
Tim Cooper 9 年前
当前提交
7ae021c6
共有 47 个文件被更改,包括 661 次插入580 次删除
  1. 4
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/CopySelected.cs
  2. 4
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/DrawableNode.cs
  3. 10
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphDataSource.cs
  4. 22
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs
  5. 10
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/IntegrationTests/SerializationTests.cs
  6. 311
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/UnitTests/SerializedGraphTests.cs
  7. 26
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/NodeUtils.cs
  8. 12
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableGraph.cs
  9. 37
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableNode.cs
  10. 40
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableSlot.cs
  11. 10
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/INode.cs
  12. 4
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/ISlot.cs
  13. 10
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/SlotReference.cs
  14. 135
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/DynamicSlotTests.cs
  15. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/Function1InputTests.cs
  16. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/Function2InputTests.cs
  17. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/Function3InputTests.cs
  18. 61
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/MaterialNodeTests.cs
  19. 45
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/ShaderGeneratorTests.cs
  20. 81
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Light/BaseLightFunction.cs
  21. 33
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/AbstractMaterialNode.cs
  22. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ColorNode.cs
  23. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/DotNode.cs
  24. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/FresnelNode.cs
  25. 22
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function1Input.cs
  26. 30
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function2Input.cs
  27. 53
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function3Input.cs
  28. 35
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/MaterialSlot.cs
  29. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/NormalNode.cs
  30. 18
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/PixelShaderNode.cs
  31. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ReflectNode.cs
  32. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ScreenPosNode.cs
  33. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/SinTimeNode.cs
  34. 49
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/TextureNode.cs
  35. 30
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/TimeNode.cs
  36. 7
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UVNode.cs
  37. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UnpackNormalNode.cs
  38. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector1Node.cs
  39. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector2Node.cs
  40. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector3Node.cs
  41. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector4Node.cs
  42. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ViewDirectionNode.cs
  43. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/WorldPosNode.cs
  44. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/AbstractSubGraphIONode.cs
  45. 14
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphInputNode.cs
  46. 14
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphNode.cs
  47. 9
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphOutputNode.cs

4
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/CopySelected.cs


if (nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid)
&& nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid))
{
var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotName);
var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotName);
var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId);
var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId);
addedEdges.Add(graph.Connect(outputSlotRef, inputSlotRef));
}
}

4
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/DrawableNode.cs


pos.x = width;
pos.y = yStart;
bool first = true;
foreach (var slot in node.GetOutputSlots<ISlot>().OrderBy(x => x.priority))
foreach (var slot in node.GetOutputSlots<ISlot>().OrderBy(x => x.priority).ThenBy(x => x.id))
var edges = node.owner.GetEdges(node.GetSlotReference(slot.name));
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;

10
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphDataSource.cs


{
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.name));
var edges = baseNode.owner.GetEdges(new SlotReference(baseNode.guid, slot.id));
var toSlot = toNode.FindInputSlot<ISlot>(edge.inputSlot.slotName);
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));

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.slotName) == e.Left.m_Slot
&& graph.GetNodeFromGuid(x.inputSlot.nodeGuid).FindInputSlot<ISlot>(x.inputSlot.slotName) == e.Right.m_Slot);
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);
}

public void Connect(NodeAnchor a, NodeAnchor b)
{
var graph = graphAsset.graph;
graph.Connect(a.m_Node.GetSlotReference(a.m_Slot.name), b.m_Node.GetSlotReference(b.m_Slot.name));
graph.Connect(a.m_Node.GetSlotReference(a.m_Slot.id), b.m_Node.GetSlotReference(b.m_Slot.id));
MarkDirty();
}

22
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs


// pasting nice internal links!
if (outputRemapExists && inputRemapExists)
{
var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotName);
var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotName);
var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId);
var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId);
graph.Connect(outputSlotRef, inputSlotRef);
}
// one edge needs to go to outside world

foreach (var group in uniqueOutputs)
{
var inputNode = graph.inputNode;
var index = inputNode.GetOutputSlots<ISlot>().Count();
inputNode.AddSlot();
var slotId = inputNode.AddSlot();
var outputSlotRef = new SlotReference(inputNode.guid, "Input" + index);
var outputSlotRef = new SlotReference(inputNode.guid, slotId);
var newEdge = graph.Connect(outputSlotRef, new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotName));
var newEdge = graph.Connect(outputSlotRef, new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId));
inputsNeedingConnection.Add(new KeyValuePair<IEdge, IEdge>(edge, newEdge));
}
}

foreach (var group in uniqueInputs)
{
var outputNode = graph.outputNode;
var index = outputNode.GetInputSlots<ISlot>().Count();
outputNode.AddSlot();
var slotId = outputNode.AddSlot();
var inputSlotRef = new SlotReference(outputNode.guid, "Output" + index);
var inputSlotRef = new SlotReference(outputNode.guid, slotId);
var newEdge = graph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotName), inputSlotRef);
var newEdge = graph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef);
outputsNeedingConnection.Add(new KeyValuePair<IEdge, IEdge>(edge, newEdge));
}
}

foreach (var edgeMap in inputsNeedingConnection)
{
targetGraph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.outputSlot.slotName));
targetGraph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.outputSlot.slotId));
targetGraph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotName), edgeMap.Key.inputSlot);
targetGraph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
}
var toDelete = m_Canvas.selection.Where(x => x is DrawableNode).ToList();

10
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/IntegrationTests/SerializationTests.cs


{
var toSerialize = new List<SerializableSlot>()
{
new SerializableSlot("InSlot", "InSlot", SlotType.Input, 0),
new SerializableSlot("OutSlot", "OutSlot", SlotType.Output, 0),
new SerializableSlot(0, "InSlot", SlotType.Input, 0),
new SerializableSlot(1, "OutSlot", SlotType.Output, 5),
};
var serialized = SerializationHelper.Serialize(toSerialize);

Assert.IsInstanceOf<SerializableSlot>(loaded[0]);
Assert.IsInstanceOf<SerializableSlot>(loaded[1]);
Assert.AreEqual("InSlot", loaded[0].name);
Assert.AreEqual(0, loaded[0].id);
Assert.AreEqual("OutSlot", loaded[1].name);
Assert.AreEqual(1, loaded[1].id);
Assert.AreEqual(0, loaded[1].priority);
Assert.AreEqual(5, loaded[1].priority);
}
}
}

311
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/UnitTests/SerializedGraphTests.cs


Assert.AreNotEqual(guid, newGuid);
}
public class TestableNode : SerializableNode
{
public const int Input0 = 0;
public const int Input1 = 1;
public const int Input2 = 2;
public const int Output0 = 3;
public const int Output1 = 4;
public const int Output2 = 5;
public TestableNode()
{
AddSlot(new SerializableSlot(Input0, "Input", SlotType.Input));
AddSlot(new SerializableSlot(Input1, "Input", SlotType.Input));
AddSlot(new SerializableSlot(Input2, "Input", SlotType.Input));
AddSlot(new SerializableSlot(Output0, "Output", SlotType.Output));
AddSlot(new SerializableSlot(Output1, "Output", SlotType.Output));
AddSlot(new SerializableSlot(Output2, "Output", SlotType.Output));
}
}
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
var createdEdge = graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
var createdEdge = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.edges.Count());
var edge = graph.edges.FirstOrDefault();

{
var graph = new SerializableGraph();
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("input", "input", SlotType.Input, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output));
node.AddSlot(new SerializableSlot(1, "input", SlotType.Input));
node.name = "Test Node";
graph.AddNode(node);

Assert.AreEqual("input", found.GetInputSlots<ISlot>().FirstOrDefault().name);
Assert.AreEqual(1, found.GetInputSlots<ISlot>().FirstOrDefault().id);
Assert.AreEqual("output", found.GetOutputSlots<ISlot>().FirstOrDefault().name);
Assert.AreEqual(0, found.GetOutputSlots<ISlot>().FirstOrDefault().id);
Assert.AreEqual(2, found.GetSlots<ISlot>().Count());
}

{
var graph = new SerializableGraph();
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("input", "input", SlotType.Input, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output));
node.AddSlot(new SerializableSlot(1, "input", SlotType.Input));
graph.AddNode(node);
Assert.AreEqual(2, node.GetSlots<ISlot>().Count());

node.RemoveSlot("input");
node.RemoveSlot(1);
Assert.AreEqual(1, node.GetSlots<ISlot>().Count());
Assert.AreEqual(0, node.GetInputSlots<ISlot>().Count());

public void TestCanRemoveSlotsWithNonMathingNameFromSerializableNode()
{
var graph = new SerializableGraph();
var node = new SerializableNode();
var node = new TestableNode();
node.AddSlot(new SerializableSlot("input1", "input", SlotType.Input, 0));
node.AddSlot(new SerializableSlot("input2", "input", SlotType.Input, 0));
node.AddSlot(new SerializableSlot("input3", "input", SlotType.Input, 0));
node.AddSlot(new SerializableSlot("input4", "input", SlotType.Input, 0));
Assert.AreEqual(4, node.GetSlots<ISlot>().Count());
Assert.AreEqual(4, node.GetInputSlots<ISlot>().Count());
Assert.AreEqual(0, node.GetOutputSlots<ISlot>().Count());
Assert.AreEqual(6, node.GetSlots<ISlot>().Count());
Assert.AreEqual(3, node.GetInputSlots<ISlot>().Count());
Assert.AreEqual(3, node.GetOutputSlots<ISlot>().Count());
node.RemoveSlotsNameNotMatching(new []{"input1", "input3"});
node.RemoveSlotsNameNotMatching(new []{TestableNode.Input1});
Assert.AreEqual(2, node.GetSlots<ISlot>().Count());
Assert.AreEqual(2, node.GetInputSlots<ISlot>().Count());
Assert.AreEqual(1, node.GetSlots<ISlot>().Count());
Assert.AreEqual(1, node.GetInputSlots<ISlot>().Count());
Assert.IsNotNull(node.FindInputSlot<ISlot>("input1"));
Assert.IsNull(node.FindInputSlot<ISlot>("input2"));
Assert.IsNotNull(node.FindInputSlot<ISlot>("input3"));
Assert.IsNull(node.FindInputSlot<ISlot>("input4"));
Assert.IsNull(node.FindInputSlot<ISlot>(TestableNode.Input0));
Assert.IsNotNull(node.FindInputSlot<ISlot>(TestableNode.Input1));
Assert.IsNull(node.FindInputSlot<ISlot>(TestableNode.Input2));
}
[Test]

var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output));
node.name = "Test Node";
graph.AddNode(node);

{
var graph = new SerializableGraph();
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("output", "output_updated", SlotType.Output, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output));
node.AddSlot(new SerializableSlot(0, "output_updated", SlotType.Output));
node.name = "Test Node";
graph.AddNode(node);

{
var graph = new SerializableGraph();
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output, 0));
node.name = "Test Node";
graph.AddNode(node);

{
var graph = new SerializableGraph();
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 1));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output, 5));
node.name = "Test Node";
graph.AddNode(node);

Assert.AreEqual(1, found.GetSlots<ISlot>().Count());
var slot = found.GetOutputSlots<ISlot>().FirstOrDefault();
Assert.AreEqual(1, slot.priority);
Assert.AreEqual(5, slot.priority);
}

var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot(0, "output", SlotType.Output));
node.name = "Test Node";
Assert.AreEqual(0, node.GetInputSlots<ISlot>().Count());

[Test]
public void TestCanFindSlotOnSerializableNode()
{
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("input", "input", SlotType.Input, 0));
var node = new TestableNode();
Assert.AreEqual(2, node.GetSlots<ISlot>().Count());
Assert.IsNotNull(node.FindInputSlot<ISlot>("input"));
Assert.IsNull(node.FindInputSlot<ISlot>("output"));
Assert.IsNotNull(node.FindOutputSlot<ISlot>("output"));
Assert.IsNull(node.FindOutputSlot<ISlot>("input"));
Assert.AreEqual(6, node.GetSlots<ISlot>().Count());
Assert.IsNotNull(node.FindInputSlot<ISlot>(TestableNode.Input0));
Assert.IsNull(node.FindInputSlot<ISlot>(TestableNode.Output0));
Assert.IsNotNull(node.FindOutputSlot<ISlot>(TestableNode.Output0));
Assert.IsNull(node.FindOutputSlot<ISlot>(TestableNode.Input0));
Assert.IsNotNull(node.FindSlot<ISlot>("input"));
Assert.IsNotNull(node.FindSlot<ISlot>("output"));
Assert.IsNull(node.FindSlot<ISlot>("invalid"));
Assert.IsNotNull(node.FindSlot<ISlot>(TestableNode.Input0));
Assert.IsNotNull(node.FindSlot<ISlot>(TestableNode.Output0));
Assert.IsNull(node.FindSlot<ISlot>(555));
var node = new SerializableNode();
node.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
node.AddSlot(new SerializableSlot("input", "input", SlotType.Input, 0));
var node = new TestableNode();
Assert.AreEqual(2, node.GetSlots<ISlot>().Count());
Assert.IsNotNull(node.GetSlotReference("input"));
Assert.IsNotNull(node.GetSlotReference("output"));
Assert.Null(node.GetSlotReference("invalid"));
Assert.AreEqual(6, node.GetSlots<ISlot>().Count());
Assert.IsNotNull(node.GetSlotReference(TestableNode.Input0));
Assert.IsNotNull(node.GetSlotReference(TestableNode.Output0));
Assert.Null(node.GetSlotReference(555));
}
[Test]

var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
var createdEdge = graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
var createdEdge = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.edges.Count());
var edge = graph.edges.FirstOrDefault();

var foundOutputNode = graph.GetNodeFromGuid(edge.outputSlot.nodeGuid);
var foundOutputSlot = foundOutputNode.FindOutputSlot<ISlot>(edge.outputSlot.slotName);
var foundOutputSlot = foundOutputNode.FindOutputSlot<ISlot>(edge.outputSlot.slotId);
Assert.AreEqual(outputSlot, foundOutputSlot);
Assert.IsNotNull(foundOutputSlot);
var foundInputSlot = foundInputNode.FindInputSlot<ISlot>(edge.inputSlot.slotName);
var foundInputSlot = foundInputNode.FindInputSlot<ISlot>(edge.inputSlot.slotId);
Assert.AreEqual(inputSlot, foundInputSlot);
Assert.IsNotNull(foundInputSlot);
}
[Test]

var outputNode = new SerializableNode();
var outputNodeOutputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputNodeOutputSlot);
var outputNode = new TestableNode();
var middleNode = new SerializableNode();
var middleNodeInputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
var middleNodeoutputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
middleNode.AddSlot(middleNodeInputSlot);
middleNode.AddSlot(middleNodeoutputSlot);
var middleNode = new TestableNode();
var inputNode = new SerializableNode();
var inputNodeInputSlot1 = new SerializableSlot("input1", "input1", SlotType.Input, 0);
var inputNodeInputSlot2 = new SerializableSlot("input2", "input2", SlotType.Input, 1);
inputNode.AddSlot(inputNodeInputSlot1);
inputNode.AddSlot(inputNodeInputSlot2);
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), middleNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), middleNode.GetSlotReference(TestableNode.Input0));
graph.Connect(middleNode.GetSlotReference("output"), inputNode.GetSlotReference("input1"));
graph.Connect(middleNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(2, graph.edges.Count());
var edgesOnMiddleNode = NodeUtils.GetAllEdges(middleNode);

Assert.AreEqual(3, result.Count);
result.Clear();
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, inputNodeInputSlot1);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input0);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, inputNodeInputSlot2);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input1);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, inputNodeInputSlot1, false);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input0, false);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, inputNodeInputSlot2, false);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input1, false);
Assert.AreEqual(0, result.Count);
result.Clear();

public void TestConectionToSameInputReplacesOldInput()
{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot1 = new SerializableSlot("output1", "output1", SlotType.Output, 0);
var outputSlot2 = new SerializableSlot("output2", "output2", SlotType.Output, 1);
outputNode.AddSlot(outputSlot1);
outputNode.AddSlot(outputSlot2);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
var createdEdge = graph.Connect(outputNode.GetSlotReference("output1"), inputNode.GetSlotReference("input"));
var createdEdge = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
var createdEdge2 = graph.Connect(outputNode.GetSlotReference("output2"), inputNode.GetSlotReference("input"));
var createdEdge2 = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.edges.Count());
var edge2 = graph.edges.FirstOrDefault();
Assert.AreEqual(createdEdge2, edge2);

public void TestRemovingSlotRemovesConnectedEdges()
{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
inputNode.RemoveSlot("input");
outputNode.RemoveSlot(TestableNode.Output0);
Assert.AreEqual(0, graph.edges.Count());
}

var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
graph.AddNode(outputNode);
var inputNode = new SerializableNode();

var createdEdge = graph.Connect(outputNode.GetSlotReference("output"), null);
var createdEdge = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), null);
var createdEdge2 = graph.Connect(outputNode.GetSlotReference("output"), new SlotReference(Guid.NewGuid(), "nope"));
var createdEdge2 = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), new SlotReference(Guid.NewGuid(), 666));
Assert.AreEqual(0, graph.edges.Count());
Assert.IsNull(createdEdge2);
}

{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var outputNode2 = new SerializableNode();
var outputSlot2 = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode2.AddSlot(outputSlot2);
var outputNode2 = new TestableNode();
var createdEdge = graph.Connect(outputNode.GetSlotReference("output"), outputNode2.GetSlotReference("output"));
var createdEdge = graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), outputNode2.GetSlotReference(TestableNode.Output0));
Assert.IsNull(createdEdge);
Assert.AreEqual(0, graph.edges.Count());
}

{
var graph = new SerializableGraph();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
var inputNode2 = new SerializableNode();
var inputSlot2 = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode2.AddSlot(inputSlot2);
var inputNode2 = new TestableNode();
var createdEdge = graph.Connect(inputNode.GetSlotReference("input"), inputNode2.GetSlotReference("input"));
var createdEdge = graph.Connect(inputNode.GetSlotReference(TestableNode.Input0), inputNode2.GetSlotReference(TestableNode.Input0));
Assert.IsNull(createdEdge);
Assert.AreEqual(0, graph.edges.Count());
}

{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.edges.Count());
graph.RemoveNode(graph.GetNodes<INode>().FirstOrDefault());

public void TestRemovingEdgeOnSerializableGraph()
{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.edges.Count());
graph.RemoveEdge(graph.edges.FirstOrDefault());

public void TestRemovingElementsFromSerializableGraph()
{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.edges.Count());
graph.RemoveElements(graph.GetNodes<INode>(), graph.edges);

public void TestCanGetEdgesOnSerializableGraphFromSlotReference()
{
var graph = new SerializableGraph();
var outputNode = new SerializableNode();
var outputSlot = new SerializableSlot("output", "output", SlotType.Output, 0);
outputNode.AddSlot(outputSlot);
var outputNode = new TestableNode();
var inputNode = new SerializableNode();
var inputSlot = new SerializableSlot("input", "input", SlotType.Input, 0);
inputNode.AddSlot(inputSlot);
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, graph.GetEdges(inputNode.GetSlotReference("input")).Count());
Assert.AreEqual(1, graph.GetEdges(outputNode.GetSlotReference("output")).Count());
Assert.AreEqual(0, graph.GetEdges(outputNode.GetSlotReference("badslot")).Count());
Assert.AreEqual(1, graph.GetEdges(inputNode.GetSlotReference(TestableNode.Input0)).Count());
Assert.AreEqual(1, graph.GetEdges(outputNode.GetSlotReference(TestableNode.Output0)).Count());
Assert.AreEqual(0, graph.GetEdges(outputNode.GetSlotReference(666)).Count());
}
[Test]

var outputNode = new SerializableNode();
outputNode.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
graph.AddNode(outputNode);
var outputNode = new TestableNode();
graph.AddNode(outputNode);
var inputNode = new SerializableNode();
inputNode.AddSlot(new SerializableSlot("input", "input", SlotType.Input, 0));
inputNode.AddSlot(new SerializableSlot("input2", "input2", SlotType.Input, 1));
inputNode.AddSlot(new SerializableSlot("output", "output", SlotType.Output, 0));
var inputNode = new TestableNode();
graph.Connect(outputNode.GetSlotReference("output"), inputNode.GetSlotReference("input"));
graph.Connect(outputNode.GetSlotReference(TestableNode.Output0), inputNode.GetSlotReference(TestableNode.Input0));
Assert.AreEqual(1, slots.Count());
Assert.AreEqual("input2", slots.FirstOrDefault().name);
Assert.AreEqual(2, slots.Count());
CollectionAssert.AreEqual(new [] { TestableNode.Input1, TestableNode.Input2 }, slots.Select(x => x.id));
}
[Test]

var nodeA = new SerializableNode();
var inputSlotA = new SerializableSlot("input", "input", SlotType.Input, 0);
var outputSlotA = new SerializableSlot("output", "output", SlotType.Output, 0);
nodeA.AddSlot(inputSlotA);
nodeA.AddSlot(outputSlotA);
var nodeA = new TestableNode();
var nodeB = new SerializableNode();
var inputSlotB = new SerializableSlot("input", "input", SlotType.Input, 0);
var outputSlotB = new SerializableSlot("output", "output", SlotType.Output, 0);
nodeB.AddSlot(inputSlotB);
nodeB.AddSlot(outputSlotB);
var nodeB = new TestableNode();
graph.Connect(nodeA.GetSlotReference("output"), nodeB.GetSlotReference("input"));
graph.Connect(nodeA.GetSlotReference(TestableNode.Output0), nodeB.GetSlotReference(TestableNode.Input0));
var edge = graph.Connect(nodeB.GetSlotReference("output"), nodeA.GetSlotReference("input"));
var edge = graph.Connect(nodeB.GetSlotReference(TestableNode.Output0), nodeA.GetSlotReference(TestableNode.Input0));
Assert.IsNull(edge);
Assert.AreEqual(1, graph.edges.Count());
}

26
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/NodeUtils.cs


for (int index = 0; index < validSlots.Count; index++)
{
var inputSlot = validSlots[index];
result.AddRange(node.owner.GetEdges(node.GetSlotReference(inputSlot.name)));
result.AddRange(node.owner.GetEdges(inputSlot.slotReference));
}
validSlots.Clear();

var outputSlot = validSlots[index];
result.AddRange(node.owner.GetEdges(node.GetSlotReference(outputSlot.name)));
result.AddRange(node.owner.GetEdges(outputSlot.slotReference));
}
ListPool<ISlot>.Release(validSlots);

// which child nodes it depends on for it's calculation.
// Results are returned depth first so by processing each node in
// order you can generate a valid code block.
public static void DepthFirstCollectNodesFromNode(List<INode> nodeList, INode node, ISlot slotToUse = null, bool includeSelf = true)
public static void DepthFirstCollectNodesFromNode(List<INode> nodeList, INode node, int? slotId = null, bool includeSelf = true)
{
// no where to start
if (node == null)

return;
// if we have a slot passed in but can not find it on the node abort
if (slotToUse != null && node.GetInputSlots<ISlot>().All(x => x.name != slotToUse.name))
if (slotId.HasValue && node.GetInputSlots<ISlot>().All(x => x.id != slotId.Value))
var validSlots = ListPool<ISlot>.Get();
if (slotToUse != null)
validSlots.Add(slotToUse);
var validSlots = ListPool<int>.Get();
if (slotId.HasValue)
validSlots.Add(slotId.Value);
validSlots.AddRange(node.GetInputSlots<ISlot>());
validSlots.AddRange(node.GetInputSlots<ISlot>().Select(x => x.id));
for (int index = 0; index < validSlots.Count; index++)
foreach (var slot in validSlots)
var slot = validSlots[index];
foreach (var edge in node.owner.GetEdges(node.GetSlotReference(slot.name)))
foreach (var edge in node.owner.GetEdges(node.GetSlotReference(slot)))
{
var outputNode = node.owner.GetNodeFromGuid(edge.outputSlot.nodeGuid);
DepthFirstCollectNodesFromNode(nodeList, outputNode);

if (includeSelf)
nodeList.Add(node);
ListPool<ISlot>.Release(validSlots);
ListPool<int>.Release(validSlots);
}
public static void CollectNodesNodeFeedsInto(List<INode> nodeList, INode node, bool includeSelf = true)

foreach (var slot in node.GetOutputSlots<ISlot>())
{
foreach (var edge in node.owner.GetEdges(node.GetSlotReference(slot.name)))
foreach (var edge in node.owner.GetEdges(slot.slotReference))
{
var inputNode = node.owner.GetNodeFromGuid(edge.inputSlot.nodeGuid);
CollectNodesNodeFeedsInto(nodeList, inputNode);

12
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableGraph.cs


if (dependentNodes.Contains(fromNode))
return null;
var fromSlot = fromNode.FindSlot<ISlot>(fromSlotRef.slotName);
var toSlot = toNode.FindSlot<ISlot>(toSlotRef.slotName);
var fromSlot = fromNode.FindSlot<ISlot>(fromSlotRef.slotId);
var toSlot = toNode.FindSlot<ISlot>(toSlotRef.slotId);
SlotReference outputSlot = null;
SlotReference inputSlot = null;

return new Edge[0];
return m_Edges.Where(x =>
(x.outputSlot.nodeGuid == s.nodeGuid && x.outputSlot.slotName == s.slotName)
|| x.inputSlot.nodeGuid == s.nodeGuid && x.inputSlot.slotName == s.slotName);
(x.outputSlot.nodeGuid == s.nodeGuid && x.outputSlot.slotId == s.slotId)
|| x.inputSlot.nodeGuid == s.nodeGuid && x.inputSlot.slotId == s.slotId);
}
public virtual void OnBeforeSerialize()

if (outputNode == null
|| inputNode == null
|| outputNode.FindOutputSlot<ISlot>(edge.outputSlot.slotName) == null
|| inputNode.FindInputSlot<ISlot>(edge.inputSlot.slotName) == null)
|| outputNode.FindOutputSlot<ISlot>(edge.outputSlot.slotId) == null
|| inputNode.FindInputSlot<ISlot>(edge.inputSlot.slotId) == null)
{
//orphaned edge
RemoveEdgeNoValidate(edge);

37
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableNode.cs


if (slot == null)
return;
m_Slots.RemoveAll(x => x.name == slot.name);
m_Slots.RemoveAll(x => x.id == slot.id);
slot.owner = this;
public void RemoveSlot(string name)
public void RemoveSlot(int slotId)
var edges = owner.GetEdges(GetSlotReference(name));
var edges = owner.GetEdges(GetSlotReference(slotId));
m_Slots.RemoveAll(x => x.name == name);
m_Slots.RemoveAll(x => x.id == slotId);
public void RemoveSlotsNameNotMatching(IEnumerable<string> slotNames)
public void RemoveSlotsNameNotMatching(IEnumerable<int> slotIds)
var invalidSlots = m_Slots.Select(x => x.name).Except(slotNames);
var invalidSlots = m_Slots.Select(x => x.id).Except(slotIds);
foreach (var invalidSlot in invalidSlots.ToArray())
{

}
public SlotReference GetSlotReference(string name)
public SlotReference GetSlotReference(int slotId)
var slot = FindSlot<ISlot>(name);
var slot = FindSlot<ISlot>(slotId);
return new SlotReference(guid, name);
return new SlotReference(guid, slotId);
public T FindSlot<T>(string name) where T: ISlot
public T FindSlot<T>(int slotId) where T: ISlot
var slot = GetSlots<T>().FirstOrDefault(x => x.name == name);
var slot = GetSlots<T>().FirstOrDefault(x => x.id == slotId);
public T FindInputSlot<T>(string name) where T : ISlot
public T FindInputSlot<T>(int slotId) where T : ISlot
var slot = GetInputSlots<T>().FirstOrDefault(x => x.name == name);
var slot = GetInputSlots<T>().FirstOrDefault(x => x.id == slotId);
public T FindOutputSlot<T>(string name) where T : ISlot
public T FindOutputSlot<T>(int slotId) where T : ISlot
var slot = GetOutputSlots<T>().FirstOrDefault(x => x.name == name);
var slot = GetOutputSlots<T>().FirstOrDefault(x => x.id == slotId);
if (slot == null)
Debug.LogErrorFormat("Output Slot: {0} could be found on node {1}", name, this);
return slot;

m_Guid = Guid.NewGuid();
m_Slots = SerializationHelper.Deserialize<ISlot>(m_SerializableSlots);
m_SerializableSlots = null;
m_SerializableSlots = null;
foreach (var s in m_Slots)
s.owner = this;
return GetInputSlots<ISlot>().Where(x => !owner.GetEdges(GetSlotReference(x.name)).Any());
return GetInputSlots<ISlot>().Where(x => !owner.GetEdges(GetSlotReference(x.id)).Any());
}
public virtual void UpdateNodeAfterDeserialization()

40
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableSlot.cs


private const string kNotInit = "Not Initilaized";
[SerializeField]
private string m_Name = kNotInit;
private int m_Id;
[SerializeField]
private string m_DisplayName = kNotInit;

[SerializeField]
private int m_Priority;
public string name
private int m_Priority = int.MaxValue;
public SlotReference slotReference
get { return m_Name; }
get { return new SlotReference(owner.guid, m_Id); }
}
public INode owner { get; set; }
public int id
{
get { return m_Id;}
}
public virtual string displayName

}
public int priority
{
get { return m_Priority; }
set { m_Priority = value; }
}
public bool isInputSlot
{
get { return m_SlotType == SlotType.Input; }

{
get { return m_SlotType == SlotType.Output; }
}
public int priority
{
get { return m_Priority; }
set { m_Priority = value; }
}
// used via reflection / serialization after deserialize
// to reconstruct this slot.

public SerializableSlot(string name, string displayName, SlotType slotType, int priority)
public SerializableSlot(int id, string displayName, SlotType slotType, int priority)
m_Name = name;
m_Id = id;
}
public SerializableSlot(int id, string displayName, SlotType slotType)
{
m_Id = id;
m_DisplayName = displayName;
m_SlotType = slotType;
}
}
}

10
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/INode.cs


IEnumerable<T> GetOutputSlots<T>() where T : ISlot;
IEnumerable<T> GetSlots<T>() where T : ISlot;
void AddSlot(ISlot slot);
void RemoveSlot(string name);
SlotReference GetSlotReference(string name);
T FindSlot<T>(string name) where T : ISlot;
T FindInputSlot<T>(string name) where T : ISlot;
T FindOutputSlot<T>(string name) where T : ISlot;
void RemoveSlot(int slotId);
SlotReference GetSlotReference(int slotId);
T FindSlot<T>(int slotId) where T : ISlot;
T FindInputSlot<T>(int slotId) where T : ISlot;
T FindOutputSlot<T>(int slotId) where T : ISlot;
IEnumerable<ISlot> GetInputsWithNoConnection();
DrawingData drawState { get; set; }
bool hasError { get; }

4
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/ISlot.cs


{
public interface ISlot
{
string name { get; }
int id { get; }
SlotReference slotReference { get; }
INode owner { get; set; }
}
}

10
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/SlotReference.cs


public class SlotReference : ISerializationCallbackReceiver
{
[SerializeField]
private string m_SlotName;
private int m_SlotId;
[NonSerialized]
private Guid m_NodeGUID;

public SlotReference(Guid nodeGuid, string slotName)
public SlotReference(Guid nodeGuid, int slotId)
m_SlotName = slotName;
m_SlotId = slotId;
m_NodeGUIDSerialized = string.Empty;
}

}
public string slotName
public int slotId
get { return m_SlotName; }
get { return m_SlotId; }
}
public void OnBeforeSerialize()

135
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/DynamicSlotTests.cs


class DynamicNode : AbstractMaterialNode
{
public const int DynIn1 = 0;
public const int DynIn2 = 1;
public const int DynOut = 2;
AddSlot(new MaterialSlot("DynIn1", "DynIn1", SlotType.Input, 0, SlotValueType.Dynamic, Vector4.zero));
AddSlot(new MaterialSlot("DynIn2", "DynIn2", SlotType.Input, 1, SlotValueType.Dynamic, Vector4.zero));
AddSlot(new MaterialSlot("DynOut", "DynOut", SlotType.Output, 0, SlotValueType.Dynamic, Vector4.zero));
AddSlot(new MaterialSlot(DynIn1, "DynIn1", "DynIn1", SlotType.Input, SlotValueType.Dynamic, Vector4.zero));
AddSlot(new MaterialSlot(DynIn2, "DynIn2", "DynIn2", SlotType.Input, SlotValueType.Dynamic, Vector4.zero));
AddSlot(new MaterialSlot(DynOut, "DynOut", "DynOut", SlotType.Output, SlotValueType.Dynamic, Vector4.zero));
public const int V1Out = 0;
public const int V2Out = 1;
public const int V3Out = 2;
public const int V4Out = 3;
AddSlot(new MaterialSlot("V1Out", "V1Out", SlotType.Output, 0, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot("V2Out", "V2Out", SlotType.Output, 1, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot("V3Out", "V3Out", SlotType.Output, 2, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot("V4Out", "V4Out", SlotType.Output, 3, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(V1Out, "V1Out", "V1Out", SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(V2Out, "V2Out", "V2Out", SlotType.Output, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(V3Out, "V3Out", "V3Out", SlotType.Output, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot(V4Out, "V4Out", "V4Out", SlotType.Output, SlotValueType.Vector4, Vector4.zero));
}
}

[Test]
public void DynamicInputsV1NoneWorks()
{
m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn1"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector1, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector1, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector3, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector4, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn1"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn1"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector3, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector3, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector3, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector3, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn1"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector4, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V1Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V1Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector4, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V2Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V2Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector2, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V3Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V3Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector3, dynOut1.concreteValueType);
}

m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn1"));
m_Graph.Connect(m_StaticNode.GetSlotReference("V4Out"), m_DynamicNode.GetSlotReference("DynIn2"));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>("DynOut");
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn1));
m_Graph.Connect(m_StaticNode.GetSlotReference(TestNode.V4Out), m_DynamicNode.GetSlotReference(DynamicNode.DynIn2));
var dynOut1 = m_DynamicNode.FindOutputSlot<MaterialSlot>(DynamicNode.DynOut);
Assert.AreEqual(ConcreteSlotValueType.Vector4, dynOut1.concreteValueType);
}
}

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/Function1InputTests.cs


m_InputOne.value = 0.2f;
m_Graph.Connect(m_InputOne.GetSlotReference("Value"), m_TestNode.GetSlotReference("Input"));
m_Graph.Connect(m_TestNode.GetSlotReference("Output"), m_Graph.pixelMasterNode.GetSlotReference("Emission"));
m_Graph.Connect(m_InputOne.GetSlotReference(Vector1Node.OutputSlotId), m_TestNode.GetSlotReference(Function1Input.InputSlotId));
m_Graph.Connect(m_TestNode.GetSlotReference(Function1Input.OutputSlotId), m_Graph.pixelMasterNode.GetSlotReference(BaseLightFunction.NormalSlotId));
}
[Test]

8
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/Function2InputTests.cs


m_InputOne.value = 0.2f;
m_InputTwo.value = 0.3f;
m_Graph.Connect(m_InputOne.GetSlotReference("Value"), m_TestNode.GetSlotReference("Input1"));
m_Graph.Connect(m_InputTwo.GetSlotReference("Value"), m_TestNode.GetSlotReference("Input2"));
m_Graph.Connect(m_TestNode.GetSlotReference("Output"), m_Graph.pixelMasterNode.GetSlotReference("Emission"));
m_Graph.Connect(m_InputOne.GetSlotReference(Vector1Node.OutputSlotId), m_TestNode.GetSlotReference(Function2Input.InputSlot1Id));
m_Graph.Connect(m_InputTwo.GetSlotReference(Vector1Node.OutputSlotId), m_TestNode.GetSlotReference(Function2Input.InputSlot2Id));
m_Graph.Connect(m_TestNode.GetSlotReference(Function2Input.OutputSlotId), m_Graph.pixelMasterNode.GetSlotReference(BaseLightFunction.NormalSlotId));
}
[Test]

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/Function3InputTests.cs


m_InputOne.value = 0.2f;
m_InputTwo.value = 0.3f;
m_InputThree.value = 0.6f;
m_Graph.Connect(m_InputOne.GetSlotReference("Value"), m_TestNode.GetSlotReference("Input1"));
m_Graph.Connect(m_InputTwo.GetSlotReference("Value"), m_TestNode.GetSlotReference("Input2"));
m_Graph.Connect(m_InputThree.GetSlotReference("Value"), m_TestNode.GetSlotReference("Input3"));
m_Graph.Connect(m_TestNode.GetSlotReference("Output"), m_Graph.pixelMasterNode.GetSlotReference("Emission"));
m_Graph.Connect(m_InputOne.GetSlotReference(Vector1Node.OutputSlotId), m_TestNode.GetSlotReference(Function3Input.InputSlot1Id));
m_Graph.Connect(m_InputTwo.GetSlotReference(Vector1Node.OutputSlotId), m_TestNode.GetSlotReference(Function3Input.InputSlot2Id));
m_Graph.Connect(m_InputThree.GetSlotReference(Vector1Node.OutputSlotId), m_TestNode.GetSlotReference(Function3Input.InputSlot3Id));
m_Graph.Connect(m_TestNode.GetSlotReference(Function3Input.OutputSlotId), m_Graph.pixelMasterNode.GetSlotReference(BaseLightFunction.NormalSlotId));
[Test]
public void TestGenerateNodeCodeGeneratesCorrectCode()
{

61
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/MaterialNodeTests.cs


class TestNode : AbstractMaterialNode
{
public const int V1Out = 0;
public const int V2Out = 1;
public const int V3Out = 2;
public const int V4Out = 3;
public const int V1In = 4;
public const int V2In = 5;
public const int V3In = 6;
public const int V4In = 7;
AddSlot(new MaterialSlot("V1Out", "V1Out", SlotType.Output, 0, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot("V2Out", "V2Out", SlotType.Output, 1, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot("V3Out", "V3Out", SlotType.Output, 2, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot("V4Out", "V4Out", SlotType.Output, 3, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot("V1In", "V1In", SlotType.Input, 0, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot("V2In", "V2In", SlotType.Input, 1, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot("V3In", "V3In", SlotType.Input, 2, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot("V4In", "V4In", SlotType.Input, 3, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(V1Out, "V1Out", "V1Out", SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(V2Out, "V2Out", "V2Out", SlotType.Output, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(V3Out, "V3Out", "V3Out", SlotType.Output, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot(V4Out, "V4Out", "V4Out", SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(V1In, "V1In", "V1In", SlotType.Input, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(V2In, "V2In", "V2In", SlotType.Input, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(V3In, "V3In", "V3In", SlotType.Input, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot(V4In, "V4In", "V4In", SlotType.Input, SlotValueType.Vector4, Vector4.zero));
}
}

[Test]
public void ConnectV1ToV1Works()
{
m_Graph.Connect(m_NodeA.GetSlotReference("V1Out"), m_NodeB.GetSlotReference("V1In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V1Out), m_NodeB.GetSlotReference(TestNode.V1In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V1Out"), m_NodeB.GetSlotReference("V2In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V1Out), m_NodeB.GetSlotReference(TestNode.V2In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V1Out"), m_NodeB.GetSlotReference("V3In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V1Out), m_NodeB.GetSlotReference(TestNode.V3In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V1Out"), m_NodeB.GetSlotReference("V4In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V1Out), m_NodeB.GetSlotReference(TestNode.V4In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V2Out"), m_NodeB.GetSlotReference("V1In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V2Out), m_NodeB.GetSlotReference(TestNode.V1In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V2Out"), m_NodeB.GetSlotReference("V2In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V2Out), m_NodeB.GetSlotReference(TestNode.V2In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V2Out"), m_NodeB.GetSlotReference("V3In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V2Out), m_NodeB.GetSlotReference(TestNode.V3In));
Assert.IsTrue(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V2Out"), m_NodeB.GetSlotReference("V4In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V2Out), m_NodeB.GetSlotReference(TestNode.V4In));
Assert.IsTrue(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V3Out"), m_NodeB.GetSlotReference("V1In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V3Out), m_NodeB.GetSlotReference(TestNode.V1In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V3Out"), m_NodeB.GetSlotReference("V2In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V3Out), m_NodeB.GetSlotReference(TestNode.V2In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V3Out"), m_NodeB.GetSlotReference("V3In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V3Out), m_NodeB.GetSlotReference(TestNode.V3In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V3Out"), m_NodeB.GetSlotReference("V4In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V3Out), m_NodeB.GetSlotReference(TestNode.V4In));
Assert.IsTrue(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V4Out"), m_NodeB.GetSlotReference("V1In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V4Out), m_NodeB.GetSlotReference(TestNode.V1In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V4Out"), m_NodeB.GetSlotReference("V2In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V4Out), m_NodeB.GetSlotReference(TestNode.V2In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V4Out"), m_NodeB.GetSlotReference("V3In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V4Out), m_NodeB.GetSlotReference(TestNode.V3In));
Assert.IsFalse(m_NodeB.hasError);
}

m_Graph.Connect(m_NodeA.GetSlotReference("V4Out"), m_NodeB.GetSlotReference("V4In"));
m_Graph.Connect(m_NodeA.GetSlotReference(TestNode.V4Out), m_NodeB.GetSlotReference(TestNode.V4In));
Assert.IsFalse(m_NodeB.hasError);
}
}

45
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/ShaderGeneratorTests.cs


class TestNode : AbstractMaterialNode
{
public const int V1Out = 0;
public const int V2Out = 1;
public const int V3Out = 2;
public const int V4Out = 3;
AddSlot(new MaterialSlot("V1Out", "V1Out", SlotType.Output, 0, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot("V2Out", "V2Out", SlotType.Output, 1, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot("V3Out", "V3Out", SlotType.Output, 2, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot("V4Out", "V4Out", SlotType.Output, 3, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(V1Out, "V1Out", "V1Out", SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(V2Out, "V2Out", "V2Out", SlotType.Output, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(V3Out, "V3Out", "V3Out", SlotType.Output, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot(V4Out, "V4Out", "V4Out", SlotType.Output, SlotValueType.Vector4, Vector4.zero));
}
}

var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V1Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V1Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector1);
Assert.AreEqual(string.Format("{0}", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V1Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V1Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector2);
Assert.AreEqual(string.Format("({0})", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V1Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V1Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector3);
Assert.AreEqual(string.Format("({0})", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V1Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V1Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector4);
Assert.AreEqual(string.Format("({0})", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V2Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V2Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector1);
Assert.AreEqual(string.Format("({0}).x", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V2Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V2Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector2);
Assert.AreEqual(string.Format("{0}", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V2Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V2Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector3);
Assert.AreEqual("ERROR!", result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V2Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V2Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector4);
Assert.AreEqual("ERROR!", result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V3Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V3Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector1);
Assert.AreEqual(string.Format("({0}).x", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V3Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V3Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector2);
Assert.AreEqual(string.Format("({0}.xy)", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V3Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V3Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector3);
Assert.AreEqual(string.Format("{0}", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V3Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V3Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector4);
Assert.AreEqual("ERROR!", result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V4Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V4Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector1);
Assert.AreEqual(string.Format("({0}).x", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V4Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V4Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector2);
Assert.AreEqual(string.Format("({0}.xy)", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V4Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V4Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector3);
Assert.AreEqual(string.Format("({0}.xyz)", node.GetVariableNameForSlot(slot)), result);
}

{
var node = new TestNode();
var slot = node.FindOutputSlot<MaterialSlot>("V4Out");
var slot = node.FindOutputSlot<MaterialSlot>(TestNode.V4Out);
var result = ShaderGenerator.AdaptNodeOutput(node, slot, ConcreteSlotValueType.Vector4);
Assert.AreEqual(string.Format("{0}", node.GetVariableNameForSlot(slot)), result);
}

81
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Light/BaseLightFunction.cs


public abstract class BaseLightFunction
{
public const string kNormalSlotName = "Normal";
public const int NormalSlotId = 1;
public virtual string GetLightFunctionName() { return ""; }
public virtual string GetSurfaceOutputStructureName() { return ""; }

public abstract void DoSlotsForConfiguration(PixelShaderNode node);
public virtual string GetFirstPassSlotName()
public virtual int GetFirstPassSlotId()
return kNormalSlotName;
return NormalSlotId;
}
}

public const string kMetallicSlotName = "Metallic";
public const string kMetallicSlotName = "Metallic";
public const string kOcclusion = "Occlusion";
public const string kOcclusionSlotName = "Occlusion";
public const int kAlbedoSlotId = 0;
public const int kMetallicSlotId = 2;
public const int kEmissionSlotId = 3;
public const int kSmoothnessSlotId = 4;
public const int kOcclusionSlotId = 5;
public const int kAlphaSlotId = 6;
node.AddSlot(new MaterialSlot(kAlbedoSlotName, kAlbedoSlotName, SlotType.Input, 0, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kNormalSlotName, kNormalSlotName, SlotType.Input, 1, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kEmissionSlotName, kEmissionSlotName, SlotType.Input, 2, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kMetallicSlotName, kMetallicSlotName, SlotType.Input, 4, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kSmoothnessSlotName, kSmoothnessSlotName, SlotType.Input, 4, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kOcclusion, kOcclusion, SlotType.Input, 5, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kAlphaSlotName, kAlphaSlotName, SlotType.Input, 6, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kAlbedoSlotId, kAlbedoSlotName, kAlbedoSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(NormalSlotId, kNormalSlotName, kNormalSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kEmissionSlotId, kEmissionSlotName, kEmissionSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kMetallicSlotId, kMetallicSlotName, kMetallicSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kSmoothnessSlotId, kSmoothnessSlotName, kSmoothnessSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kOcclusionSlotId, kOcclusionSlotName, kOcclusionSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kAlphaSlotId, kAlphaSlotName, kAlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
// clear out slot names that do not match the slots
// we support

kAlbedoSlotName,
kNormalSlotName,
kEmissionSlotName,
kMetallicSlotName,
kSmoothnessSlotName,
kOcclusion,
kAlphaSlotName
kAlbedoSlotId,
NormalSlotId,
kEmissionSlotId,
kMetallicSlotId,
kSmoothnessSlotId,
kOcclusionSlotId,
kAlphaSlotId
});
}
}

public const string kSpecularSlotName = "Specular";
public const string kEmissionSlotName = "Emission";
public const string kSmoothnessSlotName = "Smoothness";
public const string kOcclusion = "Occlusion";
public const string kOcclusionSlotName = "Occlusion";
public const int kAlbedoSlotId = 0;
public const int kSpecularSlotId = 2;
public const int kEmissionSlotId = 3;
public const int kSmoothnessSlotId = 4;
public const int kOcclusionSlotId = 5;
public const int kAlphaSlotId = 6;
node.AddSlot(new MaterialSlot(kAlbedoSlotName, kAlbedoSlotName, SlotType.Input, 0, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kNormalSlotName, kNormalSlotName, SlotType.Input, 1, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kSpecularSlotName, kSpecularSlotName, SlotType.Input, 2, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kEmissionSlotName, kEmissionSlotName, SlotType.Input, 3, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kSmoothnessSlotName, kSmoothnessSlotName, SlotType.Input, 4, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kOcclusion, kOcclusion, SlotType.Input, 5, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kAlphaSlotName, kAlphaSlotName, SlotType.Input, 6, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kAlbedoSlotId, kAlbedoSlotName, kAlbedoSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(NormalSlotId, kNormalSlotName, kNormalSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kSpecularSlotId, kSpecularSlotName, kSpecularSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kEmissionSlotId, kEmissionSlotName, kEmissionSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(kSmoothnessSlotId, kSmoothnessSlotName, kSmoothnessSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kOcclusionSlotId, kOcclusionSlotName, kOcclusionSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(kAlphaSlotId, kAlphaSlotName, kAlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
// clear out slot names that do not match the slots
// we support

kAlbedoSlotName,
kNormalSlotName,
kSpecularSlotName,
kEmissionSlotName,
kSmoothnessSlotName,
kOcclusion,
kAlphaSlotName
kAlbedoSlotId,
NormalSlotId,
kSpecularSlotId,
kEmissionSlotId,
kSmoothnessSlotId,
kOcclusionSlotId,
kAlphaSlotId
});
}
}

33
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/AbstractMaterialNode.cs


foreach (var inputSlot in GetInputSlots<MaterialSlot>())
{
var edges = owner.GetEdges(GetSlotReference(inputSlot.name));
var edges = owner.GetEdges(inputSlot.slotReference);
if (edges.Any())
continue;

public string GetSlotValue(MaterialSlot inputSlot, GenerationMode generationMode)
{
var edges = owner.GetEdges(GetSlotReference(inputSlot.name)).ToArray();
var edges = owner.GetEdges(inputSlot.slotReference).ToArray();
if (edges.Any())
{

return string.Empty;
var slot = fromNode.FindOutputSlot<MaterialSlot>(fromSocketRef.slotName);
var slot = fromNode.FindOutputSlot<MaterialSlot>(fromSocketRef.slotId);
if (slot == null)
return string.Empty;

// so do that here
foreach (var inputSlot in GetInputSlots<MaterialSlot>())
{
var edges = owner.GetEdges(GetSlotReference(inputSlot.name));
var edges = owner.GetEdges(inputSlot.slotReference);
foreach (var edge in edges)
{
var fromSocketRef = edge.outputSlot;

{
var inputType = inputSlot.valueType;
// if there is a connection
var edges = owner.GetEdges(GetSlotReference(inputSlot.name)).ToList();
var edges = owner.GetEdges(inputSlot.slotReference).ToList();
if (!edges.Any())
{
if (inputType != SlotValueType.Dynamic)

if (outputNode == null)
continue;
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(outputSlotRef.slotName);
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(outputSlotRef.slotId);
if (outputSlot == null)
continue;

for (var index = 0; index < validSlots.Length; index++)
{
var s = validSlots[index];
var edges = owner.GetEdges(GetSlotReference(s.name));
var edges = owner.GetEdges(s.slotReference);
if (edges.Any())
continue;

if (!GetSlots<MaterialSlot>().Contains(s))
Debug.LogError("Attempting to use MaterialSlot (" + s + ") on a node that does not have this MaterialSlot!");
return GetVariableNameForNode() + "_" + s.name;
return GetVariableNameForNode() + "_" + s.id;
}
public virtual string GetVariableNameForNode()

Debug.LogWarningFormat("Trying to add slot {0} to Material node {1}, but it is not a {2}", slot, this, typeof(MaterialSlot));
return;
}
var addingSlot = (MaterialSlot) slot;
var foundSlot = FindSlot<MaterialSlot>(slot.id);
// this will remove the old slot and add a new one
// if an old one was found. This allows updating values
var addingSlot = (MaterialSlot) slot;
var foundSlot = FindSlot<MaterialSlot>(slot.name);
// if the default and current are the same, change the current
// to the new default.
if (addingSlot.defaultValue == foundSlot.currentValue)
foundSlot.currentValue = addingSlot.defaultValue;
foundSlot.defaultValue = addingSlot.defaultValue;
foundSlot.valueType = addingSlot.valueType;
// preserve the old current value.
addingSlot.currentValue = foundSlot.currentValue;
}
}
}

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ColorNode.cs


[SerializeField]
private Color m_Color;
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "Color";
public ColorNode()

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] {kOutputSlotName});
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override PropertyType propertyType

6
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/DotNode.cs


protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(GetInputSlot1Name(), GetInputSlot1Name(), SlotType.Input, 0, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(GetInputSlot2Name(), GetInputSlot2Name(), SlotType.Input, 1, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 2, SlotValueType.Vector1, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector1, Vector4.zero);
}
}
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/FresnelNode.cs


protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(GetInputSlot1Name(), GetInputSlot1Name(), SlotType.Input, 0, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(GetInputSlot2Name(), GetInputSlot2Name(), SlotType.Input, 1, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 0, SlotValueType.Vector1, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector1, Vector4.zero);
}
protected override string GetFunctionName() { return "unity_fresnel_" + precision; }

22
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function1Input.cs


{
public abstract class Function1Input : AbstractMaterialNode, IGeneratesBodyCode
{
protected const string kInputSlotShaderName = "Input";
protected const string kOutputSlotShaderName = "Output";
public const int InputSlotId = 0;
public const int OutputSlotId = 1;
public override bool hasPreview
{
get { return true; }

RemoveSlotsNameNotMatching(validSlots);
}
protected string[] validSlots
protected int[] validSlots
get { return new[] {GetInputSlotName(), GetOutputSlotName()}; }
get { return new[] { InputSlotId, OutputSlotId }; }
return new MaterialSlot(GetInputSlotName(), GetInputSlotName(), SlotType.Input, 0, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(InputSlotId, GetInputSlotName(), kInputSlotShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 0, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Dynamic, Vector4.zero);
}
protected virtual string GetInputSlotName() {return "Input"; }

public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot<MaterialSlot>(GetOutputSlotName());
var inputSlot = FindInputSlot<MaterialSlot>(GetInputSlotName());
var outputSlot = FindOutputSlot<MaterialSlot>(OutputSlotId);
var inputSlot = FindInputSlot<MaterialSlot>(InputSlotId);
if (inputSlot == null || outputSlot == null)
{

public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(GetOutputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(GetInputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType); }
}
}
}

30
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function2Input.cs


{
public abstract class Function2Input : AbstractMaterialNode, IGeneratesBodyCode
{
protected const string kInputSlot1ShaderName = "Input1";
protected const string kInputSlot2ShaderName = "Input2";
protected const string kOutputSlotShaderName = "Output";
public const int InputSlot1Id = 0;
public const int InputSlot2Id = 1;
public const int OutputSlotId = 2;
public override bool hasPreview
{
get { return true; }

RemoveSlotsNameNotMatching(validSlots);
}
protected string[] validSlots
protected int[] validSlots
get { return new[] {GetInputSlot1Name(), GetInputSlot2Name(), GetOutputSlotName()}; }
get { return new[] {InputSlot1Id, InputSlot2Id, OutputSlotId}; }
return new MaterialSlot(GetInputSlot1Name(), GetInputSlot1Name(), SlotType.Input, 0, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(GetInputSlot2Name(), GetInputSlot2Name(), SlotType.Input, 1, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 0, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Dynamic, Vector4.zero);
}
protected virtual string GetInputSlot1Name()

public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot<MaterialSlot>(GetOutputSlotName());
var inputSlot1 = FindInputSlot<MaterialSlot>(GetInputSlot1Name());
var inputSlot2 = FindInputSlot<MaterialSlot>(GetInputSlot2Name());
var outputSlot = FindOutputSlot<MaterialSlot>(OutputSlotId);
var inputSlot1 = FindInputSlot<MaterialSlot>(InputSlot1Id);
var inputSlot2 = FindInputSlot<MaterialSlot>(InputSlot2Id);
if (inputSlot1 == null || inputSlot2 == null || outputSlot == null)
{

public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(GetOutputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(GetInputSlot1Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlot1Id).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(GetInputSlot2Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType); }
}
}
}

53
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function3Input.cs


{
public abstract class Function3Input : AbstractMaterialNode, IGeneratesBodyCode
{
private const string kInputSlot1ShaderName = "Input1";
private const string kInputSlot2ShaderName = "Input2";
private const string kInputSlot3ShaderName = "Input3";
private const string kOutputSlotShaderName = "Output";
public const int InputSlot1Id = 0;
public const int InputSlot2Id = 1;
public const int InputSlot3Id = 2;
public const int OutputSlotId = 3;
public override bool hasPreview
{
get { return true; }

RemoveSlotsNameNotMatching(validSlots);
}
protected string[] validSlots
protected int[] validSlots
get { return new[] {GetInputSlot1Name(), GetInputSlot2Name(), GetInputSlot3Name(), GetOutputSlotName()}; }
get { return new[] {InputSlot1Id, InputSlot2Id, InputSlot3Id, OutputSlotId}; }
protected MaterialSlot GetInputSlot1()
protected virtual MaterialSlot GetInputSlot1()
return new MaterialSlot(GetInputSlot1Name(), GetInputSlot1Name(), SlotType.Input, 0, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
protected MaterialSlot GetInputSlot2()
protected virtual MaterialSlot GetInputSlot2()
return new MaterialSlot(GetInputSlot2Name(), GetInputSlot2Name(), SlotType.Input, 1, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
protected MaterialSlot GetInputSlot3()
protected virtual MaterialSlot GetInputSlot3()
return new MaterialSlot(GetInputSlot3Name(), GetInputSlot3Name(), SlotType.Input, 2, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(InputSlot3Id, GetInputSlot3Name(), kInputSlot3ShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
protected MaterialSlot GetOutputSlot()
protected virtual MaterialSlot GetOutputSlot()
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 0, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Dynamic, Vector4.zero);
protected virtual string GetInputSlot1Name()
{
return "Input1";

public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot<MaterialSlot>(GetOutputSlotName());
var inputSlot1 = FindInputSlot<MaterialSlot>(GetInputSlot1Name());
var inputSlot2 = FindInputSlot<MaterialSlot>(GetInputSlot2Name());
var inputSlot3 = FindInputSlot<MaterialSlot>(GetInputSlot3Name());
var outputSlot = FindOutputSlot<MaterialSlot>(OutputSlotId);
var inputSlot1 = FindInputSlot<MaterialSlot>(InputSlot1Id);
var inputSlot2 = FindInputSlot<MaterialSlot>(InputSlot2Id);
var inputSlot3 = FindInputSlot<MaterialSlot>(InputSlot3Id);
if (inputSlot1 == null || inputSlot2 == null || inputSlot3 == null || outputSlot == null)
{

public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(GetOutputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType); }
public string input1Dimension
private string input1Dimension
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(GetInputSlot1Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlot1Id).concreteValueType); }
public string input2Dimension
private string input2Dimension
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(GetInputSlot2Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(GetInputSlot3Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlot3Id).concreteValueType); }
}
}
}

35
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/MaterialSlot.cs


[SerializeField]
private ConcreteSlotValueType m_ConcreteValueType;
[SerializeField]
private string m_ShaderOutputName;
public MaterialSlot(string name, string displayName, SlotType slotType, int priority, SlotValueType valueType, Vector4 defaultValue)
: base(name, displayName, slotType, priority)
public MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, SlotValueType valueType, Vector4 defaultValue, int priority)
: base(slotId, displayName, slotType, priority)
{
SharedInitialize(shaderOutputName, valueType, defaultValue);
}
public MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, SlotValueType valueType, Vector4 defaultValue)
: base(slotId, displayName, slotType)
{
SharedInitialize(shaderOutputName, valueType, defaultValue);
}
private void SharedInitialize(string inShaderOutputName, SlotValueType inValueType, Vector4 inDefaultValue)
m_ValueType = valueType;
m_DefaultValue = defaultValue;
m_CurrentValue = defaultValue;
m_ShaderOutputName = inShaderOutputName;
m_ValueType = inValueType;
m_DefaultValue = inDefaultValue;
m_CurrentValue = inDefaultValue;
switch (valueType)
switch (inValueType)
{
case SlotValueType.Vector1:
concreteValueType = ConcreteSlotValueType.Vector1;

get { return m_ConcreteValueType; }
set { m_ConcreteValueType = value; }
}
public string shaderOutputName
{
get { return m_ShaderOutputName; }
set { m_ShaderOutputName = value; }
}
public void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode, ConcreteSlotValueType slotValueType, AbstractMaterialNode owner)
{
if (!generationMode.IsPreview())

8
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/NormalNode.cs


[Title("Input/Normal Node")]
public class NormalNode : AbstractMaterialNode
{
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "Normal";
public NormalNode()
{
name = "Normal";

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector3, new Vector4(0,0,1,1)));
RemoveSlotsNameNotMatching(new[] {kOutputSlotName});
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector3, new Vector4(0, 0, 1, 1)));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
private const string kOutputSlotName = "Normal";
public override bool hasPreview
{

18
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/PixelShaderNode.cs


public void GenerateNodeCode(ShaderGenerator shaderBody, GenerationMode generationMode)
{
var lightFunction = GetLightFunction();
var firstPassSlotName = lightFunction.GetFirstPassSlotName();
var firstPassSlotId = lightFunction.GetFirstPassSlotId();
var firstPassSlot = FindInputSlot<MaterialSlot>(firstPassSlotName);
var firstPassSlot = FindInputSlot<MaterialSlot>(firstPassSlotId);
NodeUtils.DepthFirstCollectNodesFromNode(nodes, this, firstPassSlot, false);
NodeUtils.DepthFirstCollectNodesFromNode(nodes, this, firstPassSlotId, false);
for (int index = 0; index < nodes.Count; index++)
{

}
foreach (var edge in owner.GetEdges(GetSlotReference(firstPassSlot.name)))
foreach (var edge in owner.GetEdges(firstPassSlot.slotReference))
{
var outputRef = edge.outputSlot;
var fromNode = owner.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);

var fromSlot = fromNode.FindOutputSlot<MaterialSlot>(outputRef.slotName) as MaterialSlot;
var fromSlot = fromNode.FindOutputSlot<MaterialSlot>(outputRef.slotId) as MaterialSlot;
shaderBody.AddShaderChunk("o." + firstPassSlot.name + " = " + fromNode.GetVariableNameForSlot(fromSlot) + ";", true);
shaderBody.AddShaderChunk("o." + firstPassSlot.shaderOutputName + " = " + fromNode.GetVariableNameForSlot(fromSlot) + ";", true);
}
// track the last index of nodes... they have already been processed :)

if (slot == firstPassSlot)
continue;
foreach (var edge in owner.GetEdges(GetSlotReference(slot.name)))
foreach (var edge in owner.GetEdges(slot.slotReference))
{
var outputRef = edge.outputSlot;
var fromNode = owner.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);

var fromSlot = fromNode.FindOutputSlot<MaterialSlot>(outputRef.slotName) as MaterialSlot;
var fromSlot = fromNode.FindOutputSlot<MaterialSlot>(outputRef.slotId) as MaterialSlot;
shaderBody.AddShaderChunk("o." + slot.name + " = " + fromNode.GetVariableNameForSlot(fromSlot) + ";", true);
shaderBody.AddShaderChunk("o." + slot.shaderOutputName + " = " + fromNode.GetVariableNameForSlot(fromSlot) + ";", true);
}
}
}

8
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ReflectNode.cs


protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(GetInputSlot1Name(), GetInputSlot1Name(), SlotType.Input, 0, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(GetInputSlot2Name(), GetInputSlot2Name(), SlotType.Input, 1, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 0, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector3, Vector4.zero);
protected override string GetFunctionName() {return "unity_reflect_" + precision; }
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ScreenPosNode.cs


UpdateNodeAfterDeserialization();
}
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "ScreenPos";
public override bool hasPreview { get { return true; } }

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotName });
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override string GetVariableNameForSlot(MaterialSlot slot)

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/SinTimeNode.cs


UpdateNodeAfterDeserialization();
}
private const int kOutputSlotId = 0;
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.one));
RemoveSlotsNameNotMatching(new[] {kOutputSlotName});
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.one));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override bool hasPreview

49
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/TextureNode.cs


[Title("Input/Texture Node")]
public class TextureNode : PropertyNode, IGeneratesBodyCode, IGeneratesVertexShaderBlock, IGeneratesVertexToFragmentBlock
{
protected const string kUVSlotName = "UV";
protected const string kUVSlotName = "UV";
protected const int kUVSlotId = 0;
protected const int kOutputSlotRGBAId = 1;
protected const int kOutputSlotRId =2;
protected const int kOutputSlotGId =3;
protected const int kOutputSlotBId = 4;
protected const int kOutputSlotAId = 5;
[SerializeField]
private string m_TextureGuid;

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotRName, kOutputSlotRName, SlotType.Output, 1, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotGName, kOutputSlotGName, SlotType.Output, 2, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotBName, kOutputSlotBName, SlotType.Output, 3, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotAName, kOutputSlotAName, SlotType.Output, 4, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kUVSlotName, kUVSlotName, SlotType.Input, 0, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(kUVSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero));
protected string[] validSlots
protected int[] validSlots
get { return new[] {kOutputSlotRGBAName, kOutputSlotRName, kOutputSlotGName, kOutputSlotBName, kOutputSlotAName, kUVSlotName}; }
get { return new[] {kOutputSlotRGBAId, kOutputSlotRId, kOutputSlotGId, kOutputSlotBId, kOutputSlotAId, kUVSlotId}; }
var uvSlot = FindInputSlot<MaterialSlot>(kUVSlotName);
var uvSlot = FindInputSlot<MaterialSlot>(kUVSlotId);
var edges = owner.GetEdges(GetSlotReference(uvSlot.name)).ToList();
var edges = owner.GetEdges(uvSlot.slotReference).ToList();
var slot = fromNode.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotName);
var slot = fromNode.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId);
uvName = ShaderGenerator.AdaptNodeOutput(fromNode, slot, ConcreteSlotValueType.Vector2, true);
}

public override string GetVariableNameForSlot(MaterialSlot s)
{
string slotOutput;
switch (s.name)
switch (s.id)
case kOutputSlotRName:
case kOutputSlotRId:
case kOutputSlotGName:
case kOutputSlotGId:
case kOutputSlotBName:
case kOutputSlotBId:
case kOutputSlotAName:
case kOutputSlotAId:
slotOutput = ".a";
break;
default:

public void GenerateVertexToFragmentBlock(ShaderGenerator visitor, GenerationMode generationMode)
{
var uvSlot = FindInputSlot<MaterialSlot>(kUVSlotName);
var uvSlot = FindInputSlot<MaterialSlot>(kUVSlotId);
var edges = owner.GetEdges(GetSlotReference(uvSlot.name));
var edges = owner.GetEdges(uvSlot.slotReference);
if (!edges.Any())
UVNode.StaticGenerateVertexToFragmentBlock(visitor, generationMode);
}

var uvSlot = FindInputSlot<MaterialSlot>(kUVSlotName);
var uvSlot = FindInputSlot<MaterialSlot>(kUVSlotId);
var edges = owner.GetEdges(GetSlotReference(uvSlot.name));
var edges = owner.GetEdges(uvSlot.slotReference);
if (!edges.Any())
UVNode.GenerateVertexShaderBlock(visitor);
}

30
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/TimeNode.cs


private const string kOutputSlotNameZ = "Time.z";
private const string kOutputSlotNameW = "Time.w";
private const int kOutputSlotId = 0;
private const int kOutputSlotIdX = 1;
private const int kOutputSlotIdY = 2;
private const int kOutputSlotIdZ = 3;
private const int kOutputSlotIdW = 4;
public TimeNode()
{
name = "Time";

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotNameX, kOutputSlotNameX, SlotType.Output, 1, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotNameY, kOutputSlotNameY, SlotType.Output, 2, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotNameZ, kOutputSlotNameZ, SlotType.Output, 3, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotNameW, kOutputSlotNameW, SlotType.Output, 4, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotIdX, kOutputSlotNameX, kOutputSlotNameX, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotIdY, kOutputSlotNameY, kOutputSlotNameY, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotIdZ, kOutputSlotNameZ, kOutputSlotNameZ, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlotIdW, kOutputSlotNameW, kOutputSlotNameW, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
protected string[] validSlots
protected int[] validSlots
get { return new[] {kOutputSlotName, kOutputSlotNameX, kOutputSlotNameY, kOutputSlotNameZ, kOutputSlotName}; }
get { return new[] {kOutputSlotId, kOutputSlotIdX, kOutputSlotIdY, kOutputSlotIdZ, kOutputSlotId}; }
switch (s.name)
switch (s.id)
case kOutputSlotNameX:
case kOutputSlotIdX:
case kOutputSlotNameY:
case kOutputSlotIdY:
case kOutputSlotNameZ:
case kOutputSlotIdZ:
case kOutputSlotNameW:
case kOutputSlotIdW:
return "_Time.w";
default:
return "_Time";

7
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UVNode.cs


[Title("Input/UV Node")]
public class UVNode : AbstractMaterialNode, IGeneratesVertexToFragmentBlock, IGeneratesVertexShaderBlock, IGeneratesBodyCode
{
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "UV";
public override bool hasPreview { get { return true; } }

public override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] {kOutputSlotName});
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public static void StaticGenerateVertexToFragmentBlock(ShaderGenerator visitor, GenerationMode generationMode)

public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot<MaterialSlot>(kOutputSlotName);
var outputSlot = FindOutputSlot<MaterialSlot>(kOutputSlotId);
string uvValue = "IN.meshUV0";
visitor.AddShaderChunk(precision + "4 " + GetVariableNameForSlot(outputSlot) + " = " + uvValue + ";", true);

6
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UnpackNormalNode.cs


protected virtual MaterialSlot GetInputSlot()
{
return new MaterialSlot(GetInputSlotName(), GetInputSlotName(), SlotType.Input, 0, SlotValueType.Vector4, Vector4.zero);
return new MaterialSlot(InputSlotId, GetInputSlotName(), kInputSlotShaderName, SlotType.Input, SlotValueType.Vector4, Vector4.zero);
return new MaterialSlot(GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, 0, SlotValueType.Vector3, Vector4.zero);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector3, Vector4.zero);
protected override string GetInputSlotName() {return "PackedNormal"; }
protected override string GetOutputSlotName() {return "Normal"; }

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector1Node.cs


[SerializeField]
private float m_Value;
public const int OutputSlotId = 0;
private const string kOutputSlotName = "Value";
public Vector1Node()

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector1, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotName });
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
}
public override PropertyType propertyType

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector2Node.cs


[Title("Input/Vector 2 Node")]
public class Vector2Node : PropertyNode, IGeneratesBodyCode
{
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "Value";
[SerializeField]

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector2, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotName });
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector2, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override PropertyType propertyType

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector3Node.cs


[Title("Input/Vector 3 Node")]
public class Vector3Node : PropertyNode, IGeneratesBodyCode
{
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "Value";
[SerializeField]

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector3, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotName });
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector3, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override PropertyType propertyType

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector4Node.cs


[SerializeField]
private Vector4 m_Value;
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "Value";
public Vector4Node()

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] {kOutputSlotName});
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override PropertyType propertyType

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ViewDirectionNode.cs


[Title("Input/View Direction Node")]
public class ViewDirectionNode : AbstractMaterialNode, IGeneratesVertexToFragmentBlock
{
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "ViewDirection";
public override bool hasPreview { get { return true; } }

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector3, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotName });
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector3, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override string GetVariableNameForSlot(MaterialSlot slot)

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/WorldPosNode.cs


[Title("Input/World Pos Node")]
public class WorldPosNode : AbstractMaterialNode, IGeneratesVertexToFragmentBlock
{
private const int kOutputSlotId = 0;
private const string kOutputSlotName = "WorldPos";
public override bool hasPreview { get { return true; } }

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotName, kOutputSlotName, SlotType.Output, 0, SlotValueType.Vector3, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotName });
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector3, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}
public override string GetVariableNameForSlot(MaterialSlot slot)

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/AbstractSubGraphIONode.cs


{
public abstract class AbstractSubGraphIONode : AbstractMaterialNode
{
public abstract void AddSlot();
public abstract int AddSlot();
public abstract void RemoveSlot();

14
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphInputNode.cs


{
name = "SubGraphInputs";
}
public override void AddSlot()
public override int AddSlot()
var index = GetOutputSlots<ISlot>().Count();
AddSlot(new MaterialSlot("Input" + index, "Input" + index, SlotType.Output, index, SlotValueType.Vector4, Vector4.zero));
var nextSlotId = GetOutputSlots<ISlot>().Count() + 1;
AddSlot(new MaterialSlot(-nextSlotId, "Input " + nextSlotId, "Input" + nextSlotId, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
return -nextSlotId;
var index = GetOutputSlots<ISlot>().Count();
if (index == 0)
var lastSlotId = GetOutputSlots<ISlot>().Count();
if (lastSlotId == 0)
RemoveSlot("Input" + (index - 1));
RemoveSlot(-lastSlotId);
}
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)

14
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphNode.cs


public void OnEnable()
{
List<string> validNames = new List<string>();
var validNames = new List<int>();
if (subGraphAsset == null)
{
RemoveSlotsNameNotMatching(validNames);

var subGraphInputNode = subGraphAsset.subGraph.inputNode;
foreach (var slot in subGraphInputNode.GetOutputSlots<MaterialSlot>())
{
AddSlot(new MaterialSlot(slot.name, slot.displayName, SlotType.Input, slot.priority, slot.valueType, slot.defaultValue));
validNames.Add(slot.name);
AddSlot(new MaterialSlot(slot.id, slot.displayName, slot.shaderOutputName, SlotType.Input, slot.valueType, slot.defaultValue));
validNames.Add(slot.id);
AddSlot(new MaterialSlot(slot.name, slot.displayName, SlotType.Output, slot.priority, slot.valueType, slot.defaultValue));
validNames.Add(slot.name);
AddSlot(new MaterialSlot(slot.id, slot.displayName, slot.shaderOutputName, SlotType.Output, slot.valueType, slot.defaultValue));
validNames.Add(slot.id);
}
RemoveSlotsNameNotMatching(validNames);

foreach (var slot in GetInputSlots<MaterialSlot>())
{
var varName = subGraphInputNode.GetVariableNameForSlot(subGraphInputNode.FindOutputSlot<MaterialSlot>(slot.name));
var varName = subGraphInputNode.GetVariableNameForSlot(subGraphInputNode.FindOutputSlot<MaterialSlot>(slot.id));
var varValue = GetSlotValue(slot, GenerationMode.SurfaceShader);
var outDimension = ConvertConcreteSlotValueTypeToString(slot.concreteValueType);

// Copy the outputs to the parent context name);
foreach (var slot in GetOutputSlots<MaterialSlot>())
{
var inputSlot = subGraphOutputNode.FindInputSlot<MaterialSlot>(slot.name);
var inputSlot = subGraphOutputNode.FindInputSlot<MaterialSlot>(slot.id);
var inputValue = subGraphOutputNode.GetSlotValue(inputSlot, GenerationMode.SurfaceShader);
outputString.AddShaderChunk(

9
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphOutputNode.cs


name = "SubGraphOutputs";
}
public override void AddSlot()
public override int AddSlot()
var index = GetInputSlots<ISlot>().Count();
AddSlot(new MaterialSlot("Output" + index, "Output" + index, SlotType.Input, index, SlotValueType.Vector4, Vector4.zero));
var index = GetInputSlots<ISlot>().Count() + 1;
AddSlot(new MaterialSlot(index, "Output " + index, "Output" + index, SlotType.Input, SlotValueType.Vector4, Vector4.zero));
return index;
}
public override void RemoveSlot()

return;
RemoveSlot("Output" + (index - 1));
RemoveSlot(index);
}
}
}
正在加载...
取消
保存