浏览代码

Attribute control for gradient node

/main
Peter Bay Bastian 7 年前
当前提交
aeedf575
共有 8 个文件被更改,包括 310 次插入158 次删除
  1. 230
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/GradientNode.cs
  2. 1
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialGraphPresenter.cs
  3. 89
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Controls/GradientControl.cs
  4. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Controls/GradientControl.cs.meta
  5. 42
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/Graphs/Gradient.ShaderGraph
  6. 9
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/Graphs/Gradient.ShaderGraph.meta
  7. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/Nodes/GradientNodePresenter.cs.meta
  8. 82
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/Nodes/GradientNodePresenter.cs

230
MaterialGraphProject/Assets/NewNodes/Editor/Keep/GradientNode.cs


using System.Reflection;
using System.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.MaterialGraph.Drawing.Controls;
public class GradientNode : CodeFunctionNode
public class GradientNode : AbstractMaterialNode, IGeneratesBodyCode
Gradient m_Gradient;
private Gradient m_gradient;
Vector4[] m_SerializableColorKeys = { new Vector4(1f, 1f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f), };
[SerializeField]
Vector2[] m_SerializableAlphaKeys = { new Vector2(1f, 0f), new Vector2(1f, 1f) };
[GradientControl("")]
get { return m_gradient; }
get
{
return m_Gradient;
}
if (m_gradient == value)
return;
var scope = ModificationScope.Nothing;
m_gradient = value;
if (onModified != null)
onModified(this, ModificationScope.Graph);
var currentColorKeys = m_Gradient.colorKeys;
var currentAlphaKeys = m_Gradient.alphaKeys;
var newColorKeys = value.colorKeys;
var newAlphaKeys = value.alphaKeys;
if (currentColorKeys.Length != newColorKeys.Length || currentAlphaKeys.Length != newAlphaKeys.Length)
{
scope = scope < ModificationScope.Graph ? ModificationScope.Graph : scope;
}
else
{
for (var i = 0; i < currentColorKeys.Length; i++)
{
if (currentColorKeys[i].color != newColorKeys[i].color || Math.Abs(currentColorKeys[i].time - newColorKeys[i].time) > 1e-9)
scope = scope < ModificationScope.Node ? ModificationScope.Node : scope;
}
for (var i = 0; i < currentAlphaKeys.Length; i++)
{
if (Math.Abs(currentAlphaKeys[i].alpha - newAlphaKeys[i].alpha) > 1e-9 || Math.Abs(currentAlphaKeys[i].time - newAlphaKeys[i].time) > 1e-9)
scope = scope < ModificationScope.Node ? ModificationScope.Node : scope;
}
}
if (scope > ModificationScope.Nothing)
{
gradient.SetKeys(newColorKeys, newAlphaKeys);
if (onModified != null)
onModified(this, scope);
}
public void UpdateGradient()
{
if (onModified != null)
{
onModified(this, ModificationScope.Graph);
}
public const int TimeInputSlotId = 0;
const string k_TimeInputSlotName = "Time";
public const int RGBAOutputSlotId = 1;
const string k_RGBAOutputSlotName = "RGBA";
public const int ROutputSlotId = 2;
const string k_ROutputSlotName = "R";
public const int GOutputSlotId = 3;
const string k_GOutputSlotName = "G";
public const int BOutputSlotId = 4;
const string k_BOutputSlotName = "B";
// Debug.Log("UPDATED GRAPH");
}
public const int AOutputSlotId = 5;
const string k_AOutputSlotName = "A";
UpdateNodeAfterDeserialization();
protected override MethodInfo GetFunctionToConvert()
public sealed override void UpdateNodeAfterDeserialization()
return GetType().GetMethod("Unity_Gradient", BindingFlags.NonPublic | BindingFlags.Instance);
AddSlot(new MaterialSlot(TimeInputSlotId, k_TimeInputSlotName, k_TimeInputSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(RGBAOutputSlotId, k_RGBAOutputSlotName, k_RGBAOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(ROutputSlotId, k_ROutputSlotName, k_ROutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(GOutputSlotId, k_GOutputSlotName, k_GOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(BOutputSlotId, k_BOutputSlotName, k_BOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(AOutputSlotId, k_AOutputSlotName, k_AOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { TimeInputSlotId, RGBAOutputSlotId, ROutputSlotId, GOutputSlotId, BOutputSlotId, AOutputSlotId });
m_Gradient = new Gradient();
var colorKeys = m_SerializableColorKeys.Select(k => new GradientColorKey(new Color(k.x, k.y, k.z, 1f), k.w)).ToArray();
var alphaKeys = m_SerializableAlphaKeys.Select(k => new GradientAlphaKey(k.x, k.y)).ToArray();
m_Gradient.SetKeys(colorKeys, alphaKeys);
string Unity_Gradient(
[Slot(0, Binding.None)] Vector1 value,
[Slot(1, Binding.None)] out Vector4 result)
public override void OnBeforeSerialize()
result = Vector4.zero;
base.OnBeforeSerialize();
m_SerializableColorKeys = gradient.colorKeys.Select(k => new Vector4(k.color.r, k.color.g, k.color.b, k.time)).ToArray();
m_SerializableAlphaKeys = gradient.alphaKeys.Select(k => new Vector2(k.alpha, k.time)).ToArray();
}
string GetColorKeyName(int index)
{
return string.Format("{0}_ck{1}", GetVariableNameForNode(), index);
}
GradientColorKey[] colorkeys = m_gradient.colorKeys;
GradientAlphaKey[] alphakeys = m_gradient.alphaKeys;
string GetAlphaKeyName(int index)
{
return string.Format("{0}_ak{1}", GetVariableNameForNode(), index);
}
//Start
StringBuilder outputString = new StringBuilder();
string start = @"
{
";
outputString.Append(start);
//Color
Color c;
float cp;
for (int i = 0; i < colorkeys.Length; i++)
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
{
base.CollectShaderProperties(properties, generationMode);
var colorKeys = m_Gradient.colorKeys;
var alphaKeys = m_Gradient.alphaKeys;
for (var i = 0; i < colorKeys.Length; i++)
c = colorkeys[i].color;
cp = colorkeys[i].time;
outputString.AppendLine(string.Format("\t{{precision}}3 color{0}=float3({1},{2},{3});", i, c.r, c.g, c.b));
outputString.AppendLine(string.Format("\t{{precision}} colorp{0}={1};", i, cp));
var colorKey = colorKeys[i];
properties.AddShaderProperty(new Vector4ShaderProperty
{
overrideReferenceName = GetColorKeyName(i),
generatePropertyBlock = false,
value = new Vector4(colorKey.color.r, colorKey.color.g, colorKey.color.b, colorKey.time)
});
outputString.AppendLine("\t{precision}3 gradcolor = color0;");
for (var i = 0; i < alphaKeys.Length; i++)
{
properties.AddShaderProperty(new Vector2ShaderProperty
{
overrideReferenceName = GetAlphaKeyName(i),
generatePropertyBlock = false,
value = new Vector2(alphaKeys[i].alpha, alphaKeys[i].time)
});
}
}
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
base.CollectPreviewMaterialProperties(properties);
var colorKeys = m_Gradient.colorKeys;
var alphaKeys = m_Gradient.alphaKeys;
for (int i = 0; i < colorkeys.Length - 1; i++)
for (var i = 0; i < colorKeys.Length; i++)
int j = i + 1;
outputString.AppendLine(string.Format("\t{{precision}} colorLerpPosition{0}=smoothstep(colorp{0},colorp{1},value);", i, j));
outputString.AppendLine(string.Format("\tgradcolor = lerp(gradcolor,color{0},colorLerpPosition{1});", j, i));
var colorKey = colorKeys[i];
properties.Add(new PreviewProperty()
{
m_Name = GetColorKeyName(i),
m_PropType = PropertyType.Vector4,
m_Vector4 = new Vector4(colorKey.color.r, colorKey.color.g, colorKey.color.b, colorKey.time)
});
//Alpha
float a;
float ap;
for (int i = 0; i < alphakeys.Length; i++)
for (var i = 0; i < alphaKeys.Length; i++)
a = alphakeys[i].alpha;
ap = alphakeys[i].time;
outputString.AppendLine(string.Format("\t{{precision}} alpha{0}={1};", i, a));
outputString.AppendLine(string.Format("\t{{precision}} alphap{0}={1};", i, ap));
properties.Add(new PreviewProperty
{
m_Name = GetAlphaKeyName(i),
m_PropType = PropertyType.Vector2,
m_Vector4 = new Vector2(alphaKeys[i].alpha, alphaKeys[i].time)
});
}
outputString.AppendLine("\t{precision} gradalpha = alpha0;");
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var rgbaOutputName = GetVariableNameForSlot(RGBAOutputSlotId);
visitor.AddShaderChunk(string.Format("{0}4 {1};", precision, rgbaOutputName), false);
for (int i = 0; i < alphakeys.Length - 1; i++)
visitor.AddShaderChunk("{", false);
visitor.Indent();
int j = i + 1;
outputString.AppendLine(string.Format("\t{{precision}} alphaLerpPosition{0}=smoothstep(alphap{0},alphap{1},value);", i, j));
outputString.AppendLine(string.Format("\tgradalpha = lerp(gradalpha,alpha{0},alphaLerpPosition{1});", j, i));
}
var timeInputValue = GetSlotValue(TimeInputSlotId, generationMode);
// Color interpolation
visitor.AddShaderChunk(string.Format("{1}3 gradientColor = {0}.rgb;", GetColorKeyName(0), precision), false);
for (var i = 0; i < m_Gradient.colorKeys.Length - 1; i++)
{
visitor.AddShaderChunk(string.Format("gradientColor = lerp(gradientColor, {1}.rgb, smoothstep({0}.a, {1}.a, {2}));", GetColorKeyName(i), GetColorKeyName(i + 1), timeInputValue), false);
}
//Result
outputString.AppendLine("\tresult = float4(gradcolor,gradalpha);");
outputString.AppendLine("}");
// Alpha interpolation
visitor.AddShaderChunk(string.Format("{1} gradientAlpha = {0}.r;", GetAlphaKeyName(0), precision), false);
for (var i = 0; i < m_Gradient.alphaKeys.Length - 1; i++)
visitor.AddShaderChunk(string.Format("gradientAlpha = lerp(gradientAlpha, {1}.r, smoothstep({0}.g, {1}.g, {2}));", GetAlphaKeyName(i), GetAlphaKeyName(i + 1), timeInputValue), false);
return outputString.ToString();
//Result
visitor.AddShaderChunk(string.Format("{0} = float4(gradientColor, gradientAlpha);", rgbaOutputName), false);
}
visitor.Deindent();
visitor.AddShaderChunk("}", false);
visitor.AddShaderChunk(string.Format("{0} {1} = {2}.r;", precision, GetVariableNameForSlot(ROutputSlotId), rgbaOutputName), false);
visitor.AddShaderChunk(string.Format("{0} {1} = {2}.g;", precision, GetVariableNameForSlot(GOutputSlotId), rgbaOutputName), false);
visitor.AddShaderChunk(string.Format("{0} {1} = {2}.b;", precision, GetVariableNameForSlot(BOutputSlotId), rgbaOutputName), false);
visitor.AddShaderChunk(string.Format("{0} {1} = {2}.a;", precision, GetVariableNameForSlot(AOutputSlotId), rgbaOutputName), false);
}
}
}

1
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialGraphPresenter.cs


{
typeMapper = new GraphTypeMapper(typeof(MaterialNodePresenter));
typeMapper[typeof(AbstractMaterialNode)] = typeof(MaterialNodePresenter);
typeMapper[typeof(GradientNode)] = typeof(GradientNodePresenter);
// typeMapper[typeof(ScatterNode)] = typeof(ScatterNodePresenter);
//typeMapper[typeof(TextureNode)] = typeof(TextureNodePresenter);

89
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Controls/GradientControl.cs


using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
using UnityEngine.MaterialGraph;
namespace UnityEditor.MaterialGraph.Drawing.Controls
{
[AttributeUsage(AttributeTargets.Property)]
public class GradientControlAttribute : Attribute, IControlAttribute
{
string m_Label;
public GradientControlAttribute(string label = null)
{
m_Label = label;
}
public VisualElement InstantiateControl(AbstractMaterialNode node, PropertyInfo propertyInfo)
{
return new GradientControlView(m_Label, node, propertyInfo);
}
}
[Serializable]
public class GradientObject : ScriptableObject
{
public Gradient gradient = new Gradient();
}
public class GradientControlView : VisualElement
{
GUIContent m_Label;
AbstractMaterialNode m_Node;
PropertyInfo m_PropertyInfo;
string m_PrevWindow = "";
[SerializeField]
GradientObject m_GradientObject;
[SerializeField]
SerializedObject m_SerializedObject;
[SerializeField]
SerializedProperty m_SerializedProperty;
public GradientControlView(string label, AbstractMaterialNode node, PropertyInfo propertyInfo)
{
m_Label = new GUIContent(label ?? ObjectNames.NicifyVariableName(propertyInfo.Name));
m_Node = node;
m_PropertyInfo = propertyInfo;
if (propertyInfo.PropertyType != typeof(Gradient))
throw new ArgumentException("Property must be of type Gradient.", "propertyInfo");
m_GradientObject = ScriptableObject.CreateInstance<GradientObject>();
m_GradientObject.gradient = new Gradient();
m_SerializedObject = new SerializedObject(m_GradientObject);
m_SerializedProperty = m_SerializedObject.FindProperty("gradient");
Add(new IMGUIContainer(OnGUIHandler));
}
void OnGUIHandler()
{
m_SerializedObject.Update();
var gradient = (Gradient)m_PropertyInfo.GetValue(m_Node, null);
m_GradientObject.gradient.SetKeys(gradient.colorKeys, gradient.alphaKeys);
using (var changeCheckScope = new EditorGUI.ChangeCheckScope())
{
EditorGUILayout.PropertyField(m_SerializedProperty, m_Label, true, null);
m_SerializedObject.ApplyModifiedProperties();
if (changeCheckScope.changed)
m_PropertyInfo.SetValue(m_Node, m_GradientObject.gradient, null);
}
var e = Event.current;
if (EditorWindow.focusedWindow != null && m_PrevWindow != EditorWindow.focusedWindow.ToString() && EditorWindow.focusedWindow.ToString() != "(UnityEditor.GradientPicker)")
{
m_PropertyInfo.SetValue(m_Node, m_GradientObject.gradient, null);
m_PrevWindow = EditorWindow.focusedWindow.ToString();
Debug.Log("Update Gradient Shader");
}
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Controls/GradientControl.cs.meta


fileFormatVersion: 2
guid: 41930fdac13e47db8faedb82e6411a4f
timeCreated: 1507882043

42
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/Graphs/Gradient.ShaderGraph
文件差异内容过多而无法显示
查看文件

9
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/Graphs/Gradient.ShaderGraph.meta


fileFormatVersion: 2
guid: 090ac3a2dd039884ba2dfa3b2ca34452
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/Nodes/GradientNodePresenter.cs.meta


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

82
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/Nodes/GradientNodePresenter.cs


using System;
using System.Collections.Generic;
using UnityEditor.Experimental.UIElements.GraphView;
using UnityEngine;
namespace UnityEditor.MaterialGraph.Drawing
{
[Serializable]
class GradientContolPresenter : GraphControlPresenter
{
[SerializeField]
private GradientObject gradientobj;
[SerializeField]
private SerializedObject hserializedObject;
[SerializeField]
private SerializedProperty hcolorGradient;
private UnityEngine.MaterialGraph.GradientNode prevnode;
private string prevWindow = "";
public override void OnGUIHandler()
{
base.OnGUIHandler();
var cNode = node as UnityEngine.MaterialGraph.GradientNode;
if (cNode == null)
return;
if (gradientobj == null || prevnode != cNode)
{
prevnode = cNode;
gradientobj = new GradientObject();
if (cNode.gradient != null)
{
gradientobj.gradient = cNode.gradient;
}
hserializedObject = new SerializedObject(gradientobj);
hcolorGradient = hserializedObject.FindProperty("gradient");
}
EditorGUILayout.PropertyField(hcolorGradient, true, null);
hserializedObject.ApplyModifiedProperties();
cNode.gradient = gradientobj.gradient;
Event e = Event.current;
if (EditorWindow.focusedWindow != null && prevWindow != EditorWindow.focusedWindow.ToString() && EditorWindow.focusedWindow.ToString() != "(UnityEditor.GradientPicker)")
{
cNode.UpdateGradient();
prevWindow = EditorWindow.focusedWindow.ToString();
Debug.Log("Update Gradient Shader");
}
}
public override float GetHeight()
{
return EditorGUIUtility.singleLineHeight + 10 * EditorGUIUtility.standardVerticalSpacing;
}
}
[Serializable]
public class GradientNodePresenter : MaterialNodePresenter
{
protected override IEnumerable<GraphControlPresenter> GetControlData()
{
var instance = CreateInstance<GradientContolPresenter>();
instance.Initialize(node);
return new List<GraphControlPresenter> { instance };
}
}
[Serializable]
public class GradientObject : ScriptableObject
{
public Gradient gradient = new Gradient();
}
}
正在加载...
取消
保存