浏览代码

Add drawing of custom node preview

Delegate drawing to a custom drawer class that is looked up via
attribute, it will search for most specific drawer first, then walk up
the inheritence chain.
/main
Tim Cooper 9 年前
当前提交
a2d8ad62
共有 27 个文件被更改,包括 479 次插入379 次删除
  1. 7
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/DrawableNode.cs
  2. 79
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphDataSource.cs
  3. 3
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs
  4. 10
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/GUIModificationType.cs
  5. 8
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableGraph.cs
  6. 5
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableNode.cs
  7. 9
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/DrawingData.cs
  8. 1
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/IGraph.cs
  9. 2
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/INode.cs
  10. 83
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Editors/MaterialGraphEditor.cs
  11. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/AbstractMaterialGraphTests.cs
  12. 23
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/AbstractMaterialGraph.cs
  13. 264
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/AbstractMaterialNode.cs
  14. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Function2Input.cs
  15. 11
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/MaterialSlot.cs
  16. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/PixelShaderNode.cs
  17. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/PropertyNode.cs
  18. 38
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Vector4Node.cs
  19. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Util/ShaderGenerator.cs
  20. 6
      .gitignore
  21. 9
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers.meta
  22. 201
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/BaseMaterialNodeUI.cs
  23. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/BaseMaterialNodeUI.cs.meta
  24. 41
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector4NodeUI.cs
  25. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector4NodeUI.cs.meta
  26. 5
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Util.meta

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


{
public interface ICustomNodeUi
{
int GetNodeUiHeight(int width);
float GetNodeUiHeight(float width);
void SetNode(INode node);
private readonly Rect m_CustomUiRect;
public readonly INode m_Node;
private readonly ICustomNodeUi m_Ui;

const int width = 200;
var drawData = node.drawState;
translation = drawData.position.min;
scale = new Vector2(width, width);
scale = new Vector2(drawData.width, drawData.width);
m_Node = node;
m_Ui = ui;

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


using System;
using System.Reflection;
using UnityEngineInternal;
[AttributeUsage(AttributeTargets.Class)]
sealed class CustomNodeUI : Attribute
{
private Type m_ModeToDrawFor ;
public CustomNodeUI(Type nodeToDrawFor)
{
m_ModeToDrawFor = nodeToDrawFor;
}
public Type nodeToDrawFor
{
get { return m_ModeToDrawFor; } }
}
public class GraphDataSource : ICanvasDataSource
{
readonly List<DrawableNode> m_DrawableNodes = new List<DrawableNode>();

get { return m_DrawableNodes; }
}
private static Type[] GetTypesFromAssembly(Assembly assembly)
{
if (assembly == null)
return new Type[] {};
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException)
{
return new Type[] {};
}
}
private static Dictionary<Type, Type> s_DrawerUI;
private static Dictionary<Type, Type> drawerUI
{
get
{
if (s_DrawerUI == null)
{
s_DrawerUI = new Dictionary<Type, Type>();
var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => GetTypesFromAssembly(x));
foreach (var type in loadedTypes)
{
var attribute = type.GetCustomAttributes(true).OfType<CustomNodeUI>().FirstOrDefault();
if (attribute != null && typeof(ICustomNodeUi).IsAssignableFrom(type))
s_DrawerUI.Add(attribute.nodeToDrawFor, type);
}
}
return s_DrawerUI;
}
}
public CanvasElement[] FetchElements()
{
m_DrawableNodes.Clear();

var nodeType = node.GetType();
Type draweruiType = null;
while (draweruiType == null && nodeType != null)
{
draweruiType = drawerUI.FirstOrDefault(x => x.Key == nodeType).Value;
nodeType = nodeType.BaseType;
}
ICustomNodeUi customUI = null;
if (draweruiType != null)
{
try
{
customUI = Activator.CreateInstance(draweruiType) as ICustomNodeUi;
customUI.SetNode(node);
}
catch (Exception e)
{
Debug.LogWarningFormat("Could not construct instance of: {0} - {1}", draweruiType, e);
}
}
m_DrawableNodes.Add(new DrawableNode(node, null, this));
m_DrawableNodes.Add(new DrawableNode(node, customUI, this));
}
// Add the edges now

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


using System;
using System.Reflection;
using UnityEditor.Experimental;
using UnityEditor.MaterialGraph;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;

GUILayout.FlexibleSpace();
EditorGUILayout.BeginVertical();
m_ScrollPos = GUILayout.BeginScrollView(m_ScrollPos, EditorStyles.textArea, GUILayout.Width(250), GUILayout.ExpandHeight(true));
m_ScrollPos = GUILayout.BeginScrollView(m_ScrollPos, EditorStyles.textArea, GUILayout.width(250), GUILayout.ExpandHeight(true));
graph.materialOptions.DoGUI();
EditorGUILayout.Separator();

10
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/GUIModificationType.cs


using System;
[Flags]
None,
Repaint,
ModelChanged
None = 0,
Repaint = 1 << 0,
ModelChanged = 1 << 1,
DataChanged = 1 << 2
}
}

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


return m_Nodes.FirstOrDefault(x => x.guid == guid);
}
public T GetNodeFromGuid<T>(Guid guid) where T : INode
{
return m_Nodes.Where(x => x.guid == guid).OfType<T>().FirstOrDefault();
}
public IEnumerable<IEdge> GetEdges(SlotReference s)
{
if (s == null)

//orphaned edge
RemoveEdgeNoValidate(edge);
}
foreach (var node in nodes)
node.ValidateNode();
}
}
}

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


set { m_DrawData = value; }
}
public virtual bool hasError { get; set; }
public virtual void ValidateNode()
{}
public IEnumerable<ISlot> inputSlots
{
get { return m_Slots.Where(x => x.isInputSlot); }

public SerializableNode(IGraph theOwner)
{
m_DrawData.expanded = true;
m_DrawData.width = 200;
owner = theOwner;
m_Guid = Guid.NewGuid();
}

9
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/DrawingData.cs


[SerializeField]
private Rect m_Position;
[SerializeField]
private int m_Width;
public bool expanded
{
get { return m_Expanded; }

{
get { return m_Position; }
set { m_Position = value; }
}
public int width
{
get { return m_Width; }
set { m_Width = value; }
}
}
}

1
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/IGraph.cs


void RemoveEdge(IEdge e);
void RemoveElements(IEnumerable<INode> nodes, IEnumerable<IEdge> edges);
INode GetNodeFromGuid(Guid guid);
T GetNodeFromGuid<T>(Guid guid) where T : INode;
IEnumerable<IEdge> GetEdges(SlotReference s);
void ValidateGraph();
}

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


ISlot FindOutputSlot(string name);
IEnumerable<ISlot> GetInputsWithNoConnection();
DrawingData drawState { get; set; }
bool hasError { get; }
void ValidateNode();
}
}

83
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Editors/MaterialGraphEditor.cs


namespace UnityEditor.MaterialGraph
{
[CustomEditor(typeof (MaterialGraphAsset), true)]
internal class MaterialGraphEditor : Editor
internal class MaterialGraphPreviewGenerator
{
private PreviewRenderUtility m_PreviewUtility;
private static readonly Mesh[] s_Meshes = {null, null, null, null, null};

private static readonly GUIContent[] s_TimeIcons = {null, null};
public override bool HasPreviewGUI()
{
return false;
}
private void Init()
public MaterialGraphPreviewGenerator()
{
if (m_PreviewUtility == null)
{

}
}
public override void OnPreviewGUI(Rect r, GUIStyle background)
public Texture DoRenderPreview(Material mat, PreviewMode mode, Rect size)
if (mat == null || mat.shader == null)
return Texture2D.blackTexture;
if (!ShaderUtil.hardwareSupportsRectRenderTexture)
m_PreviewUtility.BeginPreview(size, GUIStyle.none);
if (mode == PreviewMode.Preview3D)
if (Event.current.type == EventType.Repaint)
EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "Material preview \nnot available");
return;
m_PreviewUtility.m_Camera.transform.position = -Vector3.forward * 5;
m_PreviewUtility.m_Camera.transform.rotation = Quaternion.identity;
EditorUtility.SetCameraAnimateMaterialsTime(m_PreviewUtility.m_Camera, Time.realtimeSinceStartup);
var amb = new Color(.2f, .2f, .2f, 0);
m_PreviewUtility.m_Light[0].intensity = 1.0f;
m_PreviewUtility.m_Light[0].transform.rotation = Quaternion.Euler(50f, 50f, 0);
m_PreviewUtility.m_Light[1].intensity = 1.0f;
InternalEditorUtility.SetCustomLighting(m_PreviewUtility.m_Light, amb);
m_PreviewUtility.DrawMesh(s_Meshes[0], Vector3.zero, Quaternion.Euler(-20, 0, 0) * Quaternion.Euler(0, 0, 0), mat, 0);
var oldFog = RenderSettings.fog;
Unsupported.SetRenderSettingsUseFogNoDirty(false);
m_PreviewUtility.m_Camera.Render();
Unsupported.SetRenderSettingsUseFogNoDirty(oldFog);
InternalEditorUtility.RemoveCustomLighting();
Init();
if (Event.current.type != EventType.Repaint)
return;
m_PreviewUtility.BeginPreview(r, background);
DoRenderPreview();
m_PreviewUtility.EndAndDrawPreview(r);
}
private void DoRenderPreview()
{
var materialGraph = target as MaterialGraphAsset;
if (materialGraph == null)
return;
m_PreviewUtility.m_Camera.transform.position = -Vector3.forward * 5;
m_PreviewUtility.m_Camera.transform.rotation = Quaternion.identity;
m_PreviewUtility.m_Light[0].intensity = 1.0f;
m_PreviewUtility.m_Light[0].transform.rotation = Quaternion.Euler(50f, 50f, 0);
m_PreviewUtility.m_Light[1].intensity = 1.0f;
var amb = new Color(.2f, .2f, .2f, 0);
InternalEditorUtility.SetCustomLighting(m_PreviewUtility.m_Light, amb);
Quaternion rot = Quaternion.identity;
Mesh mesh = s_Meshes[0];
// We need to rotate camera, so we can see different reflections from different angles
// If we would only rotate object, the reflections would stay the same
m_PreviewUtility.m_Camera.transform.position = Quaternion.Inverse(rot) * m_PreviewUtility.m_Camera.transform.position;
m_PreviewUtility.m_Camera.transform.LookAt(Vector3.zero);
rot = Quaternion.identity;
m_PreviewUtility.DrawMesh(mesh, Vector3.zero, rot, materialGraph.GetMaterial(), 0);
bool oldFog = RenderSettings.fog;
Unsupported.SetRenderSettingsUseFogNoDirty(false);
m_PreviewUtility.m_Camera.Render();
Unsupported.SetRenderSettingsUseFogNoDirty(oldFog);
InternalEditorUtility.RemoveCustomLighting();
else
{
EditorUtility.UpdateGlobalShaderProperties(Time.realtimeSinceStartup);
Graphics.Blit(null, mat);
}
return m_PreviewUtility.EndPreview();
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/AbstractMaterialGraphTests.cs


Assert.AreEqual(0, graph.edges.Count());
Assert.AreEqual(1, graph.nodes.Count());
Assert.AreEqual(node, graph.GetMaterialNodeFromGuid(node.guid));
Assert.AreEqual(node, graph.GetNodeFromGuid(node.guid));
Assert.AreEqual(node, graph.GetNodeFromGuid<TestableMNode>(node.guid));
}
[Test]

23
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/AbstractMaterialGraph.cs


}
}
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();
foreach (var node in materialNodes)
node.ValidateNode();
}
/*public PreviewRenderUtility previewUtility
{
get

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


[Serializable]
public abstract class AbstractMaterialNode : SerializableNode, IGenerateProperties
{
/*private static readonly Mesh[] s_Meshes = {null, null, null, null};
protected PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;*/
/*[SerializeField]
private string m_LastShader;
[NonSerialized]
private Material m_PreviewMaterial;
[NonSerialized]
private Shader m_PreviewShader;*/
public AbstractMaterialGraph materialGraphOwner
{
get
{
return owner as AbstractMaterialGraph;;
}
}
public string precision
{
get { return "half"; }

get { return true; }
}
/* public Material previewMaterial
{
get
{
if (m_PreviewMaterial == null)
{
m_PreviewMaterial = new Material(m_PreviewShader) {hideFlags = HideFlags.HideInHierarchy};
m_PreviewMaterial.hideFlags = HideFlags.HideInHierarchy;
}
return m_PreviewMaterial;
}
}
*/
public bool hasError
{
get { return m_HasError; }

}
protected AbstractMaterialNode(IGraph theOwner) : base(theOwner)
{ }
{
version = 0;
}
public virtual void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{}

}
}
/*
protected virtual void OnPreviewGUI()
{
if (!ShaderUtil.hardwareSupportsRectRenderTexture)
return;
GUILayout.BeginHorizontal(GUILayout.MinWidth(previewWidth + 10), GUILayout.MinWidth(previewHeight + 10));
GUILayout.FlexibleSpace();
var rect = GUILayoutUtility.GetRect(previewWidth, previewHeight, GUILayout.ExpandWidth(false));
var preview = RenderPreview(rect);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear;
GUI.DrawTexture(rect, preview, ScaleMode.StretchToFill, false);
GL.sRGBWrite = false;
}
*/
protected string GetSlotValue(MaterialSlot inputSlot, GenerationMode generationMode)
{
var edges = owner.GetEdges(GetSlotReference(inputSlot.name)).ToArray();

var fromSocketRef = edges[0].outputSlot;
var fromNode = materialGraphOwner.GetMaterialNodeFromGuid(fromSocketRef.nodeGuid);
var fromNode = owner.GetNodeFromGuid<AbstractMaterialNode>(fromSocketRef.nodeGuid);
if (fromNode == null)
return string.Empty;

return ShaderGenerator.AdaptNodeOutput(this, slot, generationMode, inputSlot.concreteValueType);
return ShaderGenerator.AdaptNodeOutput(fromNode, slot, generationMode, inputSlot.concreteValueType);
}
return inputSlot.GetDefaultValue(generationMode, inputSlot.concreteValueType, this);

return ConcreteSlotValueType.Error;
}
public void ValidateNode()
public override void ValidateNode()
{
var isInError = false;

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

// get the output details
var outputSlotRef = edges[0].outputSlot;
var outputNode = materialGraphOwner.GetMaterialNodeFromGuid(outputSlotRef.nodeGuid);
var outputNode = owner.GetNodeFromGuid(outputSlotRef.nodeGuid);
if (outputNode == null)
continue;

if (!hasError)
{
previewShaderNeedsUpdate = true;
++version;
public bool previewShaderNeedsUpdate { get; set; }
public int version { get; private set; }
//True if error
protected virtual bool CalculateNodeHasError()

return inputSlot.OnGUI(rect, inputSlotType);
}
protected virtual bool UpdatePreviewShader()
{
if (hasError)
return false;
var resultShader = ShaderGenerator.GeneratePreviewShader(this, out m_GeneratedShaderMode);
return InternalUpdatePreviewShader(resultShader);
}
private static bool ShaderHasError(Shader shader)
{
var hasErrorsCall = typeof(ShaderUtil).GetMethod("GetShaderErrorCount", BindingFlags.Static | BindingFlags.NonPublic);
var result = hasErrorsCall.Invoke(null, new object[] {shader});
return (int) result != 0;
}
protected bool InternalUpdatePreviewShader(string resultShader)
{
Debug.Log("RecreateShaderAndMaterial : " + name + "_" + guid.ToString().Replace("-","_") + "\n" + resultShader);
// workaround for some internal shader compiler weirdness
// if we are in error we sometimes to not properly clean
// clean out the error flags and will stay in error, even
// if we are now valid
if (m_PreviewShader && ShaderHasError(m_PreviewShader))
{
Object.DestroyImmediate(m_PreviewShader, true);
Object.DestroyImmediate(m_PreviewMaterial, true);
m_PreviewShader = null;
m_PreviewMaterial = null;
}
if (m_PreviewShader == null)
{
m_PreviewShader = ShaderUtil.CreateShaderAsset(resultShader);
m_PreviewShader.hideFlags = HideFlags.HideInHierarchy;
m_LastShader = resultShader;
}
else
{
if (string.CompareOrdinal(resultShader, m_LastShader) != 0)
{
ShaderUtil.UpdateShaderAsset(m_PreviewShader, resultShader);
m_LastShader = resultShader;
}
}
return !ShaderHasError(m_PreviewShader);
}*/
/* /// <summary>
/// RenderPreview gets called in OnPreviewGUI. Nodes can override
/// RenderPreview and do their own rendering to the render texture
/// </summary>
public Texture RenderPreview(Rect targetSize)
{
if (hasError)
return null;
if (previewShaderNeedsUpdate)
{
UpdatePreviewShader();
previewShaderNeedsUpdate = false;
}
UpdatePreviewProperties();
if (s_Meshes[0] == null)
{
var handleGo = (GameObject) EditorGUIUtility.LoadRequired("Previews/PreviewMaterials.fbx");
// @TODO: temp workaround to make it not render in the scene
handleGo.SetActive(false);
foreach (Transform t in handleGo.transform)
{
switch (t.name)
{
case "sphere":
s_Meshes[0] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh;
break;
case "cube":
s_Meshes[1] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh;
break;
case "cylinder":
s_Meshes[2] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh;
break;
case "torus":
s_Meshes[3] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh;
break;
default:
Debug.Log("Something is wrong, weird object found: " + t.name);
break;
}
}
}
var previewUtil = materialGraphOwner.previewUtility;
previewUtil.BeginPreview(targetSize, GUIStyle.none);
if (m_GeneratedShaderMode == PreviewMode.Preview3D)
{
previewUtil.m_Camera.transform.position = -Vector3.forward * 5;
previewUtil.m_Camera.transform.rotation = Quaternion.identity;
EditorUtility.SetCameraAnimateMaterialsTime(previewUtil.m_Camera, Time.realtimeSinceStartup);
var amb = new Color(.2f, .2f, .2f, 0);
previewUtil.m_Light[0].intensity = 1.0f;
previewUtil.m_Light[0].transform.rotation = Quaternion.Euler(50f, 50f, 0);
previewUtil.m_Light[1].intensity = 1.0f;
InternalEditorUtility.SetCustomLighting(previewUtil.m_Light, amb);
previewUtil.DrawMesh(s_Meshes[0], Vector3.zero, Quaternion.Euler(-20, 0, 0) * Quaternion.Euler(0, 0, 0), previewMaterial, 0);
var oldFog = RenderSettings.fog;
Unsupported.SetRenderSettingsUseFogNoDirty(false);
previewUtil.m_Camera.Render();
Unsupported.SetRenderSettingsUseFogNoDirty(oldFog);
InternalEditorUtility.RemoveCustomLighting();
}
else
{
EditorUtility.UpdateGlobalShaderProperties(Time.realtimeSinceStartup);
Graphics.Blit(null, previewMaterial);
}
return previewUtil.EndPreview();
}*/
private static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat)
{
switch (previewProperty.m_PropType)
{
case PropertyType.Texture2D:
mat.SetTexture(previewProperty.m_Name, previewProperty.m_Texture);
break;
case PropertyType.Color:
mat.SetColor(previewProperty.m_Name, previewProperty.m_Color);
break;
case PropertyType.Vector2:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector3:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector4:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Float:
mat.SetFloat(previewProperty.m_Name, previewProperty.m_Float);
break;
}
}
*/
protected virtual void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
public virtual void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
var validSlots = materialInputSlots.ToArray();

var pp = new PreviewProperty
{
m_Name = s.GetInputName(this),
m_Name = GetDefaultInputNameForSlot(s),
m_PropType = PropertyType.Vector4,
m_Vector4 = s.currentValue
};

public static void UpdateMaterialProperties(AbstractMaterialNode target, Material material)
public virtual string GetOutputVariableNameForSlot(MaterialSlot s)
var childNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(childNodes, target);
var pList = ListPool<PreviewProperty>.Get();
for (var index = 0; index < childNodes.Count; index++)
{
var node = childNodes[index] as AbstractMaterialNode;
if (node == null)
continue;
if (s.isInputSlot) Debug.LogError("Attempting to use input MaterialSlot (" + s + ") for output!");
if (!materialSlots.Contains(s)) Debug.LogError("Attempting to use MaterialSlot (" + s + ") for output on a node that does not have this MaterialSlot!");
node.CollectPreviewMaterialProperties(pList);
}
foreach (var prop in pList)
SetPreviewMaterialProperty(prop, material);
ListPool<INode>.Release(childNodes);
ListPool<PreviewProperty>.Release(pList);
return GetVariableNameForNode() + "_" + s.name;
/* public void UpdatePreviewProperties()
public virtual string GetDefaultInputNameForSlot(MaterialSlot s)
if (!hasPreview)
return;
UpdateMaterialProperties(this, previewMaterial);
}*/
public virtual string GetOutputVariableNameForSlot(MaterialSlot s, GenerationMode generationMode)
{
if (s.isInputSlot) Debug.LogError("Attempting to use input MaterialSlot (" + s + ") for output!");
if (!materialSlots.Contains(s)) Debug.LogError("Attempting to use MaterialSlot (" + s + ") for output on a node that does not have this MaterialSlot!");
if (s.isOutputSlot) Debug.LogError("Attempting to use output MaterialSlot (" + s + ") for default input!");
if (!materialSlots.Contains(s)) Debug.LogError("Attempting to use MaterialSlot (" + s + ") for default input on a node that does not have this MaterialSlot!");
return GetOutputVariableNameForNode() + "_" + s.name;
return GetVariableNameForNode() + "_" + s.name;
public virtual string GetOutputVariableNameForNode()
public virtual string GetVariableNameForNode()
{
return name + "_" + guid.ToString().Replace("-", "_");
}

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


string input1Value = GetSlotValue(inputSlot1, generationMode);
string input2Value = GetSlotValue(inputSlot2, generationMode);
visitor.AddShaderChunk(precision + outputDimension + " " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(input1Value, input2Value) + ";", true);
visitor.AddShaderChunk(precision + outputDimension + " " + GetOutputVariableNameForSlot(outputSlot) + " = " + GetFunctionCallBody(input1Value, input2Value) + ";", true);
}
protected virtual string GetFunctionCallBody(string input1Value, string input2Value)

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


get { return m_ConcreteValueType; }
set { m_ConcreteValueType = value; }
}
public string GetInputName (AbstractMaterialNode node)
{
return string.Format( "{0}_{1}", node.name, name);
}
visitor.AddShaderChunk("float" + AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(slotValueType) + " " + GetInputName(owner) + ";", true);
visitor.AddShaderChunk("float" + AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(slotValueType) + " " + owner.GetDefaultInputNameForSlot(this) + ";", true);
return GetInputName(owner);
return owner.GetDefaultInputNameForSlot(this);
switch (slotValueType)
{

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


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

shaderBody.AddShaderChunk("o." + firstPassSlot.name + " = " + fromNode.GetOutputVariableNameForSlot(fromSlot, generationMode) + ";", true);
shaderBody.AddShaderChunk("o." + firstPassSlot.name + " = " + fromNode.GetOutputVariableNameForSlot(fromSlot) + ";", true);
}
// track the last index of nodes... they have already been processed :)

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

shaderBody.AddShaderChunk("o." + slot.name + " = " + fromNode.GetOutputVariableNameForSlot(fromSlot, generationMode) + ";", true);
shaderBody.AddShaderChunk("o." + slot.name + " = " + fromNode.GetOutputVariableNameForSlot(fromSlot) + ";", true);
public override string GetOutputVariableNameForSlot(MaterialSlot s, GenerationMode generationMode)
public override string GetOutputVariableNameForSlot(MaterialSlot s)
return GetOutputVariableNameForNode();
return GetVariableNameForNode();
}
/* public override float GetNodeUIHeight(float width)

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


public abstract PreviewProperty GetPreviewProperty();
public override string GetOutputVariableNameForSlot(MaterialSlot s, GenerationMode generationMode)
public override string GetOutputVariableNameForSlot(MaterialSlot s)
protected override void CollectPreviewMaterialProperties (List<PreviewProperty> properties)
public override void CollectPreviewMaterialProperties (List<PreviewProperty> properties)
{
base.CollectPreviewMaterialProperties(properties);
properties.Add(GetPreviewProperty());

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


namespace UnityEngine.MaterialGraph
{
[Title("Input/Vector 4 Node")]
class Vector4Node : PropertyNode, IGeneratesBodyCode
public class Vector4Node : PropertyNode, IGeneratesBodyCode
public Vector4 m_Value;
private Vector4 m_Value;
private const string kOutputSlotName = "Value";

public override PropertyType propertyType
{
get { return PropertyType.Vector4; }
}
public Vector4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)

public override PreviewProperty GetPreviewProperty()
{
return new PreviewProperty
{
m_Name = propertyName,
m_PropType = PropertyType.Vector4,
m_Vector4 = m_Value
};
{
m_Name = propertyName,
m_PropType = PropertyType.Vector4,
m_Vector4 = m_Value
};
}
public override void OnAfterDeserialize()

}
/*
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);
EditorGUI.BeginChangeCheck();
m_Value = EditorGUI.Vector4Field(new Rect(drawArea.x, drawArea.y, drawArea.width, EditorGUIUtility.singleLineHeight), "Value", m_Value);
if (EditorGUI.EndChangeCheck())
{
//TODO:tidy this shit.
//EditorUtility.SetDirty(materialGraphOwner.owner);
return GUIModificationType.Repaint;
}
return GUIModificationType.None;
}
*/
}
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Util/ShaderGenerator.cs


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

if (convertFromType >= convertToType || convertFromType == ConcreteSlotValueType.Vector1)
return AdaptNodeOutput(node, outputSlot, mode, convertToType);
var rawOutput = node.GetOutputVariableNameForSlot(outputSlot, mode);
var rawOutput = node.GetOutputVariableNameForSlot(outputSlot);
// otherwise we need to pad output for the preview!
switch (convertToType)

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

6
.gitignore


MaterialGraphProject/.vs
MaterialGraphProject/Library
MaterialGraphProject/MaterialGraphProject.CSharp.csproj
*.csproj
MaterialGraphProject/MaterialGraphProject.sln

9
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers.meta


fileFormatVersion: 2
guid: d53f98da57e19bd47aa9f6aed99ae412
folderAsset: yes
timeCreated: 1464865885
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

201
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/BaseMaterialNodeUI.cs


using System;
using System.Reflection;
using UnityEditor.Graphing;
using UnityEditor.Graphing.Drawing;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
using Object = UnityEngine.Object;
namespace UnityEditor.MaterialGraph
{
[CustomNodeUI(typeof(AbstractMaterialNode))]
class BaseMaterialNodeUI : ICustomNodeUi
{
private const int kPreviewWidth = 64;
private const int kPreviewHeight = 64;
private MaterialGraphPreviewGenerator m_PreviewGenerator;
[NonSerialized]
private int m_LastShaderVersion = -1;
[NonSerialized]
private Material m_PreviewMaterial;
[NonSerialized]
private Shader m_PreviewShader;
private AbstractMaterialNode m_Node;
private PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;
public Material previewMaterial
{
get
{
if (m_PreviewMaterial == null)
{
m_PreviewMaterial = new Material(Shader.Find("Unlit/Color")) {hideFlags = HideFlags.HideInHierarchy};
m_PreviewMaterial.hideFlags = HideFlags.HideInHierarchy;
}
return m_PreviewMaterial;
}
}
public MaterialGraphPreviewGenerator previewGenerator
{
get
{
if (m_PreviewGenerator == null)
{
m_PreviewGenerator = new MaterialGraphPreviewGenerator();
}
return m_PreviewGenerator;
}
}
public virtual float GetNodeUiHeight(float width)
{
return kPreviewHeight;
}
protected virtual int previewWidth
{
get { return kPreviewWidth; }
}
protected virtual int previewHeight
{
get { return kPreviewHeight; }
}
public void SetNode(INode node)
{
if (node is AbstractMaterialNode)
m_Node = (AbstractMaterialNode)node;
}
public virtual GUIModificationType Render(Rect area)
{
if (m_Node == null)
return GUIModificationType.None;
if (m_LastShaderVersion != m_Node.version)
{
UpdatePreviewShader();
m_LastShaderVersion = m_Node.version;
}
GUILayout.BeginHorizontal(GUILayout.MinWidth(previewWidth + 10), GUILayout.MinWidth(previewHeight + 10));
GUILayout.FlexibleSpace();
var rect = GUILayoutUtility.GetRect(previewWidth, previewHeight, GUILayout.ExpandWidth(false));
var preview = RenderPreview(rect);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear;
GUI.DrawTexture(rect, preview, ScaleMode.StretchToFill, false);
GL.sRGBWrite = false;
return GUIModificationType.None;
}
private bool UpdatePreviewShader()
{
if (m_Node == null)
return false;
var resultShader = ShaderGenerator.GeneratePreviewShader(m_Node, out m_GeneratedShaderMode);
Debug.Log("RecreateShaderAndMaterial : " + m_Node.name + "_" + m_Node.guid.ToString().Replace("-", "_") + "\n" + resultShader);
// workaround for some internal shader compiler weirdness
// if we are in error we sometimes to not properly clean
// out the error flags and will stay in error, even
// if we are now valid
if (m_PreviewShader && ShaderHasError(m_PreviewShader))
{
Object.DestroyImmediate(m_PreviewShader, true);
m_PreviewShader = null;
}
if (m_PreviewShader == null)
{
m_PreviewShader = ShaderUtil.CreateShaderAsset(resultShader);
m_PreviewShader.hideFlags = HideFlags.HideInHierarchy;
}
else
{
ShaderUtil.UpdateShaderAsset(m_PreviewShader, resultShader);
}
return !ShaderHasError(m_PreviewShader);
}
private static bool ShaderHasError(Shader shader)
{
var hasErrorsCall = typeof(ShaderUtil).GetMethod("GetShaderErrorCount", BindingFlags.Static | BindingFlags.NonPublic);
var result = hasErrorsCall.Invoke(null, new object[] {shader});
return (int) result != 0;
}
/// <summary>
/// RenderPreview gets called in OnPreviewGUI. Nodes can override
/// RenderPreview and do their own rendering to the render texture
/// </summary>
public Texture RenderPreview(Rect targetSize)
{
previewMaterial.shader = m_PreviewShader;
UpdateMaterialProperties(m_Node, previewMaterial);
return previewGenerator.DoRenderPreview(previewMaterial, m_GeneratedShaderMode, targetSize);
}
private static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat)
{
switch (previewProperty.m_PropType)
{
case PropertyType.Texture2D:
mat.SetTexture(previewProperty.m_Name, previewProperty.m_Texture);
break;
case PropertyType.Color:
mat.SetColor(previewProperty.m_Name, previewProperty.m_Color);
break;
case PropertyType.Vector2:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector3:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector4:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Float:
mat.SetFloat(previewProperty.m_Name, previewProperty.m_Float);
break;
}
}
public static void UpdateMaterialProperties(AbstractMaterialNode target, Material material)
{
var childNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(childNodes, target);
var pList = ListPool<PreviewProperty>.Get();
for (var index = 0; index < childNodes.Count; index++)
{
var node = childNodes[index] as AbstractMaterialNode;
if (node == null)
continue;
node.CollectPreviewMaterialProperties(pList);
}
foreach (var prop in pList)
SetPreviewMaterialProperty(prop, material);
ListPool<INode>.Release(childNodes);
ListPool<PreviewProperty>.Release(pList);
}
}
}

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/BaseMaterialNodeUI.cs.meta


fileFormatVersion: 2
guid: 3ed1e0e3aec9a634e83fa340200854c4
timeCreated: 1464868519
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

41
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector4NodeUI.cs


using UnityEditor.Graphing;
using UnityEditor.Graphing.Drawing;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
namespace UnityEditor.MaterialGraph
{
[CustomNodeUI(typeof(Vector4Node))]
public class Vector4NodeUI : ICustomNodeUi
{
private Vector4Node m_Node;
public float GetNodeUiHeight(float width)
{
return 2 * EditorGUIUtility.singleLineHeight;
}
public GUIModificationType Render(Rect area)
{
if (m_Node == null)
return GUIModificationType.None;
EditorGUI.BeginChangeCheck();
m_Node.value = EditorGUI.Vector4Field(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Value", m_Node.value);
if (EditorGUI.EndChangeCheck())
{
//TODO:tidy this shit.
//EditorUtility.SetDirty(materialGraphOwner.owner);
return GUIModificationType.Repaint;
}
return GUIModificationType.None;
}
public void SetNode(INode node)
{
if (node is Vector4Node)
m_Node = (Vector4Node) node;
}
}
}

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector4NodeUI.cs.meta


fileFormatVersion: 2
guid: f970378d854a8e6458eb369bfb46bc42
timeCreated: 1464865885
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

5
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Util.meta


fileFormatVersion: 2
guid: 03ed77116f3480d4c85e8d92a684b096
folderAsset: yes
DefaultImporter:
userData:
正在加载...
取消
保存