浏览代码

[Shader Graph] Inital commit of modularised graph editor

/main
Tim Cooper 12 年前
当前提交
2a039635
共有 187 个文件被更改,包括 3399 次插入0 次删除
  1. 5
      UnityProject/Assets/Editor/Material.meta
  2. 104
      UnityProject/Assets/Editor/Material/BaseMaterialGraph.cs
  3. 8
      UnityProject/Assets/Editor/Material/BaseMaterialGraph.cs.meta
  4. 85
      UnityProject/Assets/Editor/Material/BaseMaterialGraphGUI.cs
  5. 8
      UnityProject/Assets/Editor/Material/BaseMaterialGraphGUI.cs.meta
  6. 5
      UnityProject/Assets/Editor/Material/Editors.meta
  7. 87
      UnityProject/Assets/Editor/Material/Editors/BaseMaterialNodeEditor.cs
  8. 8
      UnityProject/Assets/Editor/Material/Editors/BaseMaterialNodeEditor.cs.meta
  9. 34
      UnityProject/Assets/Editor/Material/Editors/PropertyNodeEditor.cs
  10. 8
      UnityProject/Assets/Editor/Material/Editors/PropertyNodeEditor.cs.meta
  11. 5
      UnityProject/Assets/Editor/Material/Interfaces.meta
  12. 5
      UnityProject/Assets/Editor/Material/Light.meta
  13. 21
      UnityProject/Assets/Editor/Material/Light/BaseLightFunction.cs
  14. 8
      UnityProject/Assets/Editor/Material/Light/BaseLightFunction.cs.meta
  15. 28
      UnityProject/Assets/Editor/Material/Light/SimpleSpecularFunction.cs
  16. 8
      UnityProject/Assets/Editor/Material/Light/SimpleSpecularFunction.cs.meta
  17. 27
      UnityProject/Assets/Editor/Material/Light/WrapLambertFunction.cs
  18. 8
      UnityProject/Assets/Editor/Material/Light/WrapLambertFunction.cs.meta
  19. 109
      UnityProject/Assets/Editor/Material/MaterialGraph.cs
  20. 8
      UnityProject/Assets/Editor/Material/MaterialGraph.cs.meta
  21. 64
      UnityProject/Assets/Editor/Material/MaterialGraphGUI.cs
  22. 8
      UnityProject/Assets/Editor/Material/MaterialGraphGUI.cs.meta
  23. 213
      UnityProject/Assets/Editor/Material/MaterialSubGraph.cs
  24. 8
      UnityProject/Assets/Editor/Material/MaterialSubGraph.cs.meta
  25. 34
      UnityProject/Assets/Editor/Material/MaterialSubGraphGUI.cs
  26. 8
      UnityProject/Assets/Editor/Material/MaterialSubGraphGUI.cs.meta
  27. 156
      UnityProject/Assets/Editor/Material/MaterialWindow.cs
  28. 8
      UnityProject/Assets/Editor/Material/MaterialWindow.cs.meta
  29. 5
      UnityProject/Assets/Editor/Material/Nodes.meta
  30. 30
      UnityProject/Assets/Editor/Material/Nodes/AbsoluteNode.cs
  31. 8
      UnityProject/Assets/Editor/Material/Nodes/AbsoluteNode.cs.meta
  32. 50
      UnityProject/Assets/Editor/Material/Nodes/AddNode.cs
  33. 8
      UnityProject/Assets/Editor/Material/Nodes/AddNode.cs.meta
  34. 486
      UnityProject/Assets/Editor/Material/Nodes/BaseMaterialNode.cs
  35. 8
      UnityProject/Assets/Editor/Material/Nodes/BaseMaterialNode.cs.meta
  36. 67
      UnityProject/Assets/Editor/Material/Nodes/BlendNode.cs
  37. 8
      UnityProject/Assets/Editor/Material/Nodes/BlendNode.cs.meta
  38. 30
      UnityProject/Assets/Editor/Material/Nodes/ClampNode.cs
  39. 8
      UnityProject/Assets/Editor/Material/Nodes/ClampNode.cs.meta
  40. 99
      UnityProject/Assets/Editor/Material/Nodes/ColorNode.cs
  41. 8
      UnityProject/Assets/Editor/Material/Nodes/ColorNode.cs.meta
  42. 72
      UnityProject/Assets/Editor/Material/Nodes/ColorizeNode.cs
  43. 8
      UnityProject/Assets/Editor/Material/Nodes/ColorizeNode.cs.meta
  44. 114
      UnityProject/Assets/Editor/Material/Nodes/CombineNode.cs
  45. 8
      UnityProject/Assets/Editor/Material/Nodes/CombineNode.cs.meta
  46. 30
      UnityProject/Assets/Editor/Material/Nodes/DivNode.cs
  47. 8
      UnityProject/Assets/Editor/Material/Nodes/DivNode.cs.meta
  48. 14
      UnityProject/Assets/Editor/Material/Nodes/DotNode.cs
  49. 8
      UnityProject/Assets/Editor/Material/Nodes/DotNode.cs.meta
  50. 47
      UnityProject/Assets/Editor/Material/Nodes/Extensions.cs
  51. 8
      UnityProject/Assets/Editor/Material/Nodes/Extensions.cs.meta
  52. 31
      UnityProject/Assets/Editor/Material/Nodes/FresnelNode.cs
  53. 8
      UnityProject/Assets/Editor/Material/Nodes/FresnelNode.cs.meta
  54. 57
      UnityProject/Assets/Editor/Material/Nodes/Function1Input.cs
  55. 8
      UnityProject/Assets/Editor/Material/Nodes/Function1Input.cs.meta
  56. 46
      UnityProject/Assets/Editor/Material/Nodes/Function2Input.cs
  57. 8
      UnityProject/Assets/Editor/Material/Nodes/Function2Input.cs.meta
  58. 51
      UnityProject/Assets/Editor/Material/Nodes/Function3Input.cs
  59. 8
      UnityProject/Assets/Editor/Material/Nodes/Function3Input.cs.meta
  60. 83
      UnityProject/Assets/Editor/Material/Nodes/FunctionMultiInput.cs
  61. 8
      UnityProject/Assets/Editor/Material/Nodes/FunctionMultiInput.cs.meta
  62. 95
      UnityProject/Assets/Editor/Material/Nodes/KaleidoscopeNode.cs
  63. 8
      UnityProject/Assets/Editor/Material/Nodes/KaleidoscopeNode.cs.meta
  64. 14
      UnityProject/Assets/Editor/Material/Nodes/LengthNode.cs
  65. 8
      UnityProject/Assets/Editor/Material/Nodes/LengthNode.cs.meta
  66. 95
      UnityProject/Assets/Editor/Material/Nodes/MandelbrotNode.cs
  67. 8
      UnityProject/Assets/Editor/Material/Nodes/MandelbrotNode.cs.meta
  68. 14
      UnityProject/Assets/Editor/Material/Nodes/MaxNode.cs
  69. 8
      UnityProject/Assets/Editor/Material/Nodes/MaxNode.cs.meta
  70. 14
      UnityProject/Assets/Editor/Material/Nodes/MinNode.cs
  71. 8
      UnityProject/Assets/Editor/Material/Nodes/MinNode.cs.meta
  72. 37
      UnityProject/Assets/Editor/Material/Nodes/MultiplyNode.cs
  73. 8
      UnityProject/Assets/Editor/Material/Nodes/MultiplyNode.cs.meta
  74. 30
      UnityProject/Assets/Editor/Material/Nodes/NormalNode.cs
  75. 8
      UnityProject/Assets/Editor/Material/Nodes/NormalNode.cs.meta
  76. 14
      UnityProject/Assets/Editor/Material/Nodes/NormalizeNode.cs
  77. 8
      UnityProject/Assets/Editor/Material/Nodes/NormalizeNode.cs.meta
  78. 101
      UnityProject/Assets/Editor/Material/Nodes/PerlinNode.cs
  79. 8
      UnityProject/Assets/Editor/Material/Nodes/PerlinNode.cs.meta
  80. 145
      UnityProject/Assets/Editor/Material/Nodes/PixelShaderNode.cs
  81. 8
      UnityProject/Assets/Editor/Material/Nodes/PixelShaderNode.cs.meta
  82. 16
      UnityProject/Assets/Editor/Material/Nodes/PowerNode.cs
  83. 8
      UnityProject/Assets/Editor/Material/Nodes/PowerNode.cs.meta
  84. 69
      UnityProject/Assets/Editor/Material/Nodes/PropertyNode.cs
  85. 8
      UnityProject/Assets/Editor/Material/Nodes/PropertyNode.cs.meta
  86. 30
      UnityProject/Assets/Editor/Material/Nodes/QuantizeNode.cs
  87. 8
      UnityProject/Assets/Editor/Material/Nodes/QuantizeNode.cs.meta
  88. 38
      UnityProject/Assets/Editor/Material/Nodes/ReflectNode.cs
  89. 8
      UnityProject/Assets/Editor/Material/Nodes/ReflectNode.cs.meta
  90. 27
      UnityProject/Assets/Editor/Material/Nodes/ScreenPosNode.cs
  91. 8
      UnityProject/Assets/Editor/Material/Nodes/ScreenPosNode.cs.meta
  92. 14
      UnityProject/Assets/Editor/Material/Nodes/SinNode.cs
  93. 8
      UnityProject/Assets/Editor/Material/Nodes/SinNode.cs.meta

5
UnityProject/Assets/Editor/Material.meta


fileFormatVersion: 2
guid: a48816fdf109ebf49adc559a855f3e42
folderAsset: yes
DefaultImporter:
userData:

104
UnityProject/Assets/Editor/Material/BaseMaterialGraph.cs


using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
public interface IGenerateGraphProperties
{
void GenerateSharedProperties (PropertyGenerator shaderProperties, ShaderGenerator propertyUsages, GenerationMode generationMode);
IEnumerable<ShaderProperty> GetPropertiesForPropertyType (PropertyType propertyType);
}
public abstract class BaseMaterialGraph : Graph
{
public abstract BaseMaterialNode masterNode { get; }
private PreviewRenderUtility m_PreviewUtility;
public PreviewRenderUtility previewUtility
{
get
{
if (m_PreviewUtility == null)
m_PreviewUtility = new PreviewRenderUtility ();
return m_PreviewUtility;
}
}
public bool requiresRepaint
{
get { return m_ImAwake && nodes.Any (x => x is IRequiresTime); }
}
public override void RemoveEdge (Edge e)
{
base.RemoveEdge (e);
var toNode = e.toSlot.node as BaseMaterialNode;
if (toNode == null)
return;
toNode.RegeneratePreviewShaders ();
}
public override Edge Connect(Slot fromSlot, Slot toSlot)
{
var edge = base.Connect (fromSlot, toSlot);
var toNode = toSlot.node as BaseMaterialNode;
var fromNode = fromSlot.node as BaseMaterialNode;
if (fromNode == null || toNode == null)
return edge;
toNode.RegeneratePreviewShaders();
fromNode.CollectChildNodesByExecutionOrder().ToList ().ForEach (s => s.UpdatePreviewProperties());
return edge;
}
public override void AddNode(Node node)
{
base.AddNode(node);
AssetDatabase.AddObjectToAsset (node, this);
var bmn = node as BaseMaterialNode;
if (bmn != null && bmn.hasPreview )
bmn.UpdatePreviewMaterial ();
}
protected void AddMasterNodeNoAddToAsset (Node node)
{
base.AddNode (node);
}
public void GeneratePreviewShaders ()
{
MaterialWindow.DebugMaterialGraph ("Generating preview shaders on: " + name);
// 2 passes...
// 1 create the shaders
foreach (var node in nodes)
{
var bmn = node as BaseMaterialNode;
if (bmn != null && bmn.hasPreview)
{
bmn.UpdatePreviewMaterial ();
}
}
// 2 set the properties
foreach (var node in nodes)
{
var pNode = node as BaseMaterialNode;
if (pNode != null)
{
MaterialWindow.DebugMaterialGraph ("Updating preview Properties on Node: " + pNode);
pNode.UpdatePreviewProperties ();
}
}
}
}
}

8
UnityProject/Assets/Editor/Material/BaseMaterialGraph.cs.meta


fileFormatVersion: 2
guid: 6567c9f37c0aaa94e9083ffc63612ecf
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

85
UnityProject/Assets/Editor/Material/BaseMaterialGraphGUI.cs


using System;
using UnityEngine;
using System.Reflection;
namespace UnityEditor.Graphs.Material
{
abstract class BaseMaterialGraphGUI : GraphGUI
{
internal const int kDefaultNodeWidth = 50;
internal const int kDefaultNodeHeight = 80;
public override void OnGraphGUI()
{
m_Host.BeginWindows();
// Process all nodes in the graph
foreach (var n in graph.nodes)
{
var n2 = n;
bool isSelected = selection.Contains(n2);
n.position = GUILayout.Window(n.GetInstanceID(), n.position, delegate { NodeGUI(n2); }, n.title, Styles.GetNodeStyle(n.style, n.color, isSelected), GUILayout.Width(kDefaultNodeWidth), GUILayout.Height(kDefaultNodeHeight));
if (n2 is BaseMaterialNode)
((BaseMaterialNode)n2).isSelected = isSelected;
}
m_Host.EndWindows();
edgeGUI.DoEdges();
edgeGUI.DoDraggedEdge ();
DragSelection(new Rect(-5000, -5000, 10000, 10000));
HandleMenuEvents ();
Event evt = Event.current;
if (evt.type == EventType.MouseDown)
{
if (evt.button == 1)
{
DoAddNodeMenu(Event.current.mousePosition);
evt.Use();
}
}
}
private class AddNodeCreationObject : object
{
public Vector2 m_Pos;
public readonly Type m_Type;
public AddNodeCreationObject(Type t, Vector2 p) { m_Type = t; m_Pos = p; }
};
private void AddNode(object obj)
{
var posObj = obj as AddNodeCreationObject;
if (posObj == null)
return;
var node = (BaseMaterialNode)CreateInstance(posObj.m_Type);
node.Init ();
node.position = new Rect(posObj.m_Pos.x, posObj.m_Pos.y, node.position.width, node.position.height);
graph.AddNode(node);
}
public virtual bool CanAddToNodeMenu(Type type) { return true; }
protected void DoAddNodeMenu (Vector2 pos)
{
var gm = new GenericMenu();
foreach (Type type in Assembly.GetAssembly(typeof(BaseMaterialNode)).GetTypes())
{
if(type.IsClass && !type.IsAbstract && (type.IsSubclassOf(typeof(BaseMaterialNode)) || type.IsSubclassOf(typeof(PropertyNode))))
{
var attrs = type.GetCustomAttributes(typeof(TitleAttribute), false) as TitleAttribute[];
if(attrs != null && attrs.Length > 0 && CanAddToNodeMenu(type))
{
gm.AddItem(new GUIContent(attrs[0].m_Title), false, AddNode, new AddNodeCreationObject(type, pos));
}
}
}
gm.ShowAsContext ();
}
}
}

8
UnityProject/Assets/Editor/Material/BaseMaterialGraphGUI.cs.meta


fileFormatVersion: 2
guid: ac8e8db31ba040a479c767257822927a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

5
UnityProject/Assets/Editor/Material/Editors.meta


fileFormatVersion: 2
guid: 221d30ba302de9c4c8912141392f3afa
folderAsset: yes
DefaultImporter:
userData:

87
UnityProject/Assets/Editor/Material/Editors/BaseMaterialNodeEditor.cs


using System;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[CustomEditor(typeof(BaseMaterialNode), true)]
class BaseMaterialNodeEditor : Editor
{
public override void OnInspectorGUI()
{
var node = target as BaseMaterialNode;
if (node == null)
return;
var slots = node.slots.ToArray();
EditorGUILayout.LabelField ("Preview Mode: " + node.previewMode);
foreach (var slot in slots)
DoSlotUI (node, slot);
}
/*private bool DoDefaultInspectorUI ()
{
EditorGUIUtility.LookLikeInspector();
EditorGUI.BeginChangeCheck ();
serializedObject.Update();
bool materialSlotsFound = serializedObject.FindProperty("m_SlotDefaultValues") != null;
SerializedProperty property = serializedObject.GetIterator ();
bool expanded = true;
while (property.NextVisible (expanded))
{
expanded = false;
if (materialSlotsFound && (property.type == "Slot" || property.name == "m_SlotPropertiesIndexes" || property.name == "m_SlotProperties"))
continue;
EditorGUILayout.PropertyField (property, true);
}
serializedObject.ApplyModifiedProperties ();
EditorGUI.EndChangeCheck ();
return materialSlotsFound;
}
*/
private void DoSlotUI (BaseMaterialNode node, Slot slot)
{
GUILayout.BeginHorizontal (EditorStyles.inspectorBig);
GUILayout.BeginVertical ();
GUILayout.BeginHorizontal ();
GUILayout.Label ("Slot " + slot.title, EditorStyles.largeLabel);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal ();
GUILayout.EndVertical ();
GUILayout.EndHorizontal ();
DoMaterialSlotUIBody (node, slot);
}
private static void DoMaterialSlotUIBody(BaseMaterialNode node, Slot slot)
{
SlotDefaultValue defaultValue = node.GetSlotDefaultValue (slot.name);
if (defaultValue == null)
return;
if (defaultValue.editable)
slot.title = EditorGUILayout.TextField ("Title", slot.title);
var def = node.GetSlotDefaultValue (slot.name);
if (def != null)
{
if (def.OnGUI())
{
node.UpdatePreviewProperties ();
}
}
}
private static void RemoveSlot (BaseMaterialNode node, Slot slot)
{
node.RemoveSlot (slot);
}
}
}

8
UnityProject/Assets/Editor/Material/Editors/BaseMaterialNodeEditor.cs.meta


fileFormatVersion: 2
guid: d1e060684b84ebf4aa8b96b424def1ab
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

34
UnityProject/Assets/Editor/Material/Editors/PropertyNodeEditor.cs


using System.Collections.Generic;
using System.Linq;
namespace UnityEditor.Graphs.Material
{
[CustomEditor(typeof(PropertyNode), true)]
class PropertyNodeEditor : Editor
{
public override void OnInspectorGUI()
{
var propertyNode = target as PropertyNode;
if (propertyNode == null)
return;
// find available properties
var allowedBindings = propertyNode.FindValidPropertyBindings ().ToList ();
var names = new List<string> {"none"};
names.AddRange (allowedBindings.Select (x => x.name));
var currentIndex = names.IndexOf (propertyNode.boundProperty == null ? "none" : propertyNode.boundProperty.name);
EditorGUI.BeginChangeCheck ();
currentIndex = EditorGUILayout.Popup ("Bound Property", currentIndex, names.ToArray ());
if (EditorGUI.EndChangeCheck())
{
ShaderProperty selected = null;
if (currentIndex > 0)
selected = allowedBindings[currentIndex - 1];
propertyNode.BindProperty (selected, true);
}
}
}
}

8
UnityProject/Assets/Editor/Material/Editors/PropertyNodeEditor.cs.meta


fileFormatVersion: 2
guid: 30abe8c249112c9408f055b48acef7d8
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

5
UnityProject/Assets/Editor/Material/Interfaces.meta


fileFormatVersion: 2
guid: 40a7723163e258742885b9b645737dd6
folderAsset: yes
DefaultImporter:
userData:

5
UnityProject/Assets/Editor/Material/Light.meta


fileFormatVersion: 2
guid: bd024cce897f5b5459ef6b8b08a31329
folderAsset: yes
DefaultImporter:
userData:

21
UnityProject/Assets/Editor/Material/Light/BaseLightFunction.cs


using System;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
public abstract class BaseLightFunction
{
public virtual string GetName () { return ""; }
public virtual void GenerateBody (ShaderGenerator visitor) {}
}
class LambertLightFunction : BaseLightFunction
{
public override string GetName () { return "Lambert"; }
}
class BlinnPhongLightFunction : BaseLightFunction
{
public override string GetName () { return "BlinnPhong"; }
}
}

8
UnityProject/Assets/Editor/Material/Light/BaseLightFunction.cs.meta


fileFormatVersion: 2
guid: 0981739b7ed42c34c9f238c36a1d63e0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

28
UnityProject/Assets/Editor/Material/Light/SimpleSpecularFunction.cs


using System;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
class SimpleSpecularFunction : BaseLightFunction
{
public override string GetName () { return "SimpleSpecular"; }
public override void GenerateBody(ShaderGenerator visitor)
{
var outputString = new ShaderGenerator ();
outputString.AddShaderChunk ("half4 Lighting" + GetName () + " (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)", false);
outputString.AddShaderChunk ("{", false);
outputString.Indent ();
outputString.AddShaderChunk ("half3 h = normalize (lightDir + viewDir);", false);
outputString.AddShaderChunk ("half diff = max (0, dot (s.Normal, lightDir));", false);
outputString.AddShaderChunk ("half nh = max (0, dot (s.Normal, h));", false);
outputString.AddShaderChunk ("half spec = pow (nh, 48.0);", false);
outputString.AddShaderChunk ("half4 c; c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);", false);
outputString.AddShaderChunk ("c.a = s.Alpha;", false);
outputString.AddShaderChunk ("return c;", false);
outputString.Deindent ();
outputString.AddShaderChunk ("}", false);
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Light/SimpleSpecularFunction.cs.meta


fileFormatVersion: 2
guid: 241a90386f89a7f4da1ca187a0dd3eb2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

27
UnityProject/Assets/Editor/Material/Light/WrapLambertFunction.cs


using System;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
class WrapLambertFunction : BaseLightFunction
{
public override string GetName () { return "WrapLambert"; }
public override void GenerateBody(ShaderGenerator visitor)
{
var outputString = new ShaderGenerator ();
outputString.AddShaderChunk ("half4 Lighting" + GetName () + " (SurfaceOutput s, half3 lightDir, half atten)", false);
outputString.AddShaderChunk ("{", false);
outputString.Indent ();
outputString.AddShaderChunk ("half NdotL = dot (s.Normal, lightDir);", false);
outputString.AddShaderChunk ("half diff = NdotL * 0.5 + 0.5;", false);
outputString.AddShaderChunk ("half4 c;", false);
outputString.AddShaderChunk ("c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);", false);
outputString.AddShaderChunk ("c.a = s.Alpha;", false);
outputString.AddShaderChunk ("return c;", false);
outputString.Deindent ();
outputString.AddShaderChunk ("}", false);
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Light/WrapLambertFunction.cs.meta


fileFormatVersion: 2
guid: 4ed268fcd50cca74489ba39307e33e63
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

109
UnityProject/Assets/Editor/Material/MaterialGraph.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
public class MaterialGraph : ScriptableObject, IGenerateGraphProperties
{
[SerializeField]
private MaterialProperties m_MaterialProperties;
[SerializeField]
private MaterialOptions m_MaterialOptions;
[SerializeField]
private PixelGraph m_PixelGraph;
[SerializeField]
private Shader m_Shader;
public MaterialProperties materialProperties { get { return m_MaterialProperties; } }
public MaterialOptions materialOptions { get { return m_MaterialOptions; } }
public BaseMaterialGraph currentGraph { get { return m_PixelGraph; } }
public void GenerateSharedProperties(PropertyGenerator shaderProperties, ShaderGenerator propertyUsages, GenerationMode generationMode)
{
m_MaterialProperties.GenerateSharedProperties (shaderProperties, propertyUsages, generationMode);
}
public IEnumerable<ShaderProperty> GetPropertiesForPropertyType (PropertyType propertyType)
{
return m_MaterialProperties.GetPropertiesForPropertyType(propertyType);
}
public void OnEnable ()
{
if (m_MaterialProperties == null)
{
m_MaterialProperties = CreateInstance<MaterialProperties>();
m_MaterialProperties.hideFlags = HideFlags.HideInHierarchy;
}
if (m_MaterialOptions == null)
{
m_MaterialOptions = CreateInstance<MaterialOptions> ();
m_MaterialOptions.Init ();
m_MaterialOptions.hideFlags = HideFlags.HideInHierarchy;
}
if (m_PixelGraph == null)
{
m_PixelGraph = CreateInstance<PixelGraph>();
m_PixelGraph.hideFlags = HideFlags.HideInHierarchy;
m_PixelGraph.name = name;
}
m_PixelGraph.owner = this;
}
public void OnDisable ()
{
// if (m_MaterialProperties != null)
// m_MaterialProperties.OnChangePreviewState -= OnChangePreviewState;
}
void OnChangePreviewState (object sender, EventArgs eventArgs)
{
m_PixelGraph.previewState = (PreviewState)sender;
}
public void UpdateShaderSource (string src, Dictionary<string, Texture> defaultTexutres)
{
UnityEditorInternal.InternalEditorUtility.UpdateShaderAsset (m_Shader, src);
EditorMaterialUtility.SetShaderDefaults (m_Shader, defaultTexutres.Keys.ToArray (), defaultTexutres.Values.ToArray ());
}
public void CreateSubAssets ()
{
AssetDatabase.AddObjectToAsset (m_MaterialProperties, this);
AssetDatabase.AddObjectToAsset (m_MaterialOptions, this);
AssetDatabase.AddObjectToAsset (m_PixelGraph, this);
if (m_Shader == null)
{
const string shaderSource = "Shader \"Graphs/Dummy\" {" +
"Properties { _Color (\"Main Color\", Color) = (1,1,1,0) }" +
"SubShader {" +
" Tags { \"Queue\" = \"Transparent\" }" +
" Pass {" +
" Blend One One ZWrite Off ColorMask RGB" +
" Material { Diffuse [_Color] Ambient [_Color] }" +
" Lighting On" +
" SetTexture [_Dummy] { combine primary double, primary }" +
" }" +
"}" +
"}";
m_Shader = UnityEditorInternal.InternalEditorUtility.CreateShaderAsset(shaderSource);
m_Shader.name = name;
m_Shader.hideFlags = HideFlags.HideInHierarchy;
}
AssetDatabase.AddObjectToAsset (m_Shader, this);
m_PixelGraph.AddMasterNodeToAsset ();
}
}
}

8
UnityProject/Assets/Editor/Material/MaterialGraph.cs.meta


fileFormatVersion: 2
guid: ef5b9f0785847b04983f907c7f016a36
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

64
UnityProject/Assets/Editor/Material/MaterialGraphGUI.cs


using System.IO;
using UnityEngine;
using System.Linq;
namespace UnityEditor.Graphs.Material
{
class MaterialGraphGUI : BaseMaterialGraphGUI
{
enum SelectedOptions
{
properties,
options
}
private PixelGraph GetGraph() {return graph as PixelGraph;}
public MaterialGraph materialGraph;
private SelectedOptions m_SelectedGUI = SelectedOptions.properties;
private static void DrawSpacer()
{
var spacerLine = GUILayoutUtility.GetRect(GUIContent.none,
GUIStyle.none,
GUILayout.ExpandWidth(true),
GUILayout.Height(1));
var oldBgColor = GUI.backgroundColor;
if (EditorGUIUtility.isProSkin)
GUI.backgroundColor = oldBgColor * 0.7058f;
else
GUI.backgroundColor = Color.black;
if (Event.current.type == EventType.Repaint)
EditorGUIUtility.whiteTextureStyle.Draw(spacerLine, GUIContent.none, false, false, false, false);
GUI.backgroundColor = oldBgColor;
}
public void RenderOptions (Rect rect, MaterialGraph graph)
{
GUILayout.BeginArea (rect);
m_SelectedGUI = (SelectedOptions)EditorGUILayout.EnumPopup ("Options?", m_SelectedGUI);
DrawSpacer ();
if (m_SelectedGUI == SelectedOptions.properties)
graph.materialProperties.DoGUI(GetGraph().nodes);
else if (m_SelectedGUI == SelectedOptions.options)
graph.materialOptions.DoGUI ();
GUILayout.FlexibleSpace ();
if (GUILayout.Button ("Output Shader :)"))
{
var templateLocation = Path.Combine( Application.dataPath,
Path.Combine ("MaterialGraph",
"Shader.template"));
if (File.Exists(templateLocation))
ShaderGenerator.GenerateSurfaceShader (graph);
}
GUILayout.EndArea ();
}
}
}

8
UnityProject/Assets/Editor/Material/MaterialGraphGUI.cs.meta


fileFormatVersion: 2
guid: b8ed425deb1eed44fb9b594561203b1a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

213
UnityProject/Assets/Editor/Material/MaterialSubGraph.cs


using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
public class MaterialSubGraph : BaseMaterialGraph, IGeneratesVertexToFragmentBlock, IGeneratesFunction, IGeneratesVertexShaderBlock, IGenerateProperties
{
[SerializeField]
private SubGraphInputsNode m_InputsNode;
public SubGraphNode processingOwner { get; set; }
[SerializeField]
private SubGraphOutputsNode m_OutputsNode;
public SubGraphInputsNode inputsNode { get { return m_InputsNode; } }
public SubGraphOutputsNode outputsNode { get { return m_OutputsNode; } }
public override BaseMaterialNode masterNode { get { return outputsNode; } }
public new void OnEnable()
{
base.OnEnable ();
if (m_InputsNode == null)
{
m_InputsNode = CreateInstance<SubGraphInputsNode> ();
m_InputsNode.hideFlags = HideFlags.HideInHierarchy;
m_InputsNode.Init ();
AddMasterNodeNoAddToAsset (m_InputsNode);
}
if (m_OutputsNode == null)
{
m_OutputsNode = CreateInstance<SubGraphOutputsNode> ();
m_OutputsNode.hideFlags = HideFlags.HideInHierarchy;
m_OutputsNode.Init ();
AddMasterNodeNoAddToAsset (m_OutputsNode);
}
}
public void CreateSubAssets()
{
AssetDatabase.AddObjectToAsset(m_InputsNode, this);
AssetDatabase.AddObjectToAsset(m_OutputsNode, this);
}
// Return if the given input slot is wired all the way to an output slot
// and if that output slot is connected on the SubGraphNode
public bool InputInternallyWired(string slotName, SubGraphNode subGraphNode)
{
var outputSlot = inputsNode.slots.FirstOrDefault (x => x.name == slotName);
if (outputSlot == null || outputSlot.edges.Count == 0)
return false;
var usedInputSlots = new List<Slot> ();
foreach (var edge in outputSlot.edges)
{
if (edge.toSlot.node == outputsNode)
usedInputSlots.Add (edge.toSlot);
FindValidInputsToNodeFromNode (outputsNode, edge.toSlot.node, usedInputSlots);
}
//var inputWiredToSlots = new List<Slot> ();
foreach (var foundUsedInputSlot in usedInputSlots)
{
Slot slot = foundUsedInputSlot;
var onExternalNodeSlot = subGraphNode.outputSlots.FirstOrDefault (x => x.name == slot.name);
if (onExternalNodeSlot != null && onExternalNodeSlot.edges.Count > 0)
return true;
//inputWiredToSlots.Add (onExternalNodeSlot);
}
return false;
//return inputWiredToSlots;
}
private static void FindValidInputsToNodeFromNode(Node toNode, Node currentNode, ICollection<Slot> foundUsedInputSlots)
{
if (currentNode == null || toNode == null)
{
Debug.LogError ("Recursing to find valid inputs on NULL node");
return;
}
foreach (var outputSlot in currentNode.outputSlots)
{
foreach (var edge in outputSlot.edges)
{
if (edge.toSlot.node == toNode && !foundUsedInputSlots.Contains(edge.toSlot))
{
var validInputSlotsAtTarget = (edge.toSlot.node as BaseMaterialNode).GetValidInputSlots ();
if (validInputSlotsAtTarget.Contains (edge.toSlot))
foundUsedInputSlots.Add (edge.toSlot);
}
else
FindValidInputsToNodeFromNode(toNode, edge.toSlot.node, foundUsedInputSlots);
}
}
}
public string GetInputVariableNameForSlotByName(string slotName, BaseMaterialNode usageNode, GenerationMode generationMode)
{
var outputSlot = inputsNode.slots.FirstOrDefault (x => x.name == slotName);
if (outputSlot == null)
return "Could Not Find Slot";
return inputsNode.GetOutputVariableNameForSlot(outputSlot, generationMode);
}
public bool OutputInternallyWired (string slotName)
{
var inputSlot = outputsNode.slots.FirstOrDefault(x => x.name == slotName);
if (inputSlot == null)
return false;
return inputSlot.edges.Count > 0;
}
public string GetOutputVariableNameForSlotByName(string slotName, BaseMaterialNode usageNode, GenerationMode generationMode)
{
var inputSlot = outputsNode.slots.FirstOrDefault (x => x.name == slotName);
if (inputSlot == null || inputSlot.edges.Count == 0)
return "Slot Error";
var bmn = inputSlot.edges[0].fromSlot.node as BaseMaterialNode;
return bmn == null ? "Slot Error" : bmn.GetOutputVariableNameForSlot (inputSlot.edges[0].fromSlot, generationMode);
}
private IEnumerable<BaseMaterialNode> GetCollectedNodes()
{
return outputsNode.CollectChildNodesByExecutionOrder ();
}
public void GenerateNodeCode (ShaderGenerator visitor, SubGraphNode generatingFor)
{
// First find which outputs are connected externally
var externallyConnected = new List<Slot> ();
foreach (var slot in outputsNode.inputSlots)
{
var externalSlot = generatingFor.outputSlots.FirstOrDefault (x => x.name == slot.name);
if (externalSlot == null)
continue;
if (externalSlot.edges.Count > 0)
externallyConnected.Add (slot);
}
// then collect the valid nodes
var collectedNodes = new List<BaseMaterialNode>();
foreach (var s in externallyConnected)
outputsNode.CollectChildNodesByExecutionOrder (collectedNodes, s, false);
// then generate code for the connected nodes
foreach (var n in collectedNodes.OfType<IGeneratesBodyCode>())
n.GenerateNodeCode(visitor, GenerationMode.SurfaceShader);
}
public void GenerateVertexToFragmentBlock (ShaderGenerator visitor, GenerationMode generationMode)
{
foreach (var n in GetCollectedNodes ().OfType<IGeneratesVertexToFragmentBlock> ())
n.GenerateVertexToFragmentBlock(visitor, generationMode);
}
public void GenerateNodeFunction (ShaderGenerator visitor, GenerationMode generationMode)
{
foreach (var n in GetCollectedNodes ().OfType<IGeneratesFunction> ())
n.GenerateNodeFunction(visitor, generationMode);
}
public void GenerateVertexShaderBlock(ShaderGenerator visitor, GenerationMode generationMode)
{
foreach (var n in GetCollectedNodes ().OfType<IGeneratesVertexShaderBlock> ())
n.GenerateVertexShaderBlock (visitor, generationMode);
}
public void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
foreach (var n in GetCollectedNodes().OfType<IGenerateProperties>())
n.GeneratePropertyBlock (visitor, generationMode);
}
public void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
foreach (var n in GetCollectedNodes ().OfType<IGenerateProperties> ())
n.GeneratePropertyUsages (visitor, generationMode);
}
// Returns a list of preview properties that need to be set
public IEnumerable<PreviewProperty> GetPreviewProperties ()
{
var properties = new List<PreviewProperty> ();
foreach (var tnode in nodes.Where (x => x is TextureNode).Cast<TextureNode> ())
{
properties.Add (tnode.GetPreviewProperty ());
}
foreach (var subNode in nodes.Where (x=>x is SubGraphNode).Cast<SubGraphNode> ())
{
if (subNode.subGraphAsset != null)
properties.AddRange (subNode.subGraphAsset.GetPreviewProperties ());
}
return properties.Distinct();
}
}
}

8
UnityProject/Assets/Editor/Material/MaterialSubGraph.cs.meta


fileFormatVersion: 2
guid: 4b00854e54a3ed940813fa47dec62d38
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

34
UnityProject/Assets/Editor/Material/MaterialSubGraphGUI.cs


using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using System.Reflection;
namespace UnityEditor.Graphs.Material
{
class MaterialSubGraphGUI : BaseMaterialGraphGUI
{
public override void NodeGUI(Node n)
{
// Handle node selection
SelectNode(n);
// Make node minimize, etc. buttons
// Make default input slots
foreach (Slot s in n.inputSlots)
LayoutSlot(s, s.title, false, true, false, Styles.varPinIn);
// Make custom node UI
n.NodeUI(this);
// Make default output slots
foreach (Slot s in n.outputSlots)
LayoutSlot(s, s.title, true, false, true, Styles.varPinOut);
var subnode = n as SubGraphIOBaseNode;
if (subnode != null)
subnode.FooterUI (this);
DragNodes();
}
}
}

8
UnityProject/Assets/Editor/Material/MaterialSubGraphGUI.cs.meta


fileFormatVersion: 2
guid: 996990fe8c018a74aa83cd7a1f90141e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

156
UnityProject/Assets/Editor/Material/MaterialWindow.cs


#define DEBUG_MAT_GEN
using UnityEngine;
using System.IO;
namespace UnityEditor.Graphs.Material
{
class MaterialWindow : EditorWindow
{
[MenuItem("Window/Material")]
public static void OpenMenu ()
{
GetWindow<MaterialWindow>();
}
[MenuItem("Assets/Create/Shader Graph", false, 208)]
public static void CreateMaterialGraph()
{
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, DoCreateShaderGraphAsset, "New Shader Graph.ShaderGraph", null, null);
}
[MenuItem("Assets/Create/Shader Sub-Graph", false, 209)]
public static void CreateMaterialSubGraph()
{
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, DoCreateShaderSubGraphAsset, "New Shader SubGraph.ShaderSubGraph", null, null);
}
private static void DoCreateShaderGraphAsset (int instanceId, string pathName, string resourceFile)
{
var graph = CreateInstance<MaterialGraph>();
graph.name = Path.GetFileName (pathName);
AssetDatabase.CreateAsset (graph, pathName);
graph.CreateSubAssets ();
}
private static void DoCreateShaderSubGraphAsset(int instanceId, string pathName, string resourceFile)
{
var graph = CreateInstance<MaterialSubGraph>();
graph.name = Path.GetFileName(pathName);
AssetDatabase.CreateAsset(graph, pathName);
graph.CreateSubAssets();
}
private MaterialGraph m_MaterialGraph;
private MaterialGraphGUI m_MaterialGraphGUI;
private MaterialSubGraph m_MaterialSubGraph;
private MaterialSubGraphGUI m_MaterialSubGraphGUI;
private BaseMaterialGraphGUI m_ActiveGUI;
private ScriptableObject m_ActiveGraph;
private bool shouldRepaint
{
get
{
return m_MaterialGraph != null && m_MaterialGraph.currentGraph != null && m_MaterialGraph.currentGraph.requiresRepaint
|| m_MaterialSubGraph != null && m_MaterialSubGraph.requiresRepaint;
}
}
void Update ()
{
if (shouldRepaint)
Repaint();
}
void OnSelectionChange()
{
MaterialWindow.DebugMaterialGraph ( "Got OnSelection Change: " + Selection.activeObject);
if (Selection.activeObject == null || !EditorUtility.IsPersistent(Selection.activeObject))
return;
if (Selection.activeObject is MaterialSubGraph)
{
var selection = Selection.activeObject as MaterialSubGraph;
if (selection != m_MaterialSubGraph)
{
m_MaterialSubGraph = selection;
m_MaterialSubGraphGUI = null;
m_MaterialGraph = null;
m_MaterialSubGraph.GeneratePreviewShaders ();
}
if (m_MaterialSubGraphGUI == null)
{
m_MaterialSubGraphGUI = CreateInstance<MaterialSubGraphGUI>();
m_MaterialSubGraphGUI.hideFlags = HideFlags.HideAndDontSave;
m_MaterialSubGraphGUI.graph = m_MaterialSubGraph;
}
m_ActiveGUI = m_MaterialSubGraphGUI;
m_ActiveGraph = m_MaterialSubGraph;
}
else if(Selection.activeObject is MaterialGraph)
{
var selection = Selection.activeObject as MaterialGraph;
MaterialWindow.DebugMaterialGraph ("Selection: " + selection);
MaterialWindow.DebugMaterialGraph("Existing: " + m_MaterialGraph);
if (selection != m_MaterialGraph)
{
m_MaterialGraph = selection;
m_MaterialSubGraph = null;
m_MaterialGraphGUI = null;
m_MaterialGraph.currentGraph.GeneratePreviewShaders();
}
if (m_MaterialGraphGUI == null)
{
m_MaterialGraphGUI = CreateInstance<MaterialGraphGUI>();
m_MaterialGraphGUI.hideFlags = HideFlags.HideAndDontSave;
m_MaterialGraphGUI.graph = m_MaterialGraph.currentGraph;
m_MaterialGraphGUI.materialGraph = m_MaterialGraph;
}
m_ActiveGUI = m_MaterialGraphGUI;
m_ActiveGraph = m_MaterialGraph;
}
Repaint();
}
void OnGUI ()
{
if (m_ActiveGraph == null || m_ActiveGUI == null)
{
GUILayout.Label("No Graph selected");
return;
}
if(m_ActiveGUI == m_MaterialGraphGUI)
{
m_MaterialGraphGUI.graph = m_MaterialGraph.currentGraph;
m_MaterialGraphGUI.materialGraph = m_MaterialGraph;
}
else if(m_ActiveGUI == m_MaterialSubGraphGUI)
{
m_MaterialSubGraphGUI.graph = m_MaterialSubGraph;
}
m_ActiveGUI.BeginGraphGUI(this, new Rect(0, 0, position.width - 300, position.height));
m_ActiveGUI.OnGraphGUI();
m_ActiveGUI.EndGraphGUI();
if (m_ActiveGUI == m_MaterialGraphGUI)
m_MaterialGraphGUI.RenderOptions(new Rect(position.width - 300, 0, 300, position.height), m_MaterialGraph);
}
public static void DebugMaterialGraph(string s)
{
#if DEBUG_MAT_GEN
Debug.Log (s);
#endif
}
}
}

8
UnityProject/Assets/Editor/Material/MaterialWindow.cs.meta


fileFormatVersion: 2
guid: efbdf650af539bf4f872f46d9af5d72e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

5
UnityProject/Assets/Editor/Material/Nodes.meta


fileFormatVersion: 2
guid: 1722e198c31ecfd479a7a9841c53c1cc
folderAsset: yes
DefaultImporter:
userData:

30
UnityProject/Assets/Editor/Material/Nodes/AbsoluteNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Absolute Node")]
class AbsoluteNode : Function1Input, IGeneratesFunction
{
public override void Init()
{
name = "AbsoluteNode";
base.Init();
}
protected override string GetFunctionName () {return "unity_absolute_"+precision;}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_absolute_" + precision + " (" + precision + "4 arg1)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return abs(arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/AbsoluteNode.cs.meta


fileFormatVersion: 2
guid: 4b496ffd32c22d94bb525897d152da05
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

50
UnityProject/Assets/Editor/Material/Nodes/AddNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Math/Add Node")]
class AddNode : FunctionMultiInput, IGeneratesFunction
{
[SerializeField]
private float m_DefaultValue = 0.0f;
public override void Init()
{
name = "AddNode";
base.Init();
}
protected override string GetFunctionName () {return "unity_add_"+precision;}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_add_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 + arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
public override Vector4 GetNewSlotDefaultValue ()
{
return Vector4.zero;
}
public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck ();
m_DefaultValue = EditorGUILayout.FloatField("", m_DefaultValue, GUILayout.Width(64));
if (EditorGUI.EndChangeCheck ())
RegeneratePreviewShaders ();
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/AddNode.cs.meta


fileFormatVersion: 2
guid: 357a15b35b0cd9e47a66e10c5b627fcd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

486
UnityProject/Assets/Editor/Material/Nodes/BaseMaterialNode.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditorInternal;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue)]
public class TitleAttribute : Attribute
{
public string m_Title;
public TitleAttribute(string title) { this.m_Title = title; }
}
public enum Precision
{
Default = 0, // half
Full = 1,
Fixed = 2,
}
public class PreviewProperty
{
public string m_Name;
public PropertyType m_PropType;
public Color m_Color;
public Texture2D m_Texture;
public Vector4 m_Vector4;
}
public enum PreviewMode
{
Preview2D,
Preview3D
}
public abstract class BaseMaterialNode : Node, IGenerateProperties
{
#region Fields
private const int kPreviewWidth = 64;
private const int kPreviewHeight = 64;
private UnityEngine.Material m_Material;
[SerializeField]
private List<SlotDefaultValue> m_SlotDefaultValues;
#endregion
#region Properties
internal PixelGraph pixelGraph { get { return graph as PixelGraph; } }
public bool generated { get; set; }
// Nodes that want to have a preview area can override this and return true
public virtual bool hasPreview { get { return false; } }
public virtual PreviewMode previewMode { get { return PreviewMode.Preview2D; } }
public bool isSelected { get; set; }
// lookup custom slot properties
public void SetSlotDefaultValue (string slotName, SlotDefaultValue defaultValue)
{
var existingValue = m_SlotDefaultValues.FirstOrDefault (x => x.slotName == slotName);
if (existingValue != null)
m_SlotDefaultValues.Remove (existingValue);
if (defaultValue == null)
return;
m_SlotDefaultValues.Add (defaultValue);
}
public string precision
{
get { return "half"; }
}
public string[] m_PrecisionNames = {"half"};
public SlotDefaultValue GetSlotDefaultValue (string slotName)
{
return m_SlotDefaultValues.FirstOrDefault (x => x.slotName == slotName);
}
private UnityEngine.Material previewMaterial
{
get
{
if (m_Material == null)
m_Material = new UnityEngine.Material(Shader.Find("Diffuse")) { hideFlags = HideFlags.DontSave };
return m_Material;
}
}
private PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;
private bool needsUpdate
{
get { return true; }
}
#endregion
public virtual void Init ()
{
hideFlags = HideFlags.HideInHierarchy;
}
void OnEnable ()
{
if (m_SlotDefaultValues == null) {
m_SlotDefaultValues = new List<SlotDefaultValue>();
}
}
public override void NodeUI (GraphGUI host)
{
base.NodeUI(host);
if (hasPreview)
OnPreviewGUI();
}
protected virtual void OnPreviewGUI ()
{
if (!ShaderUtil.hardwareSupportsRectRenderTexture)
return;
GUILayout.BeginHorizontal(GUILayout.MinWidth (kPreviewWidth + 10), GUILayout.MinWidth (kPreviewHeight + 10));
GUILayout.FlexibleSpace();
var rect = GUILayoutUtility.GetRect(kPreviewWidth, kPreviewHeight, GUILayout.ExpandWidth(false));
var preview = RenderPreview (rect);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUI.DrawTexture (rect, preview, ScaleMode.StretchToFill, false);
}
#region Nodes
// 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<BaseMaterialNode> CollectDependentNodes()
{
var nodeList = new List<BaseMaterialNode>();
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 IEnumerable<BaseMaterialNode> CollectChildNodesByExecutionOrder(Slot slotToUse = null, bool includeSelf = true)
{
var nodeList = new List<BaseMaterialNode>();
CollectChildNodesByExecutionOrder (nodeList, slotToUse, includeSelf);
return nodeList;
}
public IEnumerable<BaseMaterialNode> CollectChildNodesByExecutionOrder (List<BaseMaterialNode> nodeList, Slot slotToUse = null, bool includeSelf = true)
{
if (slotToUse != null && !slots.Contains(slotToUse))
{
Debug.LogError("Attempting to collect nodes by execution order with an invalid slot on: " + name);
return nodeList;
}
NodeUtils.CollectChildNodesByExecutionOrder (nodeList, this, slotToUse);
if (!includeSelf)
nodeList.Remove (this);
return nodeList;
}
#endregion
#region Previews
protected virtual void SetEditorPreviewMaterialValues ()
{
if (!needsUpdate)
return;
if (previewMaterial.HasProperty ("EDITOR_TIME"))
{
var time = (float)EditorApplication.timeSinceStartup;
previewMaterial.SetVector("EDITOR_TIME", new Vector4(time / 20.0f, time, time * 2.0f, time*3));
}
if (previewMaterial.HasProperty("EDITOR_SIN_TIME"))
{
var time = (float)EditorApplication.timeSinceStartup;
previewMaterial.SetVector("EDITOR_SIN_TIME",
new Vector4(
Mathf.Sin(time / 8.0f),
Mathf.Sin(time / 4.0f),
Mathf.Sin(time / 2.0f),
Mathf.Sin(time)));
}
}
public virtual bool UpdatePreviewMaterial ()
{
MaterialWindow.DebugMaterialGraph("RecreateShaderAndMaterial : " + name + "_" + GetInstanceID());
var resultShader = ShaderGenerator.GeneratePreviewShader (this, out m_GeneratedShaderMode);
MaterialWindow.DebugMaterialGraph (resultShader);
if (previewMaterial.shader.name != "Diffuse")
DestroyImmediate(previewMaterial.shader, true);
previewMaterial.shader = UnityEditorInternal.InternalEditorUtility.CreateShaderAsset (resultShader);
previewMaterial.shader.hideFlags = HideFlags.DontSave;
return true;
}
// this function looks at all the nodes that have a
// dependency on this node. They will then have their
// preview regenerated.
public void RegeneratePreviewShaders()
{
CollectDependentNodes()
.Where(x => x.hasPreview)
.All(s => s.UpdatePreviewMaterial ());
}
private static Mesh[] s_Meshes = { null, null, null, null };
/// <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 (s_Meshes[0] == null)
{
GameObject 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 bmg = (graph as BaseMaterialGraph);
if (bmg == null)
return null;
var previewUtil = bmg.previewUtility;
previewUtil.BeginPreview (targetSize, GUIStyle.none);
// update the time in the preview material
SetEditorPreviewMaterialValues ();
if (m_GeneratedShaderMode == PreviewMode.Preview3D)
{
previewUtil.m_Camera.transform.position = -Vector3.forward * 5;
previewUtil.m_Camera.transform.rotation = Quaternion.identity;
var amb = new Color(.2f, .2f, .2f, 0);
previewUtil.m_Light[0].intensity = .5f;
previewUtil.m_Light[0].transform.rotation = Quaternion.Euler(50f, 50f, 0);
previewUtil.m_Light[1].intensity = .5f;
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);
bool oldFog = RenderSettings.fog;
Unsupported.SetRenderSettingsUseFogNoDirty (false);
previewUtil.m_Camera.Render();
Unsupported.SetRenderSettingsUseFogNoDirty (oldFog);
InternalEditorUtility.RemoveCustomLighting ();
}
else
{
Graphics.Blit(null, previewMaterial);
}
return previewUtil.EndPreview ();
}
private void SetPreviewMaterialProperty(PreviewProperty previewProperty)
{
switch (previewProperty.m_PropType)
{
case PropertyType.Texture2D:
previewMaterial.SetTexture(previewProperty.m_Name, previewProperty.m_Texture);
break;
case PropertyType.Color:
previewMaterial.SetColor(previewProperty.m_Name, previewProperty.m_Color);
break;
case PropertyType.Vector4:
previewMaterial.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
}
}
protected void SetDependentPreviewMaterialProperty (PreviewProperty previewProperty)
{
var dependentNodes = CollectDependentNodes ();
foreach (var node in dependentNodes)
{
if (node.hasPreview)
node.SetPreviewMaterialProperty (previewProperty);
}
}
public virtual void UpdatePreviewProperties()
{
foreach (var s in inputSlots)
{
if (s.edges.Count > 0)
continue;
var defaultInput = GetSlotDefaultValue (s.name);
if (defaultInput == null)
continue;
var pp = new PreviewProperty
{
m_Name = defaultInput.inputName,
m_PropType = PropertyType.Vector4,
m_Vector4 = defaultInput.defaultValue
};
SetDependentPreviewMaterialProperty (pp);
}
}
#endregion
#region Slots
public virtual IEnumerable<Slot> GetValidInputSlots ()
{
return inputSlots;
}
public virtual string GetOutputVariableNameForSlot (Slot s, GenerationMode generationMode)
{
if (s.isInputSlot) Debug.LogError ("Attempting to use input slot (" + s + ") for output!");
if (!slots.Contains(s)) Debug.LogError("Attempting to use slot (" + s + ") for output on a node that does not have this slot!");
return GetOutputVariableNameForNode () + "_" + s.name;
}
public virtual string GetOutputVariableNameForNode ()
{
return name + "_" + Math.Abs(GetInstanceID());
}
public virtual Vector4 GetNewSlotDefaultValue ()
{
return Vector4.one;
}
public new void AddSlot(Slot slot)
{
AddSlot (slot, GetNewSlotDefaultValue ());
}
public void AddSlot(Slot slot, Vector4 defaultValue)
{
base.AddSlot(slot);
// slots are not serialzied but the default values are
// because of this we need to see if the default has
// already been set
// if it has... do nothing.
MaterialWindow.DebugMaterialGraph ("Node ID: " + GetInstanceID ());
MaterialWindow.DebugMaterialGraph ("Node Name: " + GetOutputVariableNameForNode ());
if (GetSlotDefaultValue(slot.name) == null)
SetSlotDefaultValue(slot.name, new SlotDefaultValue(defaultValue, this, slot.name, true));
var slotthing = GetSlotDefaultValue (slot.name);
MaterialWindow.DebugMaterialGraph ("Slot Thing: " + slotthing.inputName);
}
public override void RemoveSlot (Slot slot)
{
SetSlotDefaultValue(slot.name, null);
base.RemoveSlot(slot);
}
public string GenerateSlotName (SlotType type)
{
var slotsToCheck = type == SlotType.InputSlot ? inputSlots.ToArray() : outputSlots.ToArray();
string format = type == SlotType.InputSlot ? "I{0:00}" : "O{0:00}";
int index = slotsToCheck.Length;
var name = string.Format (format, index);
if (slotsToCheck.All (x => x.name != name))
return name;
index = 0;
do {
name = string.Format (format, index++);
} while (slotsToCheck.Any(x => x.name == name));
return name;
}
#endregion
public virtual void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
if (!generationMode.IsPreview ())
return;
foreach (var inputSlot in inputSlots)
{
if (inputSlot.edges.Count > 0)
continue;
var defaultForSlot = GetSlotDefaultValue(inputSlot.name);
defaultForSlot.GeneratePropertyBlock(visitor, generationMode);
}
}
public virtual void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (!generationMode.IsPreview ())
return;
foreach (var inputSlot in inputSlots)
{
if (inputSlot.edges.Count > 0)
continue;
var defaultForSlot = GetSlotDefaultValue(inputSlot.name);
defaultForSlot.GeneratePropertyUsages(visitor, generationMode);
}
}
public Slot FindInputSlot (string name)
{
var slot = inputSlots.FirstOrDefault(x => x.name == name);
if (slot == null)
Debug.LogError("Input slot: " + name + " could be found on node " + GetOutputVariableNameForNode() );
return slot;
}
public Slot FindOutputSlot(string name)
{
var slot = outputSlots.FirstOrDefault(x => x.name == name);
if (slot == null)
Debug.LogError("Output slot: " + name + " could be found on node " + GetOutputVariableNameForNode());
return slot;
}
protected string GetSlotValue (Slot inputSlot, GenerationMode generationMode)
{
bool pointInputConnected = inputSlot.edges.Count > 0;
string inputValue;
if (pointInputConnected)
{
var dataProvider = inputSlot.edges[0].fromSlot.node as BaseMaterialNode;
inputValue = dataProvider.GetOutputVariableNameForSlot(inputSlot.edges[0].fromSlot, generationMode);
}
else
{
var defaultValue = GetSlotDefaultValue(inputSlot.name);
inputValue = defaultValue.GetDefaultValue(generationMode);
}
return inputValue;
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/BaseMaterialNode.cs.meta


fileFormatVersion: 2
guid: a4da4d7c02dcbdd4f9ef2d3b1106879a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

67
UnityProject/Assets/Editor/Material/Nodes/BlendNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Art/Blend Node")]
class BlendNode : Function2Input, IGeneratesFunction
{
public override void Init()
{
name = "BlendNode";
base.Init();
}
public enum Operation {
Normal,
Additive,
}
[SerializeField]
private Operation m_Operation;
[SerializeField]
private float m_Blend = 0.5f;
private static readonly string[] kOpNames = new[]
{
"normal",
"add"
};
protected override string GetFunctionName() { return "unity_blend_"+ kOpNames[(int)m_Operation] +"_"+precision; }
protected override string GetFunctionCallBody (string input1Value, string input2Value)
{
return GetFunctionName() + "("+input1Value+", "+input2Value+", "+m_Blend+")";
}
protected void AddOperationBody (ShaderGenerator visitor, string name, string body, string precision)
{
var outputString = new ShaderGenerator ();
outputString.AddShaderChunk("inline "+precision+"4 unity_blend_"+name+"_"+precision+" ("+precision+"4 arg1, "+precision+"4 arg2, "+precision+" blend)", false);
outputString.AddShaderChunk("{", false); outputString.Indent();
outputString.AddShaderChunk(body, false);
outputString.Deindent(); outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck ();
m_Blend = GUILayout.HorizontalSlider(m_Blend, 0f, 1f, GUILayout.Width(64));
m_Operation = (Operation)EditorGUILayout.EnumPopup (m_Operation);
if (EditorGUI.EndChangeCheck ())
RegeneratePreviewShaders ();
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
foreach (var precision in m_PrecisionNames)
{
AddOperationBody (visitor, kOpNames[(int)Operation.Normal], "return lerp(arg1, arg2, blend);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.Additive], "return (arg1 + arg2) * blend;", precision);
}
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/BlendNode.cs.meta


fileFormatVersion: 2
guid: 909ffbb62e82bfb4abbeeb93022c6e9b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

30
UnityProject/Assets/Editor/Material/Nodes/ClampNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Clamp Node")]
class ClampNode : Function3Input, IGeneratesFunction
{
public override void Init()
{
name = "ClampNode";
base.Init();
}
protected override string GetFunctionName () {return "unity_clamp_"+precision;}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_clamp_" + precision + " (" + precision + "4 arg1, " + precision + "4 minval, " + precision + "4 maxval)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return clamp(arg1, minval, maxval);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/ClampNode.cs.meta


fileFormatVersion: 2
guid: b58e88ce87f05b241b7dc5d9a31bac69
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

99
UnityProject/Assets/Editor/Material/Nodes/ColorNode.cs


using System;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Generate/Color Node")]
class ColorNode : PropertyNode, IGeneratesBodyCode
{
[SerializeField]
private Color m_Color;
private const string kOutputSlotName = "Color";
public override void Init()
{
base.Init ();
name = "ColorNode";
AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
}
public override PropertyType propertyType
{
get { return PropertyType.Color; }
}
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
if (HasBoundProperty() || !generationMode.IsPreview ())
return;
visitor.AddShaderProperty (new ColorPropertyChunk (GetPropertyName (), GetPropertyName (), m_Color, true));
}
public override string GetOutputVariableNameForSlot(Slot s, GenerationMode generationMode)
{
return GetPropertyName();
}
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (HasBoundProperty() || !generationMode.IsPreview ())
return;
visitor.AddShaderChunk("float4 " + GetPropertyName() + ";", true);
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
// we only need to generate node code if we are using a constant... otherwise we can just refer to the property :)
if (HasBoundProperty() || generationMode.IsPreview ())
return;
visitor.AddShaderChunk (precision+"4 " + GetPropertyName () + " = "+precision+"4 (" + m_Color.r + ", " + m_Color.g + ", " + m_Color.b + ", " + m_Color.a + ");", true);
}
public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck ();
m_Color = EditorGUILayout.ColorField(m_Color);
if (EditorGUI.EndChangeCheck())
{
var boundProp = boundProperty as ColorProperty;
if (boundProp != null)
{
boundProp.defaultColor = m_Color;
}
UpdatePreviewProperties ();
}
}
public override void BindProperty(ShaderProperty property, bool rebuildShaders)
{
base.BindProperty(property, rebuildShaders);
var colorProp = property as ColorProperty;
if (colorProp)
{
m_Color = colorProp.defaultColor;
}
if (rebuildShaders)
RegeneratePreviewShaders();
else
UpdatePreviewProperties();
}
public override PreviewProperty GetPreviewProperty ()
{
return new PreviewProperty {
m_Name = GetPropertyName (),
m_PropType = PropertyType.Color,
m_Color = m_Color
};
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/ColorNode.cs.meta


fileFormatVersion: 2
guid: 325c0e24c20746345a5f90dc201973f8
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

72
UnityProject/Assets/Editor/Material/Nodes/ColorizeNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Art/Colorize Node")]
class ColorizeNode : Function1Input, IGeneratesFunction
{
[SerializeField]
private Color m_Color = Color.blue;
[SerializeField]
private float m_Colorization = 0.0f;
[SerializeField]
private float m_Brightness = 1.0f;
[SerializeField]
private float m_Contrast = 1.0f;
public override void Init()
{
name = "ColorizeNode";
base.Init();
}
protected override string GetFunctionName() {return ""; }
protected override string GetFunctionCallBody (string inputValue)
{
return "unity_colorize_"+precision+"("+inputValue+", "+precision+"4("+m_Color.r+", "+m_Color.g+", "+m_Color.b+", "+m_Color.a+"), "+m_Colorization+", "+m_Brightness+", "+m_Contrast+")";
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var thePrecisision in m_PrecisionNames)
{
outputString.AddShaderChunk ("inline " + thePrecisision + "4 unity_colorize_" + thePrecisision + " (" + thePrecisision + "4 arg1, " + thePrecisision + "4 color, " + thePrecisision + " amount, " + thePrecisision + " brightness, " + thePrecisision + " contrast)", false);
outputString.AddShaderChunk ("{", false);
outputString.Indent ();
outputString.AddShaderChunk (thePrecisision + "4 x = lerp(arg1, arg1 * color, amount);", false);
outputString.AddShaderChunk ("x *= brightness;", false);
outputString.AddShaderChunk ("x = pow(x, contrast);", false);
outputString.AddShaderChunk ("return x;", false);
outputString.Deindent ();
outputString.AddShaderChunk ("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
static float Slider (string title, float value, float from, float to)
{
GUILayout.BeginHorizontal ();
GUILayout.Label (title);
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64));
GUILayout.EndHorizontal ();
return value;
}
public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck ();
m_Color = EditorGUILayout.ColorField("Tint", m_Color);
m_Colorization = Slider ("Colorization", m_Colorization, 0f, 1f);
m_Brightness = Slider ("Brightness", m_Brightness, 0f, 2f);
m_Contrast = Slider ("Contrast", m_Contrast, 0.3f, 4f);
if (EditorGUI.EndChangeCheck ())
RegeneratePreviewShaders ();
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/ColorizeNode.cs.meta


fileFormatVersion: 2
guid: eb2553e0542079a4b86f8abe5ad4045e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

114
UnityProject/Assets/Editor/Material/Nodes/CombineNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Art/Combine Node")]
class CombineNode : Function2Input, IGeneratesFunction
{
public override void Init()
{
name = "CombineNode";
base.Init();
}
// Based on information from:
// http://photoblogstop.com/photoshop/photoshop-blend-modes-explained
// http://www.venture-ware.com/kevin/coding/lets-learn-math-photoshop-blend-modes/
// http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/
// http://dunnbypaul.net/blends/
public enum Operation {
Darken,
Multiply,
ColorBurn,
LinearBurn,
// TODO: DarkerColor (Darken, but based on luminosity)
Lighten,
Screen,
ColorDodge,
LinearDodge,
// TODO: LighterColor (Lighten, but based on luminosity)
Overlay,
SoftLight,
HardLight,
VividLight,
LinearLight,
PinLight,
HardMix,
Difference,
Exclusion,
Subtract,
Divide,
}
[SerializeField]
private Operation m_Operation;
private static readonly string[] kOpNames = new string [] {
"darken", "mul", "cburn", "lburn",
"lighten", "screen", "cdodge", "ldodge",
"overlay", "softl", "hardl", "vividl", "linearl", "pinl", "hardmix",
"diff", "excl", "sub", "div" };
protected override string GetFunctionName() { return "unity_combine_"+ kOpNames[(int)m_Operation] +"_"+precision; }
protected void AddOperationBody(ShaderGenerator visitor, string combineName, string body, string combinePrecision)
{
var outputString = new ShaderGenerator ();
outputString.AddShaderChunk ("inline " + combinePrecision + "4 unity_combine_" + combineName + "_" + combinePrecision + " (" + combinePrecision + "4 arg1, " + combinePrecision + "4 arg2)", false);
outputString.AddShaderChunk ("{", false);
outputString.Indent ();
outputString.AddShaderChunk (body, false);
outputString.Deindent ();
outputString.AddShaderChunk ("}", false);
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck ();
m_Operation = (Operation)EditorGUILayout.EnumPopup (m_Operation);
if (EditorGUI.EndChangeCheck ())
RegeneratePreviewShaders ();
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
foreach (var precision in m_PrecisionNames)
{
// Darken group
AddOperationBody (visitor, kOpNames[(int)Operation.Darken], "return min(arg1, arg2);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.Multiply], "return arg1 * arg2;", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.ColorBurn], "return 1 - (1-arg1)/(arg2+1e-5);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.LinearBurn], "return arg1 + arg2 - 1;", precision);
// Lighten group
AddOperationBody (visitor, kOpNames[(int)Operation.Lighten], "return max(arg1, arg2);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.Screen], "return 1- (1-arg1) * (1-arg2);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.ColorDodge], "return arg1/(1-arg2+1e-5);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.LinearDodge], "return arg1 + arg2;", precision);
// Contrast group
AddOperationBody (visitor, kOpNames[(int)Operation.Overlay], "return (arg1 < 0.5)? arg1*arg2*2: 1-(1-arg1)*(1-arg2)*2;", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.SoftLight],
"return (1-arg1)*arg1*arg2 + arg1*(1- (1-arg1)*(1-arg2));", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.HardLight], "return (arg2 < 0.5)? arg1*arg2*2: 1-(1-arg1)*(1-arg2)*2;", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.VividLight],
"return (arg2 < 0.5)? 1- (1-arg1)/(2*arg2+1e-5): arg1/(1-2*(arg2-0.5)+1e-5);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.LinearLight], "return (arg2 < 0.5)? arg1+(2*arg2)-1: arg1+2*(arg2-0.5);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.PinLight], "return (arg2 < 0.5)? min(arg1, 2*arg2): max(arg1, 2*(arg2-0.5));", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.HardMix], "return (arg2 < 1-arg1)? "+precision+"(0):"+precision+"(1);", precision);
// Inversion group
AddOperationBody (visitor, kOpNames[(int)Operation.Difference], "return abs(arg2-arg1);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.Exclusion], "return arg1 + arg2 - arg1*arg2*2;", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.Subtract], "return max(arg2-arg1, 0.0);", precision);
AddOperationBody (visitor, kOpNames[(int)Operation.Divide], "return arg1 / (arg2+1e-5);", precision);
}
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/CombineNode.cs.meta


fileFormatVersion: 2
guid: 3738e97908dea1f4bbc5e5a7cf562ecc
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

30
UnityProject/Assets/Editor/Material/Nodes/DivNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Div Node")]
class DivNode : Function2Input, IGeneratesFunction
{
public override void Init()
{
name = "DivNode";
base.Init();
}
protected override string GetFunctionName () {return "unity_div_"+precision;}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_div_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 / arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/DivNode.cs.meta


fileFormatVersion: 2
guid: 8e9d13e64300d6942ad51651d39f9ac6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

14
UnityProject/Assets/Editor/Material/Nodes/DotNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Dot Node")]
class DotNode : Function2Input
{
public override void Init()
{
name = "DotNode";
base.Init();
}
protected override string GetFunctionName() { return "dot"; }
}
}

8
UnityProject/Assets/Editor/Material/Nodes/DotNode.cs.meta


fileFormatVersion: 2
guid: 97e1d998eea5d644095671979ecf2e54
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

47
UnityProject/Assets/Editor/Material/Nodes/Extensions.cs


using System;
using System.Collections.Generic;
using System.Linq;
namespace UnityEditor.Graphs.Material
{
internal static class Extensions
{
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first,
IEnumerable<TSource> second , Func<TSource, TSource, bool> comparer )
{
return first.Except(second, new LambdaComparer<TSource>(comparer));
}
public class LambdaComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> _lambdaComparer;
private readonly Func<T, int> _lambdaHash;
public LambdaComparer(Func<T, T, bool> lambdaComparer) :
this(lambdaComparer, o => 0)
{
}
public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
{
if (lambdaComparer == null)
throw new ArgumentNullException("lambdaComparer");
if (lambdaHash == null)
throw new ArgumentNullException("lambdaHash");
_lambdaComparer = lambdaComparer;
_lambdaHash = lambdaHash;
}
public bool Equals(T x, T y)
{
return _lambdaComparer(x, y);
}
public int GetHashCode(T obj)
{
return _lambdaHash(obj);
}
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/Extensions.cs.meta


fileFormatVersion: 2
guid: adf5c8d21f606c848a855790481093b2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

31
UnityProject/Assets/Editor/Material/Nodes/FresnelNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Fresnel Node")]
class FresnelNode : Function2Input, IGeneratesFunction
{
public override void Init()
{
name = "FresnelNode";
base.Init();
}
protected override string GetFunctionName() { return "unity_fresnel_" + precision; }
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_fresnel_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return (1.0 - dot (normalize (arg1.xyz), normalize (arg2.xyz))).xxxx;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/FresnelNode.cs.meta


fileFormatVersion: 2
guid: 06ab35c1dfe05414787df3ea2772d507
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

57
UnityProject/Assets/Editor/Material/Nodes/Function1Input.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
abstract class Function1Input : BaseMaterialNode, IGeneratesBodyCode
{
public override bool hasPreview
{
get { return true; }
}
public override void Init()
{
base.Init ();
AddSlot (new Slot (SlotType.OutputSlot, GetOutputSlotName ()));
AddSlot (new Slot (SlotType.InputSlot, GetInputSlotName ()));
}
protected virtual string GetInputSlotName() {return "Input";}
protected virtual string GetOutputSlotName () {return "Output";}
protected abstract string GetFunctionName ();
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot (GetOutputSlotName ());
var inputSlot = FindInputSlot (GetInputSlotName ());
if (inputSlot == null || outputSlot == null)
{
Debug.LogError ("Invalid slot configuration on node: " + name);
return;
}
bool inputConnected = inputSlot.edges.Count > 0;
string inputValue;
if (inputConnected)
{
var inputDateProvider = inputSlot.edges[0].fromSlot.node as BaseMaterialNode;
inputValue = inputDateProvider.GetOutputVariableNameForSlot (inputSlot.edges[0].fromSlot, generationMode);
}
else
{
var defaultValue = GetSlotDefaultValue(inputSlot.name);
inputValue = defaultValue.GetDefaultValue (generationMode);
}
visitor.AddShaderChunk(precision + "4 " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(inputValue) + ";", true);
}
protected virtual string GetFunctionCallBody (string inputValue)
{
return GetFunctionName() + " (" + inputValue + ")";
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/Function1Input.cs.meta


fileFormatVersion: 2
guid: 9e8ba3e80e4d9e947a9377e9e73fdca9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

46
UnityProject/Assets/Editor/Material/Nodes/Function2Input.cs


using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
abstract class Function2Input : BaseMaterialNode, IGeneratesBodyCode
{
public override bool hasPreview { get { return true; } }
public override void Init()
{
base.Init();
AddSlot(new Slot(SlotType.OutputSlot, GetOutputSlotName ()));
AddSlot(new Slot(SlotType.InputSlot, GetInputSlot1Name ()));
AddSlot(new Slot(SlotType.InputSlot, GetInputSlot2Name ()));
}
protected virtual string GetInputSlot1Name() {return "Input1";}
protected virtual string GetInputSlot2Name() {return "Input2";}
protected virtual string GetOutputSlotName() {return "Output";}
protected abstract string GetFunctionName();
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot (GetOutputSlotName ());
var inputSlot1 = FindInputSlot (GetInputSlot1Name ());
var inputSlot2 = FindInputSlot (GetInputSlot2Name ());
if (inputSlot1 == null || inputSlot2 == null || outputSlot == null)
{
Debug.LogError("Invalid slot configuration on node: " + name);
return;
}
string input1Value = GetSlotValue (inputSlot1, generationMode);
string input2Value = GetSlotValue (inputSlot2, generationMode);
visitor.AddShaderChunk(precision + "4 " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(input1Value, input2Value) + ";", true);
}
protected virtual string GetFunctionCallBody (string input1Value, string input2Value)
{
return GetFunctionName() + " (" + input1Value + ", " + input2Value +")";
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/Function2Input.cs.meta


fileFormatVersion: 2
guid: 892d91fa7ade87541bac6c322a97b1bb
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

51
UnityProject/Assets/Editor/Material/Nodes/Function3Input.cs


using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
abstract class Function3Input : BaseMaterialNode, IGeneratesBodyCode
{
public override bool hasPreview { get { return true; } }
public override void Init()
{
base.Init ();
AddSlot (new Slot (SlotType.OutputSlot, GetOutputSlotName ()));
AddSlot (new Slot (SlotType.InputSlot, GetInputSlot1Name ()));
AddSlot (new Slot (SlotType.InputSlot, GetInputSlot2Name ()));
AddSlot (new Slot (SlotType.InputSlot, GetInputSlot3Name ()));
}
protected virtual string GetInputSlot1Name() { return "Input1"; }
protected virtual string GetInputSlot2Name() { return "Input2"; }
protected virtual string GetInputSlot3Name() { return "Input3"; }
protected virtual string GetOutputSlotName() { return "Output"; }
protected abstract string GetFunctionName();
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot (GetOutputSlotName ());
var inputSlot1 = FindInputSlot (GetInputSlot1Name ());
var inputSlot2 = FindInputSlot (GetInputSlot2Name ());
var inputSlot3 = FindInputSlot (GetInputSlot3Name ());
if (inputSlot1 == null || inputSlot2 == null || inputSlot3 == null || outputSlot == null)
{
Debug.LogError("Invalid slot configuration on node: " + name);
return;
}
string input1Value = GetSlotValue(inputSlot1, generationMode);
string input2Value = GetSlotValue(inputSlot2, generationMode);
string input3Value = GetSlotValue(inputSlot2, generationMode);
visitor.AddShaderChunk(precision + "4 " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(input1Value, input2Value, input3Value) + ";", true);
}
protected virtual string GetFunctionCallBody(string inputValue1, string inputValue2, string inputValue3)
{
return GetFunctionName() + " (" + inputValue1 + ", " + inputValue2 + ", " + inputValue3 + ")";
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/Function3Input.cs.meta


fileFormatVersion: 2
guid: e7d8fb926f570fb48b10d7d068d54123
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

83
UnityProject/Assets/Editor/Material/Nodes/FunctionMultiInput.cs


using System.Linq;
using UnityEngine;
using System.Collections.Generic;
namespace UnityEditor.Graphs.Material
{
abstract class FunctionMultiInput : BaseMaterialNode, IGeneratesBodyCode
{
private const string kOutputSlotName = "Output";
private const string kBaseInputSlotName = "Input";
public override bool hasPreview { get { return true; } }
public override void Init()
{
base.Init ();
AddSlot (new Slot (SlotType.OutputSlot, kOutputSlotName));
AddSlot (new Slot (SlotType.InputSlot, GetInputSlotName (0)));
AddSlot (new Slot (SlotType.InputSlot, GetInputSlotName (1)));
}
protected bool IsInputSlotConnected (int index)
{
var inputSlot = GetValidInputSlots ().FirstOrDefault(x => x.name == GetInputSlotName (index));
if (inputSlot == null)
{
Debug.LogError("Invalid slot configuration on node: " + name);
return false;
}
return inputSlot.edges.Count > 0;
}
private static string GetInputSlotName (int index) { return kBaseInputSlotName + (index); }
public override void InputEdgeChanged(Edge e)
{
base.InputEdgeChanged(e);
int inputSlotCount = GetValidInputSlots().Count();
if (IsInputSlotConnected(inputSlotCount - 1))
AddSlot(new Slot(SlotType.InputSlot, GetInputSlotName(inputSlotCount)));
else if (inputSlotCount > 2)
{
var lastSlot = inputSlots.FirstOrDefault (x => x.name == GetInputSlotName (inputSlotCount - 1));
if (lastSlot != null)
RemoveSlot (lastSlot);
}
}
protected abstract string GetFunctionName();
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = outputSlots.FirstOrDefault (x => x.name == kOutputSlotName);
if (outputSlot == null)
{
Debug.LogError ("Invalid slot configuration on node: " + name);
return;
}
var inputSlots = GetValidInputSlots ();
int inputSlotCount = inputSlots.Count ();
// build up a list of the valid input connections
var inputValues = new List<string> (inputSlotCount);
MaterialWindow.DebugMaterialGraph ("Generating On Node: " + GetOutputVariableNameForNode () + " - Preview is: " + generationMode);
inputValues.AddRange (inputSlots.Select (inputSlot => GetSlotValue (inputSlot, generationMode)));
visitor.AddShaderChunk (precision + "4 " + GetOutputVariableNameForSlot (outputSlot, generationMode) + " = " + GetFunctionCallBody (inputValues) + ";", true);
}
protected virtual string GetFunctionCallBody(List<string> inputValues)
{
string functionCall = inputValues[0];
for (int q = 1; q < inputValues.Count; ++q)
functionCall = GetFunctionName () + " (" + functionCall + ", " + inputValues[q] + ")";
return functionCall;
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/FunctionMultiInput.cs.meta


fileFormatVersion: 2
guid: 323a0eb1930dff241b4547716c8eb21f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

95
UnityProject/Assets/Editor/Material/Nodes/KaleidoscopeNode.cs


using System;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Fractal/Kaleidoscope Node")]
class KaleidoscopeNode : BaseMaterialNode, IGeneratesFunction, IGeneratesBodyCode
{
[SerializeField]
private int m_Iterations = 6;
private const string kPointInputName = "Point";
private const string kConstant1InputName = "Constant1";
private const string kConstant2InputName = "Constant2";
private const string kOutputSlotName = "Output";
public override bool hasPreview { get { return true; } }
public override void Init()
{
name = "KaleidoscopeNode";
base.Init();
AddSlot(new Slot(SlotType.InputSlot, kPointInputName));
AddSlot(new Slot(SlotType.InputSlot, kConstant1InputName));
AddSlot(new Slot(SlotType.InputSlot, kConstant2InputName));
AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_kaleidoscope_" + precision + " (" + precision + "2 p, " + precision + "4 c1, " + precision + "4 c2, int iterations)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("c1 = c1 * 2 - 1;", false);
outputString.AddShaderChunk("c2 = c2 * 2 - 1;", false);
outputString.AddShaderChunk("for (int n = 0; n < iterations; n++)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("p = c1.xy + p * c1.zw + " + precision + "2(dot(p, c2.xy), dot(p, c2.zw));", false);
outputString.AddShaderChunk("if(p.x < p.y) p.xy = -p.yx;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
outputString.AddShaderChunk("return " + precision + "4(p, 1, 1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot (kOutputSlotName);
var pointInput = FindInputSlot (kPointInputName);
var constant1Input = FindInputSlot (kConstant1InputName);
var constant2Input = FindInputSlot (kConstant2InputName);
if (outputSlot == null || pointInput == null || constant1Input == null || constant2Input == null)
{
Debug.LogError("Invalid slot configuration on node: " + name);
return;
}
string pointInputValue = GetSlotValue (pointInput, generationMode);
string constant1InputValue = GetSlotValue (constant1Input, generationMode);
string constant2InputValue = GetSlotValue (constant2Input, generationMode);
string outName = GetOutputVariableNameForSlot (outputSlot, generationMode);
visitor.AddShaderChunk (precision + "4 " + outName + " = unity_kaleidoscope_" + precision + "(" + pointInputValue + ".xy, " + constant1InputValue + ", " + constant2InputValue + ", " + m_Iterations + ");", false);
}
static float Slider(string title, float value, float from, float to)
{
GUILayout.BeginHorizontal();
GUILayout.Label(title);
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64));
GUILayout.EndHorizontal();
return value;
}
public override void NodeUI(Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck();
m_Iterations = (int)Slider("Iterations", (float)m_Iterations, 1, 50);
if (EditorGUI.EndChangeCheck())
RegeneratePreviewShaders();
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/KaleidoscopeNode.cs.meta


fileFormatVersion: 2
guid: dfc00afcda39bfa4fbd9bd6176f53477
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

14
UnityProject/Assets/Editor/Material/Nodes/LengthNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Length Node")]
class LengthNode : Function1Input
{
public override void Init()
{
name = "LengthNode";
base.Init();
}
protected override string GetFunctionName() { return "length"; }
}
}

8
UnityProject/Assets/Editor/Material/Nodes/LengthNode.cs.meta


fileFormatVersion: 2
guid: 52afae1b1271e864c9c6965dc738c2dd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

95
UnityProject/Assets/Editor/Material/Nodes/MandelbrotNode.cs


using System;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Fractal/Mandelbrot Node")]
class MandelbrotNode : BaseMaterialNode, IGeneratesFunction, IGeneratesBodyCode
{
[SerializeField]
private int m_Iterations = 6;
private const string kPointInputName = "Point";
private const string kConstantInputName = "Constant";
private const string kOutputSlotName = "Output";
public override bool hasPreview { get { return true; } }
public override void Init()
{
name = "MandelbrotNode";
base.Init();
AddSlot(new Slot(SlotType.InputSlot, kPointInputName));
AddSlot(new Slot(SlotType.InputSlot, kConstantInputName));
AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_mandelbrot_" + precision + " (" + precision + "2 p, " + precision + "2 c, float limit, float scale, int iterations)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + " zr = p.x * 4 - 2, zi = p.y * 4 - 2, dzr = 1, dzi = 0, r = 0, len2;", false);
outputString.AddShaderChunk("for (int n = 0; n < iterations; n++)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + " tmp1 = 2 * zr * zi + c.y; zr = zr * zr - zi * zi + c.x; zi = tmp1;", false);
outputString.AddShaderChunk(precision + " tmp2 = 2 * (dzr * zi + dzi * zr); dzr = 2 * (dzr * zr - dzi * zi) + 1; dzi = tmp2;", false);
outputString.AddShaderChunk("len2 = zr * zr + zi * zi;", false);
outputString.AddShaderChunk("if (len2 > 1000000 * limit) { r = n; break; }", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
outputString.AddShaderChunk("return scale * sqrt(len2 / (dzr * dzr + dzi * dzi)) * log(len2);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = outputSlots.FirstOrDefault(x => x.name == kOutputSlotName);
var pointInput = GetValidInputSlots().FirstOrDefault(x => x.name == kPointInputName);
var constantInput = GetValidInputSlots().FirstOrDefault(x => x.name == kConstantInputName);
if (outputSlot == null || pointInput == null || constantInput == null)
{
Debug.LogError("Invalid slot configuration on node: " + name);
return;
}
//TODO: This will break if there is NO input connected, use default in that case
var pointProvider = pointInput.edges[0].fromSlot.node as BaseMaterialNode;
var pointName = pointProvider.GetOutputVariableNameForSlot(pointInput.edges[0].fromSlot, generationMode);
var constantProvider = constantInput.edges[0].fromSlot.node as BaseMaterialNode;
var constantName = constantProvider.GetOutputVariableNameForSlot(constantInput.edges[0].fromSlot, generationMode);
string outName = GetOutputVariableNameForSlot(outputSlot, generationMode);
visitor.AddShaderChunk(precision + "4 " + outName + " = unity_mandelbrot_" + precision + "(" + pointName + ".xy, " + constantName + ".xy, " + constantName + ".z, " + constantName + ".w, " + m_Iterations + ");", false);
}
static float Slider(string title, float value, float from, float to)
{
GUILayout.BeginHorizontal();
GUILayout.Label(title);
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64));
GUILayout.EndHorizontal();
return value;
}
public override void NodeUI(Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck();
m_Iterations = (int)Slider("Iterations", (float)m_Iterations, 1, 50);
if (EditorGUI.EndChangeCheck())
RegeneratePreviewShaders();
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/MandelbrotNode.cs.meta


fileFormatVersion: 2
guid: 45896ba83118f8548bd9d2f9263bcde5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

14
UnityProject/Assets/Editor/Material/Nodes/MaxNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Maximum Node")]
class MaximumNode : Function2Input
{
public override void Init()
{
name = "MaximumNode";
base.Init();
}
protected override string GetFunctionName() { return "max"; }
}
}

8
UnityProject/Assets/Editor/Material/Nodes/MaxNode.cs.meta


fileFormatVersion: 2
guid: 1de46e012f3608843978529b36704c2b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

14
UnityProject/Assets/Editor/Material/Nodes/MinNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Minimum Node")]
class MinimumNode : Function2Input
{
public override void Init()
{
name = "MinimumNode";
base.Init();
}
protected override string GetFunctionName() { return "min"; }
}
}

8
UnityProject/Assets/Editor/Material/Nodes/MinNode.cs.meta


fileFormatVersion: 2
guid: 79ffed9a70f191f4c966a6eb3ae10d07
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

37
UnityProject/Assets/Editor/Material/Nodes/MultiplyNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Math/Multiply Node")]
class MultiplyNode : FunctionMultiInput, IGeneratesFunction
{
public override void Init()
{
name = "MultiplyNode";
base.Init();
}
protected override string GetFunctionName() { return "unity_multiply_" + precision; }
public override Vector4 GetNewSlotDefaultValue()
{
return Vector4.one;
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk ("inline " + precision + "4 unity_multiply_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false);
outputString.AddShaderChunk ("{", false);
outputString.Indent ();
outputString.AddShaderChunk ("return arg1 * arg2;", false);
outputString.Deindent ();
outputString.AddShaderChunk ("}", false);
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/MultiplyNode.cs.meta


fileFormatVersion: 2
guid: 088fb5bde3ece0f4190136b3ab43f7c4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

30
UnityProject/Assets/Editor/Material/Nodes/NormalNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Input/Normal Node")]
public class NormalNode : BaseMaterialNode
{
private const string kOutputSlotName = "Normal";
public override bool hasPreview { get { return true; } }
public override PreviewMode previewMode
{
get { return PreviewMode.Preview3D; } }
public override void Init ()
{
base.Init ();
name = "Normal";
AddSlot (new Slot (SlotType.OutputSlot, kOutputSlotName));
}
public override string GetOutputVariableNameForSlot(Slot slot, GenerationMode generationMode)
{
if (generationMode == GenerationMode.Preview2D)
Debug.LogError ("Trying to generate 2D preview on a node that does not support it!");
return generationMode.Is2DPreview () ? "half4 (IN.Normal, 1)" : "half4 (o.Normal, 1)";
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/NormalNode.cs.meta


fileFormatVersion: 2
guid: 5b34601661908b3499c4c5e2ecd61f75
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

14
UnityProject/Assets/Editor/Material/Nodes/NormalizeNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Normalize Node")]
class NormalizeNode : Function1Input
{
public override void Init()
{
name = "NormalizeNode";
base.Init();
}
protected override string GetFunctionName() { return "normalize"; }
}
}

8
UnityProject/Assets/Editor/Material/Nodes/NormalizeNode.cs.meta


fileFormatVersion: 2
guid: 7eb73d726827e2c41ae4d68018bc97e1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

101
UnityProject/Assets/Editor/Material/Nodes/PerlinNode.cs


using System;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Fractal/Perlin Node")]
class PerlinNode : TextureNode, IGeneratesFunction, IGeneratesBodyCode
{
public override bool hasPreview { get { return true; } }
[SerializeField]
private int m_Iterations = 4;
[SerializeField]
private float m_Decay = 0.5f;
[SerializeField]
private float m_Frequency = 2.0f;
public override void Init()
{
name = "Perlin";
base.Init ();
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_perlin_" + precision + " ("
+ "sampler2D textureID, "
+ "int iterations, "
+ precision + " decay, "
+ precision + " frequency, "
+ precision + "2 p"
+ ")", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + "4 sum = " + precision + "4(0, 0, 0, 0);", false);
outputString.AddShaderChunk(precision + " amp = 0.5;", false);
outputString.AddShaderChunk("for(int n = 0; n < iterations; n++)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("sum += amp * tex2D (textureID, p);", false);
outputString.AddShaderChunk("p *= frequency;", false);
outputString.AddShaderChunk("amp *= decay;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
outputString.AddShaderChunk("return sum;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public override void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputSlot = FindOutputSlot(kOutputSlotName);
if (outputSlot == null)
return;
var uvSlot = FindInputSlot(kUVSlotName);
if (uvSlot == null)
return;
var uvName = "IN.meshUV0";
if (uvSlot.edges.Count > 0)
{
var fromNode = uvSlot.edges[0].fromSlot.node as BaseMaterialNode;
uvName = fromNode.GetOutputVariableNameForSlot(uvSlot.edges[0].fromSlot, generationMode);
}
string body = "unity_perlin_" + precision + "(" + GetPropertyName () + ", " + m_Iterations + ", " + m_Decay + ", " + m_Frequency + ", " + uvName + ".xy)";
visitor.AddShaderChunk("float4 " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + body + ";", true);
}
static float Slider(string title, float value, float from, float to)
{
GUILayout.BeginHorizontal();
GUILayout.Label(title);
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64));
GUILayout.EndHorizontal();
return value;
}
public override void NodeUI(Graphs.GraphGUI host)
{
base.NodeUI(host);
EditorGUI.BeginChangeCheck();
m_Iterations = (int)Slider("Iterations", (float)m_Iterations, 1, 8);
m_Decay = Slider("Decay", m_Decay, -1f, 1f);
m_Frequency = Slider("Frequency", m_Frequency, 0f, 5f);
if (EditorGUI.EndChangeCheck())
RegeneratePreviewShaders();
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/PerlinNode.cs.meta


fileFormatVersion: 2
guid: 6388ec78711fae240b4d5c60bd70d36d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

145
UnityProject/Assets/Editor/Material/Nodes/PixelShaderNode.cs


using System;
using UnityEngine;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
namespace UnityEditor.Graphs.Material
{
[Title("Output/Pixel Shader")]
class PixelShaderNode : BaseMaterialNode, IGeneratesBodyCode
{
private const string kAlbedoSlotName = "Albedo";
private const string kNormalSlotName = "Normal";
private const string kEmissionSlotName = "Emission";
private const string kSpecularSlotName = "Specular";
private const string kGlossSlotName = "Gloss";
private const string kAlphaSlotName = "Alpha";
[SerializeField]
private string m_LightFunction;
private static List<BaseLightFunction> s_LightFunctions;
public override void Init()
{
name = "PixelMaster";
base.Init ();
AddSlot (new Slot(SlotType.InputSlot, kAlbedoSlotName));
AddSlot (new Slot(SlotType.InputSlot, kNormalSlotName));
AddSlot (new Slot(SlotType.InputSlot, kEmissionSlotName));
AddSlot (new Slot(SlotType.InputSlot, kSpecularSlotName));
AddSlot (new Slot(SlotType.InputSlot, kGlossSlotName));
AddSlot (new Slot(SlotType.InputSlot, kAlphaSlotName));
}
private static List<BaseLightFunction> GetLightFunctions ()
{
if (s_LightFunctions == null)
{
s_LightFunctions = new List<BaseLightFunction> ();
foreach (Type type in Assembly.GetAssembly (typeof(BaseLightFunction)).GetTypes ())
{
if (type.IsClass && !type.IsAbstract && (type.IsSubclassOf (typeof(BaseLightFunction))))
{
var func = Activator.CreateInstance (type) as BaseLightFunction;
s_LightFunctions.Add (func);
}
}
}
return s_LightFunctions;
}
public virtual void GenerateLightFunction (ShaderGenerator visitor)
{
visitor.AddPragmaChunk (m_LightFunction);
var lightFunction = GetLightFunctions().FirstOrDefault(x => x.GetName() == m_LightFunction);
int lightFuncIndex = 0;
if (lightFunction != null)
lightFuncIndex = GetLightFunctions ().IndexOf (lightFunction);
if (lightFuncIndex < s_LightFunctions.Count)
{
BaseLightFunction func = s_LightFunctions[lightFuncIndex];
func.GenerateBody (visitor);
}
}
public void GenerateNodeCode(ShaderGenerator shaderBody, GenerationMode generationMode)
{
// do the normal slot first so that it can be used later in the shader :)
var normal = FindInputSlot (kNormalSlotName);
var nodes = new List<BaseMaterialNode>();
CollectChildNodesByExecutionOrder(nodes, normal, false);
foreach (var node in nodes)
{
if (node is IGeneratesBodyCode)
(node as IGeneratesBodyCode).GenerateNodeCode (shaderBody, generationMode);
}
foreach (var edge in normal.edges)
{
var node = edge.fromSlot.node as BaseMaterialNode;
shaderBody.AddShaderChunk("o." + normal.name + " = " + node.GetOutputVariableNameForSlot(edge.fromSlot, generationMode) + ";", true);
}
// track the last index of nodes... they have already been processed :)
int pass2StartIndex = nodes.Count;
//Get the rest of the nodes for all the other slots
CollectChildNodesByExecutionOrder(nodes, null, false);
for (var i = pass2StartIndex; i < nodes.Count; i++)
{
var node = nodes[i];
if (node is IGeneratesBodyCode)
(node as IGeneratesBodyCode).GenerateNodeCode(shaderBody, generationMode);
}
foreach (var slot in slots)
{
if (slot == normal)
continue;
foreach (var edge in slot.edges)
{
var node = edge.fromSlot.node as BaseMaterialNode;
shaderBody.AddShaderChunk("o." + slot.name + " = " + node.GetOutputVariableNameForSlot(edge.fromSlot, generationMode) + ";", true);
}
}
}
public override string GetOutputVariableNameForSlot(Slot s, GenerationMode generationMode)
{
return GetOutputVariableNameForNode();
}
public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
var lightFunction = GetLightFunctions ().FirstOrDefault (x => x.GetName () == m_LightFunction);
int lightFuncIndex = 0;
if (lightFunction != null)
lightFuncIndex = GetLightFunctions ().IndexOf (lightFunction);
lightFuncIndex = EditorGUILayout.Popup (lightFuncIndex, s_LightFunctions.Select(x => x.GetName ()).ToArray (), EditorStyles.popup);
m_LightFunction = GetLightFunctions ()[lightFuncIndex].GetName ();
}
public bool IsSpecularConnected ()
{
var specSlot = FindInputSlot (kSpecularSlotName);
var glossSlot = FindInputSlot(kGlossSlotName);
if (specSlot == null || glossSlot == null)
return false;
if (specSlot.edges.Count > 0 || glossSlot.edges.Count > 0)
return true;
return false;
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/PixelShaderNode.cs.meta


fileFormatVersion: 2
guid: 38072936174514040b3e08813a3ec4e7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

16
UnityProject/Assets/Editor/Material/Nodes/PowerNode.cs


using UnityEngine;
namespace UnityEditor.Graphs.Material
{
[Title("Math/Power Node")]
class PowerNode : Function2Input
{
public override void Init()
{
name = "PowerNode";
base.Init();
}
protected override string GetFunctionName() { return "pow"; }
}
}

8
UnityProject/Assets/Editor/Material/Nodes/PowerNode.cs.meta


fileFormatVersion: 2
guid: b2957c4e08e061444a7444a1a03fb584
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

69
UnityProject/Assets/Editor/Material/Nodes/PropertyNode.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.Graphs.Material
{
public abstract class PropertyNode : BaseMaterialNode, IGenerateProperties
{
[SerializeField]
private ShaderProperty m_BoundProperty;
public bool exposed
{
get { return m_BoundProperty != null; }
}
protected virtual bool HasBoundProperty() { return m_BoundProperty != null; }
public ShaderProperty boundProperty { get { return m_BoundProperty; } }
public virtual void BindProperty(ShaderProperty property, bool rebuildShaders)
{
m_BoundProperty = property;
}
public virtual void RefreshBoundProperty (ShaderProperty toRefresh, bool rebuildShader)
{
if (m_BoundProperty != null && m_BoundProperty == toRefresh)
{
BindProperty (toRefresh, rebuildShader);
}
}
public IEnumerable<ShaderProperty> FindValidPropertyBindings()
{
if (graph is IGenerateGraphProperties)
return (graph as IGenerateGraphProperties).GetPropertiesForPropertyType(propertyType);
return new ShaderProperty[0];
}
public virtual string GetPropertyName()
{
if (m_BoundProperty == null)
return name + "_" + Math.Abs(GetInstanceID());
return m_BoundProperty.name;
}
public abstract PropertyType propertyType { get; }
public abstract PreviewProperty GetPreviewProperty ();
public override void UpdatePreviewProperties ( )
{
base.UpdatePreviewProperties ();
MaterialWindow.DebugMaterialGraph ("In Property Node: " + this);
SetDependentPreviewMaterialProperty (GetPreviewProperty ());
}
public void UnbindProperty (ShaderProperty prop)
{
if (m_BoundProperty != null && m_BoundProperty == prop)
{
m_BoundProperty = null;
RegeneratePreviewShaders();
}
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/PropertyNode.cs.meta


fileFormatVersion: 2
guid: 93d9190b7b5ceb44ca24874c991b8da9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

30
UnityProject/Assets/Editor/Material/Nodes/QuantizeNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Quantize Node")]
class QuantizeNode : Function2Input, IGeneratesFunction
{
public override void Init()
{
name = "QuantizeNode";
base.Init();
}
protected override string GetFunctionName () {return "unity_quantize_"+precision;}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_quantize_" + precision + " (" + precision + "4 input, " + precision + "4 stepsize)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return floor(input / stepsize) * stepsize;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/QuantizeNode.cs.meta


fileFormatVersion: 2
guid: 4322ad8d0cd83df47afd741a6b97d57b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

38
UnityProject/Assets/Editor/Material/Nodes/ReflectNode.cs


using System;
namespace UnityEditor.Graphs.Material
{
[Title("Math/Reflect Node")]
class ReflectNode : Function2Input, IGeneratesFunction
{
public override void Init()
{
name = "ReflectNode";
base.Init();
}
protected override string GetInputSlot1Name() {return "Normal";}
protected override string GetInputSlot2Name() {return "Direction";}
protected override string GetOutputSlotName() {return "Reflection";}
protected override string GetFunctionName () {return "unity_reflect_"+precision;}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
foreach (var precision in m_PrecisionNames)
{
outputString.AddShaderChunk("inline " + precision + "4 unity_reflect_" + precision + " (" + precision + "4 normal, " + precision + "4 direction)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + "3 vn = normalize(normal.xyz);", false);
outputString.AddShaderChunk(precision + "3 vd = normalize(direction.xyz);", false);
outputString.AddShaderChunk("return half4 (2 * dot(vn, vd) * vn - vd, 1.0);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
}
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/ReflectNode.cs.meta


fileFormatVersion: 2
guid: 6af2205640e32994db6fd7de8aebf1de
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

27
UnityProject/Assets/Editor/Material/Nodes/ScreenPosNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Input/Screen Pos Node")]
public class ScreenPosNode : BaseMaterialNode, IGeneratesVertexToFragmentBlock
{
private const string kOutputSlotName = "ScreenPos";
public override bool hasPreview { get { return true; } }
public override void Init()
{
name = "ScreenPos";
base.Init();
AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
}
public override string GetOutputVariableNameForSlot(Slot slot, GenerationMode generationMode)
{
return "IN.screenPos";
}
public void GenerateVertexToFragmentBlock(ShaderGenerator visitor, GenerationMode generationMode)
{
visitor.AddShaderChunk(precision + "4 screenPos;", true);
}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/ScreenPosNode.cs.meta


fileFormatVersion: 2
guid: e204c7999bfa0ee42a18d8a560a36244
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

14
UnityProject/Assets/Editor/Material/Nodes/SinNode.cs


namespace UnityEditor.Graphs.Material
{
[Title("Math/Sin Node")]
class SinNode : Function1Input
{
public override void Init()
{
name = "SinNode";
base.Init();
}
protected override string GetFunctionName() {return "sin";}
}
}

8
UnityProject/Assets/Editor/Material/Nodes/SinNode.cs.meta


fileFormatVersion: 2
guid: 2b10d839969f5484cad9632519dc7324
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存