浏览代码

[material graph]Compiles again.

/main
Tim Cooper 8 年前
当前提交
7a1ca7ce
共有 16 个文件被更改,包括 361 次插入244 次删除
  1. 39
      UnityProject/Assets/UnityShaderEditor/Editor/Source/AbstractMaterialGraph.cs
  2. 10
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs
  3. 11
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialGraphDataSource.cs
  4. 26
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/BaseLightFunction.cs
  5. 258
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/AbstractMaterialNode.cs
  6. 24
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function2Input.cs
  7. 2
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MaterialSlot.cs
  8. 26
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs
  9. 119
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SerializableNode.cs
  10. 19
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SerializableSlot.cs
  11. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector4Node.cs
  12. 4
      UnityProject/Assets/UnityShaderEditor/Editor/Source/PixelGraph.cs
  13. 19
      UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph.cs
  14. 20
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/NodeUtils.cs
  15. 13
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs
  16. 9
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/GUIModificationType.cs

39
UnityProject/Assets/UnityShaderEditor/Editor/Source/AbstractMaterialGraph.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.MaterialGraph
{

m_Owner = owner;
}
public MaterialGraph owner
{
get { return m_Owner; }
}
get { return nodes.Where(x => x is AbstractMaterialNode).Cast<AbstractMaterialNode>(); }
get { return nodes.OfType<AbstractMaterialNode>(); }
}
public PreviewRenderUtility previewUtility

get { return nodes.Any(x => x is IRequiresTime); }
}
public MaterialGraph owner
{
get { return m_Owner; }
}
public override void AddNode(SerializableNode node)
{
if (node is AbstractMaterialNode)
{
base.AddNode(node);
}
else
{
Debug.LogWarningFormat("Trying to add node {0} to Material graph, but it is not a {1}", node, typeof(AbstractMaterialNode));
}
}
public AbstractMaterialNode GetMaterialNodeFromGuid(Guid guid)
{
var node = GetNodeFromGuid(guid);
if (node == null)
{
Debug.LogWarningFormat("Node with guid {0} either can not be found", guid);
return null;
}
if (node is AbstractMaterialNode)
return node as AbstractMaterialNode;
Debug.LogWarningFormat("Node {0} with guid {1} is not a Material node", guid);
return null;
}
public override void ValidateGraph()
{
base.ValidateGraph();

10
UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs


Vector3 pos = vector3;
// input slots
foreach (var slot in node.inputSlots)
foreach (var slot in node.materialInputSlots)
{
pos.y += 22;
AddChild(new NodeAnchor(pos, typeof (Vector4), node, slot, data, Direction.Input));

// output port
pos.x = width;
pos.y = yStart;
foreach (var slot in node.outputSlots)
foreach (var slot in node.materialOuputSlots)
{
var edges = node.owner.GetEdges(slot);
// don't show empty output slots in collapsed mode

private bool MarkDirtyIfNeedsTime(CanvasElement element, Event e, Canvas2D parent)
{
var childrenNodes = ListPool<AbstractMaterialNode>.Get();
var childrenNodes = ListPool<SerializableNode>.Get();
ListPool<AbstractMaterialNode>.Release(childrenNodes);
ListPool<SerializableNode>.Release(childrenNodes);
return true;
}

public static void OnGUI(List<CanvasElement> selection)
{
var drawableMaterialNode = selection.Where(x => x is DrawableMaterialNode).Cast<DrawableMaterialNode>().FirstOrDefault();
var drawableMaterialNode = selection.OfType<DrawableMaterialNode>().FirstOrDefault();
if (drawableMaterialNode != null && drawableMaterialNode.m_Node.OnGUI())
{
// if we were changed, we need to redraw all the

11
UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialGraphDataSource.cs


public void DeleteElements(List<CanvasElement> elements)
{
var toRemoveEdge = new List<Edge>();
// delete selected edges first
foreach (var e in elements.Where(x => x is Edge<NodeAnchor>))
{

&& graph.currentGraph.GetNodeFromGuid(x.inputSlot.nodeGuid).FindInputSlot(x.inputSlot.slotName) == localEdge.Right.m_Slot);
Debug.Log("Deleting edge " + edge);
graph.currentGraph.RemoveEdgeNoRevalidate(edge);
toRemoveEdge.Add(edge);
var toRemoveNode = new List<SerializableNode>();
// now delete the nodes
foreach (var e in elements.Where(x => x is DrawableMaterialNode))
{

Debug.Log("Deleting node " + e + " " + node);
graph.currentGraph.RemoveNodeNoRevalidate(node);
toRemoveNode.Add(node);
graph.currentGraph.ValidateGraph();
graph.currentGraph.RemoveElements(toRemoveNode, toRemoveEdge);
}
public void Connect(NodeAnchor a, NodeAnchor b)

26
UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/BaseLightFunction.cs


public override string GetSurfaceOutputStructureName() { return "SurfaceOutputStandard"; }
public override void DoSlotsForConfiguration(PixelShaderNode node)
{
node.AddSlot(new MaterialSlot(node, kAlbedoSlotName, kAlbedoSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kNormalSlotName, kNormalSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kMetallicSlotName, kMetallicSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kSmoothnessSlotName, kSmoothnessSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kOcclusion, kOcclusion, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kAlphaSlotName, kAlphaSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kAlbedoSlotName, kAlbedoSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kNormalSlotName, kNormalSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kMetallicSlotName, kMetallicSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kSmoothnessSlotName, kSmoothnessSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kOcclusion, kOcclusion, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kAlphaSlotName, kAlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
// clear out slot names that do not match the slots
// we support

public override string GetSurfaceOutputStructureName() { return "SurfaceOutputStandardSpecular"; }
public override void DoSlotsForConfiguration(PixelShaderNode node)
{
node.AddSlot(new MaterialSlot(node, kAlbedoSlotName, kAlbedoSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kNormalSlotName, kNormalSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kSpecularSlotName, kSpecularSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kEmissionSlotName, kEmissionSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kSmoothnessSlotName, kSmoothnessSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kOcclusion, kOcclusion, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kAlphaSlotName, kAlphaSlotName, MaterialSlot.SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kAlbedoSlotName, kAlbedoSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kNormalSlotName, kNormalSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kSpecularSlotName, kSpecularSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kEmissionSlotName, kEmissionSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kSmoothnessSlotName, kSmoothnessSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kOcclusion, kOcclusion, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
node.AddSlot(new MaterialSlot(node, kAlphaSlotName, kAlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
// clear out slot names that do not match the slots
// we support

258
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/AbstractMaterialNode.cs


[NonSerialized]
private Shader m_PreviewShader;
public NeedsRepaint onNeedsRepaint;
protected AbstractMaterialNode(AbstractMaterialGraph theOwner) : base(theOwner)
{}
public AbstractMaterialGraph materialGraphOwner
{
get
{
return owner as AbstractMaterialGraph;;
}
}
public string precision
{

}
}
}
public IEnumerable<MaterialSlot> materialSlots
{
get { return slots.OfType<MaterialSlot>(); }
}
public IEnumerable<MaterialSlot> materialInputSlots
{
get { return inputSlots.OfType<MaterialSlot>(); }
}
public IEnumerable<MaterialSlot> materialOuputSlots
{
get { return outputSlots.OfType<MaterialSlot>(); }
}
protected AbstractMaterialNode(AbstractMaterialGraph theOwner) : base(theOwner)
{ }
public virtual void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{}

if (!generationMode.IsPreview())
return;
foreach (var inputSlot in inputSlots)
foreach (var inputSlot in materialInputSlots)
{
var edges = owner.GetEdges(inputSlot);
if (edges.Any())

GL.sRGBWrite = false;
}
public MaterialSlot FindInputSlot(string name)
{
var slot = m_Slots.FirstOrDefault(x => x.isInputSlot && x.name == name);
if (slot == null)
Debug.LogError("Input MaterialSlot: " + name + " could be found on node " + GetOutputVariableNameForNode());
return slot;
}
public MaterialSlot FindOutputSlot(string name)
{
var slot = m_Slots.FirstOrDefault(x => x.isOutputSlot && x.name == name);
if (slot == null)
Debug.LogError("Output MaterialSlot: " + name + " could be found on node " + GetOutputVariableNameForNode());
return slot;
}
protected string GetSlotValue(MaterialSlot inputSlot, GenerationMode generationMode)
{
var edges = owner.GetEdges(inputSlot).ToArray();

var fromSocketRef = edges[0].outputSlot;
var fromNode = owner.GetNodeFromGuid(fromSocketRef.nodeGuid);
var slot = fromNode.FindOutputSlot(fromSocketRef.slotName);
var fromNode = materialGraphOwner.GetMaterialNodeFromGuid(fromSocketRef.nodeGuid);
if (fromNode == null)
return string.Empty;
var slot = fromNode.FindOutputSlot(fromSocketRef.slotName) as MaterialSlot;
if (slot == null)
return string.Empty;
return ShaderGenerator.AdaptNodeOutput(this, slot, generationMode, inputSlot.concreteValueType);
}

public void RemoveSlotsNameNotMatching(string[] slotNames)
public MaterialSlot FindMaterialInputSlot(string name)
var invalidSlots = m_Slots.Select(x => x.name).Except(slotNames);
var slot = FindInputSlot(name);
if (slot == null)
return null;
foreach (var invalidSlot in invalidSlots.ToList())
{
Debug.LogWarningFormat("Removing Invalid MaterialSlot: {0}", invalidSlot);
RemoveSlot(invalidSlot);
}
if (slot is MaterialSlot)
return slot as MaterialSlot;
Debug.LogErrorFormat("Input Slot: {0} exists but is not of type {1}", name, typeof(MaterialSlot));
return null;
public MaterialSlot FindMaterialOutputSlot(string name)
{
var slot = FindOutputSlot(name);
if (slot == null)
return null;
if (slot is MaterialSlot)
return slot as MaterialSlot;
Debug.LogErrorFormat("Output Slot: {0} exists but is not of type {1}", name, typeof(MaterialSlot));
return null;
}
private ConcreteSlotValueType FindCommonChannelType(ConcreteSlotValueType @from, ConcreteSlotValueType to)
{
if (ImplicitConversionExists(@from, to))

foreach (var edge in edges)
{
var fromSocketRef = edge.outputSlot;
var outputNode = owner.GetNodeFromGuid(fromSocketRef.nodeGuid);
var outputNode = materialGraphOwner.GetMaterialNodeFromGuid(fromSocketRef.nodeGuid);
if (outputNode == null)
continue;
outputNode.ValidateNode();
if (outputNode.hasError)
isInError = true;

var skippedDynamicSlots = new List<MaterialSlot>();
// iterate the input slots
foreach (var inputSlot in inputSlots)
foreach (var inputSlot in materialInputSlots)
{
var inputType = inputSlot.valueType;
// if there is a connection

// get the output details
var outputSlotRef = edges[0].outputSlot;
var outputNode = owner.GetNodeFromGuid(outputSlotRef.nodeGuid);
var outputSlot = outputNode.FindOutputSlot(outputSlotRef.slotName);
var outputNode = materialGraphOwner.GetMaterialNodeFromGuid(outputSlotRef.nodeGuid);
if (outputNode == null)
continue;
var outputSlot = outputNode.FindOutputSlot(outputSlotRef.slotName) as MaterialSlot;
if (outputSlot == null)
continue;
var outputConcreteType = outputSlot.concreteValueType;
// if we have a standard connection... just check the types work!

foreach (var skippedSlot in skippedDynamicSlots)
skippedSlot.concreteValueType = dynamicType;
var inputError = inputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
var inputError = materialInputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
foreach (var outputSlot in outputSlots)
foreach (var outputSlot in materialOuputSlots)
{
if (inputError)
{

}
isInError |= inputError;
isInError |= outputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
isInError |= materialOuputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
isInError |= CalculateNodeHasError();
hasError = isInError;

}
}
public virtual bool OnGUI()
{
GUILayout.Label("MaterialSlot Defaults", EditorStyles.boldLabel);
var modified = false;
foreach (var slot in inputSlots)
{
if (!owner.GetEdges(slot).Any())
modified |= DoSlotUI(this, slot);
}
return modified;
}
public static bool DoSlotUI(AbstractMaterialNode node, MaterialSlot slot)
{
GUILayout.BeginHorizontal( /*EditorStyles.inspectorBig*/);
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
GUILayout.Label("MaterialSlot " + slot.name, EditorStyles.largeLabel);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.EndHorizontal();
return slot.OnGUI();
}
public virtual bool DrawSlotDefaultInput(Rect rect, MaterialSlot inputSlot)
{
var inputSlotType = inputSlot.concreteValueType;

public virtual IEnumerable<MaterialSlot> GetDrawableInputProxies()
{
return inputSlots.Where(x => !owner.GetEdges(x).Any());
return materialInputSlots.Where(x => !owner.GetEdges(x).Any());
}
public void ExecuteRepaint()

}
// CollectDependentNodes looks at the current node and calculates
// which nodes further up the tree (parents) would be effected if this node was changed
// it also includes itself in this list
public IEnumerable<AbstractMaterialNode> CollectDependentNodes()
{
var nodeList = new List<AbstractMaterialNode>();
NodeUtils.CollectDependentNodes(nodeList, this);
return nodeList;
}
// CollectDependentNodes looks at the current node and calculates
// 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 List<AbstractMaterialNode> CollectChildNodesByExecutionOrder(List<AbstractMaterialNode> nodeList, MaterialSlot slotToUse = null, bool includeSelf = true)
{
if (slotToUse != null && !m_Slots.Contains(slotToUse))
{
Debug.LogError("Attempting to collect nodes by execution order with an invalid MaterialSlot on: " + name);
return nodeList;
}
NodeUtils.CollectChildNodesByExecutionOrder(nodeList, this, slotToUse);
if (!includeSelf)
nodeList.Remove(this);
return nodeList;
}
protected virtual bool UpdatePreviewShader()
{
if (hasError)

}
}
var previewUtil = owner.previewUtility;
var previewUtil = materialGraphOwner.previewUtility;
previewUtil.BeginPreview(targetSize, GUIStyle.none);
if (m_GeneratedShaderMode == PreviewMode.Preview3D)

protected virtual void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
var validSlots = inputSlots.ToArray();
var validSlots = materialInputSlots.ToArray();
for (var index = 0; index < validSlots.Length; index++)
{

public static void UpdateMaterialProperties(AbstractMaterialNode target, Material material)
{
var childNodes = ListPool<AbstractMaterialNode>.Get();
var childNodes = ListPool<SerializableNode>.Get();
var node = childNodes[index];
var node = childNodes[index] as AbstractMaterialNode;
if (node == null)
continue;
node.CollectPreviewMaterialProperties(pList);
}

ListPool<AbstractMaterialNode>.Release(childNodes);
ListPool<SerializableNode>.Release(childNodes);
ListPool<PreviewProperty>.Release(pList);
}

UpdateMaterialProperties(this, previewMaterial);
}
if (!m_Slots.Contains(s)) Debug.LogError("Attempting to use MaterialSlot (" + s + ") for output on a node that does not have this MaterialSlot!");
if (!materialSlots.Contains(s)) Debug.LogError("Attempting to use MaterialSlot (" + s + ") for output on a node that does not have this MaterialSlot!");
return GetOutputVariableNameForNode() + "_" + s.name;
}

return name + "_" + guid.ToString().Replace("-", "_");
}
public virtual Vector4 GetNewSlotDefaultValue(SlotValueType type)
{
return Vector4.one;
}
public void AddSlot(MaterialSlot slot)
public sealed override void AddSlot(SerializableSlot slot)
if (slot == null)
return;
// new MaterialSlot, just add it, we cool
if (!m_Slots.Contains(slot))
{
m_Slots.Add(slot);
return;
}
// old MaterialSlot found
// update the default value, and the slotType!
var foundSlots = m_Slots.FindAll(x => x.name == slot.name);
// if we are in a bad state (> 1 MaterialSlot with same name, just reset).
if (foundSlots.Count > 1)
if (!(slot is MaterialSlot))
Debug.LogWarningFormat("Node {0} has more than one MaterialSlot with the same name, removing.");
foundSlots.ForEach(x => m_Slots.Remove(x));
m_Slots.Add(slot);
Debug.LogWarningFormat("Trying to add slot {0} to Material node {1}, but it is not a {2}", slot, this, typeof(MaterialSlot));
var foundSlot = foundSlots[0];
base.AddSlot(slot);
// if the defualt and current are the same, change the current
var addingSlot = (MaterialSlot) slot;
var foundSlot = (MaterialSlot)slots.FirstOrDefault(x => x.name == slot.name);
// if the default and current are the same, change the current
if (foundSlot.defaultValue == foundSlot.currentValue)
foundSlot.currentValue = slot.defaultValue;
foundSlot.defaultValue = slot.defaultValue;
foundSlot.valueType = slot.valueType;
}
public void RemoveSlot(string name)
{
m_Slots.RemoveAll(x => x.name == name);
}
public string GenerateSlotName(SerializableSlot.SlotType type)
{
var slotsToCheck = type == SerializableSlot.SlotType.Input ? inputSlots.ToArray() : outputSlots.ToArray();
var format = type == SerializableSlot.SlotType.Input ? "I{0:00}" : "O{0:00}";
var index = slotsToCheck.Count();
var slotName = string.Format(format, index);
if (slotsToCheck.All(x => x.name != slotName))
return slotName;
index = 0;
do
{
slotName = string.Format(format, index++);
} while (slotsToCheck.Any(x => x.name == slotName));
if (addingSlot.defaultValue == foundSlot.currentValue)
foundSlot.currentValue = addingSlot.defaultValue;
return slotName;
foundSlot.defaultValue = addingSlot.defaultValue;
foundSlot.valueType = addingSlot.valueType;
}
public enum GUIModificationType
{
None,
Repaint,
ModelChanged
}
}

24
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function2Input.cs


get { return new[] {GetInputSlot1Name(), GetInputSlot2Name(), GetOutputSlotName()}; }
}
protected virtual MaterialSlot GetInputSlot1()
protected MaterialSlot GetInputSlot1()
return new MaterialSlot(this, GetInputSlot1Name(), GetInputSlot1Name(), MaterialSlot.SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(this, GetInputSlot1Name(), GetInputSlot1Name(), SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
protected virtual MaterialSlot GetInputSlot2()
protected MaterialSlot GetInputSlot2()
return new MaterialSlot(this, GetInputSlot2Name(), GetInputSlot2Name(), MaterialSlot.SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(this, GetInputSlot2Name(), GetInputSlot2Name(), SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
protected virtual MaterialSlot GetOutputSlot()
protected MaterialSlot GetOutputSlot()
return new MaterialSlot(this, GetOutputSlotName(), GetOutputSlotName(), MaterialSlot.SlotType.Output, SlotValueType.Dynamic, Vector4.zero);
return new MaterialSlot(this, GetOutputSlotName(), GetOutputSlotName(), SlotType.Output, SlotValueType.Dynamic, Vector4.zero);
}
protected virtual string GetInputSlot1Name()

public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot(GetOutputSlotName());
var inputSlot1 = FindInputSlot(GetInputSlot1Name());
var inputSlot2 = FindInputSlot(GetInputSlot2Name());
var outputSlot = FindMaterialOutputSlot(GetOutputSlotName());
var inputSlot1 = FindMaterialInputSlot(GetInputSlot1Name());
var inputSlot2 = FindMaterialInputSlot(GetInputSlot2Name());
if (inputSlot1 == null || inputSlot2 == null || outputSlot == null)
{

public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot(GetOutputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindMaterialOutputSlot(GetOutputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot(GetInputSlot1Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindMaterialInputSlot(GetInputSlot1Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot(GetInputSlot2Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(FindMaterialInputSlot(GetInputSlot2Name()).concreteValueType); }
}
}
}

2
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MaterialSlot.cs


}
}
public bool OnGUI()
public override bool OnGUI()
{
EditorGUI.BeginChangeCheck();
m_CurrentValue = EditorGUILayout.Vector4Field("Value", m_CurrentValue);

26
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs


var firstPassSlotName = lightFunction.GetFirstPassSlotName();
// do the normal slot first so that it can be used later in the shader :)
var firstPassSlot = FindInputSlot(firstPassSlotName);
var nodes = ListPool<AbstractMaterialNode>.Get();
var nodes = ListPool<SerializableNode>.Get();
CollectChildNodesByExecutionOrder(nodes, firstPassSlot, false);
for (int index = 0; index < nodes.Count; index++)

foreach (var edge in owner.GetEdges(firstPassSlot))
{
var outputRef = edge.outputSlot;
var fromNode = owner.GetNodeFromGuid(outputRef.nodeGuid);
var fromSlot = fromNode.FindOutputSlot(outputRef.slotName);
var fromNode = materialGraphOwner.GetMaterialNodeFromGuid(outputRef.nodeGuid);
if (fromNode == null)
continue;
var fromSlot = fromNode.FindOutputSlot(outputRef.slotName) as MaterialSlot;
if (fromSlot == null)
continue;
shaderBody.AddShaderChunk("o." + firstPassSlot.name + " = " + fromNode.GetOutputVariableNameForSlot(fromSlot, generationMode) + ";", true);
}

(node as IGeneratesBodyCode).GenerateNodeCode(shaderBody, generationMode);
}
ListPool<AbstractMaterialNode>.Release(nodes);
ListPool<SerializableNode>.Release(nodes);
foreach (var slot in inputSlots)
{

foreach (var edge in owner.GetEdges(slot))
{
var outputRef = edge.outputSlot;
var fromNode = owner.GetNodeFromGuid(outputRef.nodeGuid);
var fromSlot = fromNode.FindOutputSlot(outputRef.slotName);
var fromNode = materialGraphOwner.GetMaterialNodeFromGuid(outputRef.nodeGuid);
if (fromNode == null)
continue;
var fromSlot = fromNode.FindOutputSlot(outputRef.slotName) as MaterialSlot;
if (fromSlot == null)
continue;
shaderBody.AddShaderChunk("o." + slot.name + " = " + fromNode.GetOutputVariableNameForSlot(fromSlot, generationMode) + ";", true);
}
}

var shaderName = "Hidden/PreviewShader/" + name + "_" + guid.ToString().Replace("-","_");
List<PropertyGenerator.TextureInfo> defaultTextures;
var resultShader = ShaderGenerator.GenerateSurfaceShader(owner.owner, shaderName, true, out defaultTextures);
var resultShader = ShaderGenerator.GenerateSurfaceShader(materialGraphOwner.owner, shaderName, true, out defaultTextures);
m_GeneratedShaderMode = PreviewMode.Preview3D;
hasError = !InternalUpdatePreviewShader(resultShader);
return true;

119
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SerializableNode.cs


public class SerializableNode : ISerializationCallbackReceiver
{
public delegate void NeedsRepaint();
public NeedsRepaint onNeedsRepaint;
private const int kPreviewWidth = 64;
private const int kPreviewHeight = 64;

m_Guid = Guid.NewGuid();
}
public virtual void AddSlot(SerializableSlot slot)
{
if (slot == null)
return;
// new MaterialSlot, just add it, we cool
if (!m_Slots.Contains(slot))
{
m_Slots.Add(slot);
return;
}
// old Slot found
// update the default value, and the slotType!
var foundSlots = m_Slots.FindAll(x => x.name == slot.name);
// if we are in a bad state (> 1 slot with same name).
// or our types are differernt now
// reset the slot to the new value
if (foundSlots.Count > 1 || foundSlots[0].GetType() != slot.GetType())
{
Debug.LogWarningFormat("Node {0} has more than one MaterialSlot with the same name, removing.");
m_Slots.RemoveAll(x => x.name == slot.name);
m_Slots.Add(slot);
}
}
public void RemoveSlot(string name)
{
m_Slots.RemoveAll(x => x.name == name);
}
public void RemoveSlotsNameNotMatching(string[] slotNames)
{
var invalidSlots = m_Slots.Select(x => x.name).Except(slotNames);
foreach (var invalidSlot in invalidSlots.ToList())
{
Debug.LogFormat("Removing Invalid MaterialSlot: {0}", invalidSlot);
RemoveSlot(invalidSlot);
}
}
public SerializableSlot FindInputSlot(string name)
{
var slot = inputSlots.FirstOrDefault(x => x.name == name);
if (slot == null)
Debug.LogErrorFormat("Input Slot: {0} could be found on node {1}", name, this);
return slot;
}
public SerializableSlot FindOutputSlot(string name)
{
var slot = outputSlots.FirstOrDefault(x => x.name == name);
if (slot == null)
Debug.LogErrorFormat("Output Slot: {0} could be found on node {1}", name, this);
return slot;
}
// CollectDependentNodes looks at the current node and calculates
// which nodes further up the tree (parents) would be effected if this node was changed
// it also includes itself in this list
public IEnumerable<SerializableNode> CollectDependentNodes()
{
var nodeList = new List<SerializableNode>();
NodeUtils.CollectDependentNodes(nodeList, this);
return nodeList;
}
// CollectDependentNodes looks at the current node and calculates
// 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 List<SerializableNode> CollectChildNodesByExecutionOrder(List<SerializableNode> nodeList, SerializableSlot slotToUse = null, bool includeSelf = true)
{
if (slotToUse != null && !m_Slots.Contains(slotToUse))
{
Debug.LogError("Attempting to collect nodes by execution order with an invalid MaterialSlot on: " + name);
return nodeList;
}
NodeUtils.CollectChildNodesByExecutionOrder(nodeList, this, slotToUse);
if (!includeSelf)
nodeList.Remove(this);
return nodeList;
}
public virtual float GetNodeUIHeight(float width)
{
return 0;

{
return GUIModificationType.None;
}
public virtual bool OnGUI()
{
GUILayout.Label("MaterialSlot Defaults", EditorStyles.boldLabel);
var modified = false;
foreach (var slot in inputSlots)
{
if (!owner.GetEdges(slot).Any())
modified |= DoSlotUI(this, slot);
}
return modified;
}
public static bool DoSlotUI(SerializableNode node, SerializableSlot slot)
{
GUILayout.BeginHorizontal( /*EditorStyles.inspectorBig*/);
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
GUILayout.Label("MaterialSlot " + slot.name, EditorStyles.largeLabel);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.EndHorizontal();
return slot.OnGUI();
}
public virtual void OnBeforeSerialize()

19
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SerializableSlot.cs


public class SerializableSlot
{
private const string kNotInit = "Not Initilaized";
public enum SlotType
{
Input,
Output
}
[SerializeField]
private string m_Name = kNotInit;

}
// used via reflection / serialization after deserialize
internal SerializableSlot(SerializableNode theOwner)
// to reconstruct this slot.
protected SerializableSlot(SerializableNode theOwner)
public virtual bool OnGUI()
{
return false;
}
}
public enum SlotType
{
Input,
Output
}
}

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector4Node.cs


private void InternalValidate()
{
AddSlot(new MaterialSlot(this, kOutputSlotName, kOutputSlotName, MaterialSlot.SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(this, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
private NodeSpecificData m_NodeSpecificData = new NodeSpecificData();
public Vector4Node(AbstractMaterialGraph owner) : base(owner)
{
name = "V4Node";

m_Value = EditorGUI.Vector4Field(new Rect(drawArea.x, drawArea.y, drawArea.width, EditorGUIUtility.singleLineHeight), "Value", m_Value);
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(owner.owner);
EditorUtility.SetDirty(materialGraphOwner.owner);
return GUIModificationType.Repaint;
}
return GUIModificationType.None;

4
UnityProject/Assets/UnityShaderEditor/Editor/Source/PixelGraph.cs


[NonSerialized]
private List<AbstractMaterialNode> m_ActiveNodes = new List<AbstractMaterialNode>();
private List<SerializableNode> m_ActiveNodes = new List<SerializableNode>();
public IEnumerable<AbstractMaterialNode> activeNodes
{
get

return m_ActiveNodes;
return m_ActiveNodes.OfType<AbstractMaterialNode>();
}
}

19
UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph.cs


ValidateGraph();
}
private void RemoveNodeNoValidate(SerializableNode node)
{
if (!node.canDeleteNode)
return;
m_Nodes.Remove(node);
}
public virtual Edge Connect(SerializableSlot fromSlot, SerializableSlot toSlot)
{
SerializableSlot outputSlot = null;

public virtual void RemoveEdge(Edge e)
{
m_Edges.Remove(e);
ValidateGraph();
}
public void RemoveElements(IEnumerable<SerializableNode> nodes, IEnumerable<Edge> edges)
{
foreach (var edge in edges)
RemoveEdgeNoValidate(edge);
foreach (var serializableNode in nodes)
RemoveNodeNoValidate(serializableNode);
ValidateGraph();
}

20
UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/NodeUtils.cs


// GetSlotsThatOutputToNodeRecurse returns a list of output slots on from node that
// manage to connect to toNode... they may go via some other nodes to reach there.
// This is done by working backwards from the toNode to the fromNode as graph is one directional
public static List<MaterialSlot> GetSlotsThatOutputToNodeRecurse(AbstractMaterialNode fromNode, AbstractMaterialNode toNode)
public static List<SerializableSlot> GetSlotsThatOutputToNodeRecurse(SerializableNode fromNode, SerializableNode toNode)
var foundUsedOutputSlots = new List<MaterialSlot>();
var foundUsedOutputSlots = new List<SerializableSlot>();
public static void RecurseNodesToFindValidOutputSlots(AbstractMaterialNode fromNode, AbstractMaterialNode currentNode, ICollection<MaterialSlot> foundUsedOutputSlots)
public static void RecurseNodesToFindValidOutputSlots(SerializableNode fromNode, SerializableNode currentNode, ICollection<SerializableSlot> foundUsedOutputSlots)
{
if (fromNode == null || currentNode == null)
{

var validSlots = ListPool<MaterialSlot>.Get();
var validSlots = ListPool<SerializableSlot>.Get();
validSlots.AddRange(currentNode.inputSlots);
for (int index = 0; index < validSlots.Count; index++)
{

RecurseNodesToFindValidOutputSlots(fromNode, outputNode, foundUsedOutputSlots);
}
}
ListPool<MaterialSlot>.Release(validSlots);
ListPool<SerializableSlot>.Release(validSlots);
public static void CollectChildNodesByExecutionOrder(ICollection<AbstractMaterialNode> nodeList, AbstractMaterialNode node, MaterialSlot slotToUse)
public static void CollectChildNodesByExecutionOrder(List<SerializableNode> nodeList, SerializableNode node, SerializableSlot slotToUse)
{
if (node == null)
return;

var validSlots = ListPool<MaterialSlot>.Get();
var validSlots = ListPool<SerializableSlot>.Get();
ListPool<MaterialSlot>.Release(validSlots);
ListPool<SerializableSlot>.Release(validSlots);
return;
}

}
nodeList.Add(node);
ListPool<MaterialSlot>.Release(validSlots);
ListPool<SerializableSlot>.Release(validSlots);
public static void CollectDependentNodes(ICollection<AbstractMaterialNode> nodeList, AbstractMaterialNode node)
public static void CollectDependentNodes(List<SerializableNode> nodeList, SerializableNode node)
{
if (node == null)
return;

13
UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs


public static string GeneratePreviewShader(AbstractMaterialNode node, out PreviewMode generatedShaderMode)
{
// figure out what kind of preview we want!
var activeNodeList = ListPool<AbstractMaterialNode>.Get();
var activeNodeList = ListPool<SerializableNode>.Get();
if (activeNodeList.Any(x => x.previewMode == PreviewMode.Preview3D))
if (activeNodeList.OfType<AbstractMaterialNode>().Any(x => x.previewMode == PreviewMode.Preview3D))
{
generationMode = GenerationMode.Preview3D;
generatedShaderMode = PreviewMode.Preview3D;

var shaderPropertyUsagesVisitor = new ShaderGenerator();
var vertexShaderBlock = new ShaderGenerator();
var shaderName = "Hidden/PreviewShader/" + node.GetOutputVariableNameForSlot(node.outputSlots.First(), generationMode);
var shaderName = "Hidden/PreviewShader/" + node.GetOutputVariableNameForSlot(node.materialOuputSlots.First(), generationMode);
foreach (var activeNode in activeNodeList)
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
{
if (activeNode is IGeneratesFunction)
(activeNode as IGeneratesFunction).GenerateNodeFunction(shaderFunctionVisitor, generationMode);

}
if (generationMode == GenerationMode.Preview2D)
shaderBodyVisitor.AddShaderChunk("return " + AdaptNodeOutputForPreview(node, node.outputSlots.First(), generationMode, ConcreteSlotValueType.Vector4) + ";", true);
shaderBodyVisitor.AddShaderChunk("return " + AdaptNodeOutputForPreview(node, node.materialOuputSlots.First(), generationMode, ConcreteSlotValueType.Vector4) + ";", true);
shaderBodyVisitor.AddShaderChunk("o.Emission = " + AdaptNodeOutputForPreview(node, node.outputSlots.First(), generationMode, ConcreteSlotValueType.Vector3) + ";", true);
shaderBodyVisitor.AddShaderChunk("o.Emission = " + AdaptNodeOutputForPreview(node, node.materialOuputSlots.First(), generationMode, ConcreteSlotValueType.Vector3) + ";", true);
template = template.Replace("${ShaderName}", shaderName);
template = template.Replace("${ShaderPropertiesHeader}", shaderPropertiesVisitor.GetShaderString(2));

9
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/GUIModificationType.cs


namespace UnityEditor.MaterialGraph
{
public enum GUIModificationType
{
None,
Repaint,
ModelChanged
}
}
正在加载...
取消
保存