浏览代码

[shader graph]Data refactor 4 (working kind of now)

/main
Tim Cooper 9 年前
当前提交
34db823b
共有 11 个文件被更改,包括 152 次插入185 次删除
  1. 104
      UnityProject/Assets/UnityShaderEditor/Editor/Source/BaseMaterialGraph.cs
  2. 4
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialGraphDataSource.cs
  3. 3
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialWindow.cs
  4. 4
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/NodeAnchor.cs
  5. 2
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/AddNode.cs
  6. 95
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs
  7. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function2Input.cs
  8. 29
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs
  9. 48
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PropertyNode.cs
  10. 38
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector4Node.cs
  11. 4
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs

104
UnityProject/Assets/UnityShaderEditor/Editor/Source/BaseMaterialGraph.cs


{
[SerializeField]
private List<Edge> m_Edges = new List<Edge>();
[SerializeField]
private List<BaseMaterialNode> m_Nodes = new List<BaseMaterialNode>();

if (inputSlot == null || outputSlot == null)
return null;
var edges = GetEdges(inputSlot).ToList();
foreach (var edge in GetEdges(inputSlot))
foreach (var edge in edges)
{
Debug.Log("Removing existing edge:" + edge);
// call base here as we DO NOT want to

public virtual void RevalidateGraph()
{
var bmns = m_Nodes.Where(x => x is BaseMaterialNode).Cast<BaseMaterialNode>().ToList();
//First validate edges, remove any
//orphans. This can happen if a user
//manually modifies serialized data
//of if they delete a node in the inspector
//debug view.
var allNodeGUIDs = m_Nodes.Select(x => x.guid).ToList();
foreach (var edge in edges.ToArray())
{
if (allNodeGUIDs.Contains(edge.inputSlot.nodeGuid) && allNodeGUIDs.Contains(edge.outputSlot.nodeGuid))
continue;
foreach (var node in bmns)
node.InvalidateNode();
//orphaned edge
m_Edges.Remove(edge);
}
var bmns = m_Nodes.Where(x => x is BaseMaterialNode).ToList();
foreach (var node in bmns)
node.ValidateNode();
}

RevalidateGraph();
}
private void AddNodeNoValidate(BaseMaterialNode node)
{
m_Nodes.Add(node);
}
private static string GetTypeSerializableAsString(Type type)
{
if (type == null)
return string.Empty;
return string.Format("{0}, {1}", type.FullName, type.Assembly.GetName().Name);
}
private static Type GetTypeFromSerializedString(string type)
{
if (string.IsNullOrEmpty(type))
return null;
return Type.GetType(type);
}
[Serializable]
struct SerializableNode
{
[SerializeField]
public string typeName;
[SerializeField]
public string JSONnodeData;
}
[SerializeField]
List<SerializableNode> m_SerializableNodes = new List<SerializableNode>();
m_SerializableNodes.Clear();
foreach (var node in nodes)
{
if (node == null)
continue;
var typeName = GetTypeSerializableAsString(node.GetType());
var data = JsonUtility.ToJson(node);
if (string.IsNullOrEmpty(typeName) || string.IsNullOrEmpty(data))
continue;
m_SerializableNodes.Add( new SerializableNode()
{
typeName = typeName,
JSONnodeData = data
});
}
foreach (var node in nodes)
m_Nodes.Clear();
foreach (var serializedNode in m_SerializableNodes)
node.owner = this;
if (string.IsNullOrEmpty(serializedNode.typeName) || string.IsNullOrEmpty(serializedNode.JSONnodeData))
continue;
var type = GetTypeFromSerializedString(serializedNode.typeName);
if (type == null)
{
Debug.LogWarningFormat("Could not find node of type {0} in loaded assemblies", serializedNode.typeName);
continue;
}
BaseMaterialNode node;
try
{
var constructorInfo = type.GetConstructor(new[] { typeof(BaseMaterialGraph) });
node = (BaseMaterialNode)constructorInfo.Invoke(new object[] { this });
}
catch
{
Debug.LogWarningFormat("Could not construct instance of: {0} as there is no single argument constuctor that takes a BaseMaterialGraph", type);
continue;
}
JsonUtility.FromJsonOverwrite(serializedNode.JSONnodeData, node);
AddNodeNoValidate(node);
RevalidateGraph();
}
}
}

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


//toReturn.Add(new FloatingPreview(new Rect(Screen.width - 300, Screen.height - 300, 300, 300), pixelGraph.nodes.FirstOrDefault(x => x is PixelShaderNode)));
Debug.LogFormat("Returning {0} nodes", toReturn.Count);
Debug.LogFormat("Returning {0} nodes", m_DrawableNodes.Count);
Debug.LogFormat("Returning {0} drawableEdges", drawableEdges.Count);
Debug.LogFormat("Returning {0} nullInputSlots", nullInputSlots.Count);
return toReturn.ToArray();
}

3
UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialWindow.cs


try
{
var constructorInfo = posObj.m_Type.GetConstructor(new[] {typeof(BaseMaterialGraph)});
if (constructorInfo != null)
node = (BaseMaterialNode)constructorInfo.Invoke(new object[] { m_MaterialGraph.currentGraph });
node = (BaseMaterialNode)constructorInfo.Invoke(new object[] { m_MaterialGraph.currentGraph });
}
catch
{

4
UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/NodeAnchor.cs


Rect labelRect;
if (m_Direction == Direction.Input)
{
text += " " + ConcreteSlotValueTypeAsString(m_Node.GetConcreteInputSlotValueType(m_Slot));
text += " " + ConcreteSlotValueTypeAsString(m_Slot.concreteValueType);
text += " " + ConcreteSlotValueTypeAsString(m_Node.GetConcreteOutputSlotValueType(m_Slot));
text += " " + ConcreteSlotValueTypeAsString(m_Slot.concreteValueType);
Vector2 sizeOfText = GUIStyle.none.CalcSize(new GUIContent(text));
labelRect = new Rect(translation.x - sizeOfText.x - 4.0f, translation.y, sizeOfText.x + 4.0f, sizeOfText.y + 4.0f);
}

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


using UnityEngine;
namespace UnityEditor.MaterialGraph
{
[Title("Math/Add Node")]

95
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs


namespace UnityEditor.MaterialGraph
{
//Can not be abstract as it needs to be serialzied #justunitythings
public class BaseMaterialNode : IGenerateProperties, ISerializationCallbackReceiver
public abstract class BaseMaterialNode : IGenerateProperties, ISerializationCallbackReceiver
{
[Serializable]
protected class NodeSpecificData

private const int kPreviewHeight = 64;
private static readonly Mesh[] s_Meshes = {null, null, null, null};
[SerializeField]
protected string m_JSONNodeSpecificData;
[SerializeField]
private DrawMode m_DrawMode = DrawMode.Full;

[SerializeField]
private string m_Name;
[NonSerialized]
private bool m_NodeNeedsValidation = true;
[SerializeField]
private Rect m_Position;

get { return kPreviewHeight; }
}
public bool nodeNeedsValidation
{
get { return m_NodeNeedsValidation; }
}
if (nodeNeedsValidation)
ValidateNode();
return m_HasError;
}
protected set

}
}
public ConcreteSlotValueType concreteValueForSlot
{
get
{
if (nodeNeedsValidation)
ValidateNode();
return m_ConcreteInputSlotValueTypes;
}
}
public Dictionary<string, ConcreteSlotValueType> concreteOutputSlotValueTypes
{
get
{
if (nodeNeedsValidation)
ValidateNode();
return m_ConcreteOutputSlotValueTypes;
}
}
public Rect position
{
get

if (edges.Any())
continue;
inputSlot.GeneratePropertyUsages(visitor, generationMode, concreteInputSlotValueTypes[inputSlot.name], this);
inputSlot.GeneratePropertyUsages(visitor, generationMode, inputSlot.concreteValueType, this);
//#justunitythings Serialization callbacks are not
// being called on overrides if serializing from
// base class ref. We are in mega hax town now.
protected virtual void DelegateOnBeforeSerialize()
{ }
protected virtual void DelegateOnAfterDeserialize()
{ }
public void OnBeforeSerialize()
public virtual void OnBeforeSerialize()
DelegateOnBeforeSerialize();
public void OnAfterDeserialize()
public virtual void OnAfterDeserialize()
DelegateOnAfterDeserialize();
}
public virtual float GetNodeUIHeight(float width)

var fromNode = owner.GetNodeFromGUID(fromSocketRef.nodeGuid);
var slot = fromNode.FindOutputSlot(fromSocketRef.slotName);
return ShaderGenerator.AdaptNodeOutput(this, slot, generationMode, concreteInputSlotValueTypes[inputSlot.name]);
return ShaderGenerator.AdaptNodeOutput(this, slot, generationMode, inputSlot.concreteValueType);
return inputSlot.GetDefaultValue(generationMode, concreteInputSlotValueTypes[inputSlot.name], this);
return inputSlot.GetDefaultValue(generationMode, inputSlot.concreteValueType, this);
}
public void RemoveSlotsNameNotMatching(string[] slotNames)

}
}
public ConcreteSlotValueType GetConcreteOutputSlotValueType(Slot slot)
{
if (concreteOutputSlotValueTypes.ContainsKey(slot.name))
return concreteOutputSlotValueTypes[slot.name];
return ConcreteSlotValueType.Error;
}
public ConcreteSlotValueType GetConcreteInputSlotValueType(Slot slot)
{
if (concreteInputSlotValueTypes.ContainsKey(slot.name))
return concreteInputSlotValueTypes[slot.name];
return ConcreteSlotValueType.Error;
}
private ConcreteSlotValueType FindCommonChannelType(ConcreteSlotValueType @from, ConcreteSlotValueType to)
{
if (ImplicitConversionExists(@from, to))

public void ValidateNode()
{
if (!nodeNeedsValidation)
return;
var isInError = false;
// all children nodes needs to be updated first

var outputSlotRef = edges[0].outputSlot;
var outputNode = owner.GetNodeFromGUID(outputSlotRef.nodeGuid);
var outputSlot = outputNode.FindOutputSlot(outputSlotRef.slotName);
var outputConcreteType = outputNode.GetConcreteOutputSlotValueType(outputSlot);
var outputConcreteType = outputSlot.concreteValueType;
// if we have a standard connection... just check the types work!
if (inputType != SlotValueType.Dynamic)

isInError |= inputError;
isInError |= outputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
isInError |= CalculateNodeHasError();
m_NodeNeedsValidation = false;
hasError = isInError;
if (!hasError)

public virtual bool DrawSlotDefaultInput(Rect rect, Slot inputSlot)
{
var inputSlotType = GetConcreteInputSlotValueType(inputSlot);
var inputSlotType = inputSlot.concreteValueType;
return inputSlot.OnGUI(rect, inputSlotType);
}

if (onNeedsRepaint != null)
onNeedsRepaint();
}
public void InvalidateNode()
{
m_NodeNeedsValidation = true;
}
// CollectDependentNodes looks at the current node and calculates
// which nodes further up the tree (parents) would be effected if this node was changed

return nodeList;
}
protected virtual bool UpdatePreviewShader()
{

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


public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(concreteOutputSlotValueTypes[GetOutputSlotName()]); }
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot(GetOutputSlotName()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(concreteInputSlotValueTypes[GetInputSlot1Name()]); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot(GetInputSlot1Name()).concreteValueType); }
get { return ConvertConcreteSlotValueTypeToString(concreteInputSlotValueTypes[GetInputSlot2Name()]); }
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot(GetInputSlot2Name()).concreteValueType); }
}
}
}

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


[Serializable]
public class PixelShaderNode : BaseMaterialNode, IGeneratesBodyCode
{
[Serializable]
class NodeSpecificData : BaseMaterialNode.NodeSpecificData
{
[SerializeField]
public string m_LightFunctionClassName;
}
private NodeSpecificData m_NodeSpecificData = new NodeSpecificData();
[SerializeField]
public string m_LightFunctionClassName;
get { return m_NodeSpecificData.m_LightFunctionClassName; }
set { m_NodeSpecificData.m_LightFunctionClassName = value; }
get { return m_LightFunctionClassName; }
set { m_LightFunctionClassName = value; }
public PixelShaderNode(PixelGraph owner)
public PixelShaderNode(BaseMaterialGraph owner)
GetLightFunction().DoSlotsForConfiguration(this);
GetLightFunction().DoSlotsForConfiguration(this);
}
protected override int previewWidth

m_GeneratedShaderMode = PreviewMode.Preview3D;
hasError = !InternalUpdatePreviewShader(resultShader);
return true;
}
protected override void DelegateOnBeforeSerialize()
{
m_JSONNodeSpecificData = JsonUtility.ToJson(m_NodeSpecificData);
}
protected override void DelegateOnAfterDeserialize()
{
if (!string.IsNullOrEmpty(m_JSONNodeSpecificData))
JsonUtility.FromJsonOverwrite(m_JSONNodeSpecificData, m_NodeSpecificData);
}
}
}

48
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PropertyNode.cs


{
public abstract class PropertyNode : BaseMaterialNode
{
protected class NodeSpecificData : BaseMaterialNode.NodeSpecificData
{
[SerializeField]
public string m_PropertyName;
[SerializeField]
public string m_Description;
[SerializeField]
public bool m_Exposed;
}
[SerializeField]
public string m_PropertyName;
protected void ApplyNodeSpecificData(NodeSpecificData data)
{
m_NodeSpecificData.m_PropertyName = data.m_PropertyName;
m_NodeSpecificData.m_Description = data.m_Description;
m_NodeSpecificData.m_Exposed = data.m_Exposed;
}
[SerializeField]
public string m_Description;
private NodeSpecificData m_NodeSpecificData = new NodeSpecificData();
[SerializeField]
public bool m_Exposed;
public PropertyNode(BaseMaterialGraph owner) : base(owner)
{}

get { return m_NodeSpecificData.m_Exposed; }
get { return m_Exposed; }
}
public string description

if (string.IsNullOrEmpty(m_NodeSpecificData.m_Description))
if (string.IsNullOrEmpty(m_Description))
return m_NodeSpecificData.m_Description;
return m_Description;
set { m_NodeSpecificData.m_Description = value; }
set { m_Description = value; }
}
public virtual string propertyName

if (!exposed || string.IsNullOrEmpty(m_NodeSpecificData.m_PropertyName))
if (!exposed || string.IsNullOrEmpty(m_PropertyName))
return m_NodeSpecificData.m_PropertyName + "_Uniform";
return m_PropertyName + "_Uniform";
set { m_NodeSpecificData.m_PropertyName = value; }
set { m_PropertyName = value; }
}
public abstract PropertyType propertyType { get; }

public override bool OnGUI()
{
EditorGUI.BeginChangeCheck();
m_NodeSpecificData.m_Exposed = EditorGUILayout.Toggle("Exposed Property", m_NodeSpecificData.m_Exposed);
if (m_NodeSpecificData.m_Exposed)
m_NodeSpecificData.m_PropertyName = EditorGUILayout.DelayedTextField("Property Name", m_NodeSpecificData.m_PropertyName);
m_Exposed = EditorGUILayout.Toggle("Exposed Property", m_Exposed);
if (m_Exposed)
m_PropertyName = EditorGUILayout.DelayedTextField("Property Name", m_PropertyName);
var modified = EditorGUI.EndChangeCheck();
if (modified)

if (m_NodeSpecificData.m_Exposed)
m_NodeSpecificData.m_Description = EditorGUILayout.TextField("Description", m_NodeSpecificData.m_Description);
if (m_Exposed)
m_Description = EditorGUILayout.TextField("Description", m_Description);
modified |= base.OnGUI();
return modified;

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


[Title("Input/Vector 4 Node")]
class Vector4Node : PropertyNode, IGeneratesBodyCode
{
protected class NodeSpecificData : PropertyNode.NodeSpecificData
{
[SerializeField]
public Vector4 m_Value;
}
protected void ApplyNodeSpecificData(NodeSpecificData data)
{
base.ApplyNodeSpecificData(data);
m_NodeSpecificData.m_Value = data.m_Value;
}
protected override void DelegateOnBeforeSerialize()
{
m_JSONNodeSpecificData = JsonUtility.ToJson(m_NodeSpecificData);
}
protected override void DelegateOnAfterDeserialize()
{
if (string.IsNullOrEmpty(m_JSONNodeSpecificData))
return;
var data = JsonUtility.FromJson<NodeSpecificData>(m_JSONNodeSpecificData);
ApplyNodeSpecificData(data);
InternalValidate();
}
[SerializeField]
public Vector4 m_Value;
private void InternalValidate()
{
AddSlot(new Slot(guid, kOutputSlotName, kOutputSlotName, Slot.SlotType.Output, SlotValueType.Vector4, Vector4.zero));

public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
if (exposed)
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_NodeSpecificData.m_Value, false));
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, false));
}
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode, ConcreteSlotValueType valueType)

if (exposed || generationMode.IsPreview())
return;
visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_NodeSpecificData.m_Value.x + ", " + m_NodeSpecificData.m_Value.y + ", " + m_NodeSpecificData.m_Value.z + ", " + m_NodeSpecificData.m_Value.w + ");", true);
visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_Value.x + ", " + m_Value.y + ", " + m_Value.z + ", " + m_Value.w + ");", true);
}
public override GUIModificationType NodeUI(Rect drawArea)

EditorGUI.BeginChangeCheck();
m_NodeSpecificData.m_Value = EditorGUI.Vector4Field(new Rect(drawArea.x, drawArea.y, drawArea.width, EditorGUIUtility.singleLineHeight), "Value", m_NodeSpecificData.m_Value);
m_Value = EditorGUI.Vector4Field(new Rect(drawArea.x, drawArea.y, drawArea.width, EditorGUIUtility.singleLineHeight), "Value", m_Value);
if (EditorGUI.EndChangeCheck())
return GUIModificationType.Repaint;
return GUIModificationType.None;

{
m_Name = propertyName,
m_PropType = PropertyType.Vector4,
m_Vector4 = m_NodeSpecificData.m_Value
m_Vector4 = m_Value
};
}
}

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


if (outputSlot == null)
return kErrorString;
var convertFromType = node.GetConcreteOutputSlotValueType(outputSlot);
var convertFromType = outputSlot.concreteValueType;
var rawOutput = node.GetOutputVariableNameForSlot(outputSlot, mode);
if (convertFromType == convertToType)
return rawOutput;

if (outputSlot == null)
return kErrorString;
var convertFromType = node.GetConcreteOutputSlotValueType(outputSlot);
var convertFromType = outputSlot.concreteValueType;
// if we are in a normal situation, just convert!
if (convertFromType >= convertToType || convertFromType == ConcreteSlotValueType.Vector1)

正在加载...
取消
保存