浏览代码

[Material graph]Tidy up node remapper. It now does not emit nodes but passes through.

/main
Tim Cooper 8 年前
当前提交
c11fe3b4
共有 12 个文件被更改,包括 114 次插入306 次删除
  1. 8
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/UnitTests/SerializedGraphTests.cs
  2. 30
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/NodeUtils.cs
  3. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IMasterNode.cs
  4. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/AbstractMasterNode.cs
  5. 7
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/PropertyNode.cs
  6. 25
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/MasterRemapGraph.cs
  7. 133
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/MasterRemapInputNode.cs
  8. 1
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/MaterialRemapAsset.cs
  9. 169
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/RemapMasterNode.cs
  10. 10
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraph.cs
  11. 7
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphNode.cs
  12. 26
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SurfaceModel/AbstractSurfaceMasterNode.cs

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


Assert.AreEqual(3, result.Count);
result.Clear();
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input0);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input1);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input0, NodeUtils.IncludeSelf.Exclude);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, NodeUtils.IncludeSelf.Exclude);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, TestableNode.Input1, NodeUtils.IncludeSelf.Exclude);
NodeUtils.DepthFirstCollectNodesFromNode(result, inputNode, NodeUtils.IncludeSelf.Exclude);
Assert.AreEqual(0, result.Count);
result.Clear();

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


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

Exclude
}
public static void DepthFirstCollectNodesFromNode(List<INode> nodeList, INode node, int? slotId = null, IncludeSelf includeSelf = IncludeSelf.Include)
{
DepthFirstCollectNodesFromNodeSlotList(nodeList, node, slotId.HasValue ? new List<int>() { slotId.Value } : null, includeSelf);
}
public static void DepthFirstCollectNodesFromNodeSlotList(List<INode> nodeList, INode node, List<int> slotId = null, IncludeSelf includeSelf = IncludeSelf.Include)
public static void DepthFirstCollectNodesFromNode(List<INode> nodeList, INode node, IncludeSelf includeSelf = IncludeSelf.Include)
// allready added this node
// already added this node
// if we have a slot passed in but can not find it on the node abort
if (slotId != null && node.GetInputSlots<ISlot>().All(x => !slotId.Contains(x.id)))
var remapper = node as INodeGroupRemapper;
if (remapper != null)
{
remapper.DepthFirstCollectNodesFromNodeSlotList(nodeList, includeSelf);
var validSlots = ListPool<int>.Get();
if (slotId != null)
slotId.ForEach(x => validSlots.Add(x));
else
validSlots.AddRange(node.GetInputSlots<ISlot>().Select(x => x.id));
foreach (var slot in validSlots)
}
foreach (var slot in node.GetInputSlots<ISlot>().Select(x => x.id))
DepthFirstCollectNodesFromNodeSlotList(nodeList, outputNode);
DepthFirstCollectNodesFromNode(nodeList, outputNode);
ListPool<int>.Release(validSlots);
}
public static void CollectNodesNodeFeedsInto(List<INode> nodeList, INode node, IncludeSelf includeSelf = IncludeSelf.Include)

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IMasterNode.cs


GenerationMode mode,
out List<PropertyGenerator.TextureInfo> configuredTextures);
string GetSubShader(GenerationMode mode);
string GetSubShader(GenerationMode mode, PropertyGenerator shaderPropertiesVisitor);
string GetVariableNameForNode();
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/AbstractMasterNode.cs


}
public abstract string GetFullShader(GenerationMode mode, out List<PropertyGenerator.TextureInfo> configuredTextures);
public abstract string GetSubShader(GenerationMode mode);
public abstract string GetSubShader(GenerationMode mode, PropertyGenerator shaderPropertiesVisitor);
}
}

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


[SerializeField]
private ExposedState m_Exposed = ExposedState.NotExposed;
public override bool allowedInRemapGraph
{
get { return false; }
}
public ExposedState exposedState
{
get

25
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/MasterRemapGraph.cs


namespace UnityEngine.MaterialGraph
{
public interface INodeGroupRemapper
{
void DepthFirstCollectNodesFromNodeSlotList(List<INode> nodeList, NodeUtils.IncludeSelf includeSelf);
bool IsValidSlotConnection(int id);
}
[Serializable]
public class MasterRemapGraph : AbstractMaterialGraph
{

return;
}
if (node is AbstractMaterialNode)
var materialNode = node as AbstractMaterialNode;
if (materialNode != null)
var amn = (AbstractMaterialNode) node;
var amn = materialNode;
{
return;
}
}
base.AddNode(node);
}

}
}
public List<string> GetSubShadersFor(RemapMasterNode rmn, GenerationMode mode)
public List<string> GetSubShadersFor(RemapMasterNode rmn, GenerationMode mode, PropertyGenerator shaderPropertiesVisitor)
{
var subShaders = new List<string>();
try

foreach (var node in GetNodes<IMasterNode>())
subShaders.Add(node.GetSubShader(mode));
subShaders.Add(node.GetSubShader(mode, shaderPropertiesVisitor));
}
}
catch (Exception e)

return subShaders;
}
public void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
foreach (var node in GetNodes<AbstractMaterialNode>())
node.CollectPreviewMaterialProperties(properties);
}
}
}

133
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/MasterRemapInputNode.cs


{
[Title("Remapper/Remap Input Node")]
public class MasterRemapInputNode : AbstractSubGraphIONode
, IGeneratesBodyCode
, IGeneratesFunction
, IMayRequireNormal
, IMayRequireTangent
, IMayRequireBitangent
, IMayRequireMeshUV
, IMayRequireScreenPosition
, IMayRequireViewDirection
, IMayRequireWorldPosition
, IMayRequireVertexColor
, INodeGroupRemapper
{
[NonSerialized]
internal RemapMasterNode m_RemapTarget;

{
onModified(this, ModificationScope.Graph);
}
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
public void DepthFirstCollectNodesFromNodeSlotList(List<INode> nodeList, NodeUtils.IncludeSelf includeSelf)
base.CollectPreviewMaterialProperties(properties);
foreach (var slot in GetOutputSlots<MaterialSlot>())
{
properties.Add(
new PreviewProperty
{
m_Name = GetVariableNameForSlot(slot.id),
m_PropType = PropertyType.Vector4,
m_Vector4 = slot.defaultValue
}
);
}
NodeUtils.DepthFirstCollectNodesFromNode(nodeList, m_RemapTarget, NodeUtils.IncludeSelf.Exclude);
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
if (m_RemapTarget != null)
m_RemapTarget.GenerateNodeCode(visitor, generationMode);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
if (m_RemapTarget != null)
m_RemapTarget.GenerateNodeFunction(visitor, generationMode);
}
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
if (m_RemapTarget != null)
m_RemapTarget.GeneratePropertyBlock(visitor, generationMode);
}
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (m_RemapTarget == null)
{
foreach (var slot in GetOutputSlots<MaterialSlot>())
{
var outDimension = ConvertConcreteSlotValueTypeToString(slot.concreteValueType);
visitor.AddShaderChunk("float" + outDimension + " " + GetVariableNameForSlot(slot.id) + ";", true);
}
}
else
{
if (m_RemapTarget != null)
m_RemapTarget.GeneratePropertyUsages(visitor, generationMode);
}
}
public bool RequiresNormal()
public bool IsValidSlotConnection(int slotId)
return m_RemapTarget.RequiresNormal();
}
public bool RequiresTangent()
{
if (m_RemapTarget == null)
var slot = m_RemapTarget.FindSlot<MaterialSlot>(slotId);
if (slot == null)
return m_RemapTarget.RequiresTangent();
}
public bool RequiresBitangent()
{
if (m_RemapTarget == null)
var edge = m_RemapTarget.owner.GetEdges(slot.slotReference).FirstOrDefault();
if (edge == null)
return m_RemapTarget.RequiresBitangent();
}
public bool RequiresMeshUV()
{
if (m_RemapTarget == null)
var outputRef = edge.outputSlot;
var fromNode = m_RemapTarget.owner.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
if (fromNode == null)
return m_RemapTarget.RequiresMeshUV();
return true;
public bool RequiresScreenPosition()
public override string GetVariableNameForSlot(int slotId)
return false;
return m_RemapTarget.RequiresScreenPosition();
}
{
var defaultValueSlot = FindSlot<MaterialSlot>(slotId);
if (defaultValueSlot == null)
throw new ArgumentException(string.Format("Attempting to use MaterialSlot({0}) on node of type {1} where this slot can not be found", slotId, this), "slotId");
public bool RequiresViewDirection()
{
if (m_RemapTarget == null)
return false;
return defaultValueSlot.GetDefaultValue(GenerationMode.ForReals);
}
return m_RemapTarget.RequiresViewDirection();
}
var slot = m_RemapTarget.FindSlot<MaterialSlot>(slotId);
if (slot == null)
throw new ArgumentException(string.Format("Attempting to use MaterialSlot({0}) on node of type {1} where this slot can not be found", slotId, this), "slotId");
public bool RequiresWorldPosition()
{
if (m_RemapTarget == null)
return false;
if (slot.isOutputSlot)
throw new Exception(string.Format("Attempting to use OutputSlot({0}) on remap node)", slotId));
return m_RemapTarget.RequiresWorldPosition();
}
var edge = m_RemapTarget.owner.GetEdges(slot.slotReference).FirstOrDefault();
if (edge == null)
return slot.GetDefaultValue(GenerationMode.ForReals);
public bool RequiresVertexColor()
{
if (m_RemapTarget == null)
return false;
var outputRef = edge.outputSlot;
var fromNode = m_RemapTarget.owner.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
if (fromNode == null)
return slot.GetDefaultValue(GenerationMode.ForReals);
return m_RemapTarget.RequiresVertexColor();
return fromNode.GetVariableNameForSlot(outputRef.slotId);
}
}
}

1
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/MaterialRemapAsset.cs


using System.Collections.Generic;
using System.Linq;
using UnityEngine.Graphing;

169
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Remapper/RemapMasterNode.cs


[Serializable]
[Title("Master/Remapper")]
public class RemapMasterNode : AbstractMasterNode
, IGeneratesBodyCode
, IGeneratesFunction
, IMayRequireNormal
, IMayRequireTangent
, IMayRequireBitangent
, IMayRequireMeshUV
, IMayRequireScreenPosition
, IMayRequireViewDirection
, IMayRequireWorldPosition
, IMayRequireVertexColor
{
[SerializeField]
private string m_SerialziedRemapGraph = string.Empty;

return string.Empty;
}
// Step 1: Generate properties from this node
// remap graphs are not allowed to have subgraphs
// or property nodes, so this is okay :)
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this);
foreach (var node in activeNodeList.OfType<AbstractMaterialNode>())
node.GeneratePropertyBlock(shaderPropertiesVisitor, mode);
// Step 2: Set this node as the remap target
var subShaders = remapAsset.masterRemapGraph.GetSubShadersFor(this, mode);
// Step 1: Set this node as the remap target
// Pass in the shader properties visitor here as
// high level properties are shared
// this is only used for the header
var subShaders = remapAsset.masterRemapGraph.GetSubShadersFor(this, mode, shaderPropertiesVisitor);
resultShader = resultShader.Replace("${SubShader}", subShaders.Aggregate((i, j) => i + Environment.NewLine + j));
if (subShaders != null)
resultShader = resultShader.Replace("${SubShader}", subShaders.Aggregate(string.Empty, (i, j) => i + Environment.NewLine + j));
else
resultShader = resultShader.Replace("${SubShader}", string.Empty);
public override string GetSubShader(GenerationMode mode)
public override string GetSubShader(GenerationMode mode, PropertyGenerator shaderPropertiesVisitor)
}
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
base.CollectPreviewMaterialProperties(properties);
if (remapAsset == null)
return;
remapAsset.masterRemapGraph.CollectPreviewMaterialProperties(properties);
}
#if UNITY_EDITOR

#else
public MaterialSubGraphAsset subGraphAsset {get; set; }
#endif
private MasterRemapGraph masterRemapGraph
{
get
{
if (remapAsset == null)
return null;
return remapAsset.masterRemapGraph;
}
}
public override PreviewMode previewMode
{

validNames.Add(slot.id);
}
RemoveSlotsNameNotMatching(validNames);
}
public void GenerateNodeCode(ShaderGenerator shaderBody, GenerationMode generationMode)
{
var nodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(nodes, this, null, NodeUtils.IncludeSelf.Exclude);
for (var i = 0; i < nodes.Count; i++)
{
var node = nodes[i];
if (node is IGeneratesBodyCode)
(node as IGeneratesBodyCode).GenerateNodeCode(shaderBody, generationMode);
}
ListPool<INode>.Release(nodes);
if (remapAsset == null)
return;
var inputNode = remapAsset.masterRemapGraph.inputNode;
foreach (var mappedSlot in inputNode.GetOutputSlots<MaterialSlot>())
{
var edge = owner.GetEdges(new SlotReference(guid, mappedSlot.id)).FirstOrDefault();
if (edge != null)
{
var outputRef = edge.outputSlot;
var fromNode = owner.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
if (fromNode == null)
continue;
shaderBody.AddShaderChunk("float4 " + inputNode.GetVariableNameForSlot(mappedSlot.id) + " = " + fromNode.GetVariableNameForSlot(outputRef.slotId) + ";", true);
}
else
{
shaderBody.AddShaderChunk("float4 " + inputNode.GetVariableNameForSlot(mappedSlot.id) + " = " + inputNode.FindSlot<MaterialSlot>(mappedSlot.id).GetDefaultValue(GenerationMode.ForReals) + ";", true);
}
}
}
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
foreach (var node in activeNodeList.OfType<IGenerateProperties>())
node.GeneratePropertyBlock(visitor, generationMode);
}
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
foreach (var node in activeNodeList.OfType<IGenerateProperties>())
node.GeneratePropertyUsages(visitor, generationMode);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
foreach (var node in activeNodeList.OfType<IGeneratesFunction>())
node.GenerateNodeFunction(visitor, generationMode);
}
public bool RequiresNormal()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireNormal>().Any(x => x.RequiresNormal());
}
public bool RequiresTangent()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireTangent>().Any(x => x.RequiresTangent());
}
public bool RequiresBitangent()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireBitangent>().Any(x => x.RequiresBitangent());
}
public bool RequiresMeshUV()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireMeshUV>().Any(x => x.RequiresMeshUV());
}
public bool RequiresScreenPosition()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition());
}
public bool RequiresViewDirection()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireViewDirection>().Any(x => x.RequiresViewDirection());
}
public bool RequiresWorldPosition()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireWorldPosition>().Any(x => x.RequiresWorldPosition());
}
public bool RequiresVertexColor()
{
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this, null, NodeUtils.IncludeSelf.Exclude);
return activeNodeList.OfType<IMayRequireVertexColor>().Any(x => x.RequiresVertexColor());
}
}
}

10
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraph.cs


return;
}
if (node is AbstractMaterialNode)
var materialNode = node as AbstractMaterialNode;
if (materialNode != null)
var amn = (AbstractMaterialNode)node;
var amn = materialNode;
{
return;
}
}
base.AddNode(node);
}

{
var nodes = new List<INode>();
//Get the rest of the nodes for all the other slots
NodeUtils.DepthFirstCollectNodesFromNode(nodes, outputNode, null, NodeUtils.IncludeSelf.Exclude);
NodeUtils.DepthFirstCollectNodesFromNode(nodes, outputNode, NodeUtils.IncludeSelf.Exclude);
return nodes.OfType<AbstractMaterialNode>();
}
}

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


onModified(this, ModificationScope.Graph);
}
}
public override bool allowedInRemapGraph
{
get { return false; }
}
/*
// SAVED FOR LATER
if (serializedVersion<kCurrentSerializedVersion)

26
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SurfaceModel/AbstractSurfaceMasterNode.cs


public abstract string GetSurfaceOutputName();
public abstract string GetLightFunction();
public override string GetSubShader(GenerationMode mode)
public override string GetSubShader(GenerationMode mode, PropertyGenerator shaderPropertiesVisitor)
var templateText = File.ReadAllText(templateLocation);
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this);
foreach (var node in activeNodeList.OfType<AbstractMaterialNode>())
node.GeneratePropertyBlock(shaderPropertiesVisitor, mode);
var templateText = File.ReadAllText(templateLocation);
var shaderBodyVisitor = new ShaderGenerator();
var shaderFunctionVisitor = new ShaderGenerator();
var shaderPropertyUsagesVisitor = new ShaderGenerator();

}
var templateText = File.ReadAllText(templateLocation);
var activeNodeList = new List<INode>();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this);
foreach (var node in activeNodeList.OfType<AbstractMaterialNode>())
node.GeneratePropertyBlock(shaderPropertiesVisitor, mode);
resultShader = resultShader.Replace("${SubShader}", GetSubShader(mode, shaderPropertiesVisitor));
resultShader = resultShader.Replace("${SubShader}", GetSubShader(mode));
configuredTextures = shaderPropertiesVisitor.GetConfiguredTexutres();
return Regex.Replace(resultShader, @"\r\n|\n\r|\n|\r", Environment.NewLine);
}

var nodes = ListPool<INode>.Get();
//Get the rest of the nodes for all the other slots
NodeUtils.DepthFirstCollectNodesFromNode(nodes, this, null, NodeUtils.IncludeSelf.Exclude);
NodeUtils.DepthFirstCollectNodesFromNode(nodes, this, NodeUtils.IncludeSelf.Exclude);
for (var i = 0; i < nodes.Count; i++)
{
var node = nodes[i];

var outputRef = edge.outputSlot;
var fromNode = owner.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
if (fromNode == null)
continue;
var remapper = fromNode as INodeGroupRemapper;
if (remapper != null && !remapper.IsValidSlotConnection(outputRef.slotId))
continue;
shaderBody.AddShaderChunk("o." + slot.shaderOutputName + " = " + fromNode.GetVariableNameForSlot(outputRef.slotId) + ";", true);

正在加载...
取消
保存