Matt Dean
7 年前
当前提交
711f81fa
共有 4 个文件被更改,包括 290 次插入 和 0 次删除
-
150MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Artistic/Adjustment/ChannelMixerNode.cs
-
11MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Artistic/Adjustment/ChannelMixerNode.cs.meta
-
118MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Controls/ChannelMixerControl.cs
-
11MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Controls/ChannelMixerControl.cs.meta
|
|||
using System; |
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.ShaderGraph.Drawing.Controls; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.ShaderGraph |
|||
{ |
|||
[Title("Artistic/Adjustment/Channel Mixer")] |
|||
public class ChannelMixerNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction |
|||
{ |
|||
public ChannelMixerNode() |
|||
{ |
|||
name = "Channel Mixer"; |
|||
UpdateNodeAfterDeserialization(); |
|||
} |
|||
|
|||
private const int InputSlotId = 0; |
|||
private const int OutputSlotId = 1; |
|||
private const string kInputSlotName = "In"; |
|||
private const string kOutputSlotName = "Out"; |
|||
|
|||
public override bool hasPreview |
|||
{ |
|||
get { return true; } |
|||
} |
|||
|
|||
protected string GetFunctionName() |
|||
{ |
|||
return "Unity_ChannelMixer_" + precision; |
|||
} |
|||
|
|||
public sealed override void UpdateNodeAfterDeserialization() |
|||
{ |
|||
AddSlot(GetInputSlot()); |
|||
AddSlot(GetOutputSlot()); |
|||
RemoveSlotsNameNotMatching(validSlots); |
|||
} |
|||
|
|||
protected int[] validSlots |
|||
{ |
|||
get { return new[] { InputSlotId, OutputSlotId }; } |
|||
} |
|||
|
|||
protected virtual MaterialSlot GetInputSlot() |
|||
{ |
|||
return new Vector3MaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector3.zero); |
|||
} |
|||
|
|||
protected virtual MaterialSlot GetOutputSlot() |
|||
{ |
|||
return new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector3.zero); |
|||
} |
|||
|
|||
[Serializable] |
|||
public class ChannelMixer |
|||
{ |
|||
public OutChannel[] outChannels; |
|||
public ChannelMixer(OutChannel[] c) |
|||
{ |
|||
outChannels = c; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class OutChannel |
|||
{ |
|||
public float[] inChannels; |
|||
public OutChannel(float[] c) |
|||
{ |
|||
inChannels = c; |
|||
} |
|||
} |
|||
|
|||
[SerializeField] |
|||
private ChannelMixer m_ChannelMixer; |
|||
|
|||
[ChannelMixerControl("")] |
|||
public ChannelMixer channelMixer |
|||
{ |
|||
get |
|||
{ |
|||
if(m_ChannelMixer == null) |
|||
{ |
|||
m_ChannelMixer = new ChannelMixer( |
|||
new OutChannel[3] |
|||
{ |
|||
new OutChannel( new float[3] { 1, 0, 0 } ), |
|||
new OutChannel( new float[3] { 0, 1, 0 } ), |
|||
new OutChannel( new float[3] { 0, 0, 1 } ) |
|||
}); |
|||
} |
|||
return m_ChannelMixer; |
|||
} |
|||
set |
|||
{ |
|||
/*if (m_ChannelMixer == value) // This is always true with nested arrays in a class
|
|||
return;*/ |
|||
|
|||
m_ChannelMixer = value; |
|||
if (onModified != null) |
|||
{ |
|||
onModified(this, ModificationScope.Graph); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected string GetFunctionPrototype(string arg1Name, string arg2Name) |
|||
{ |
|||
return string.Format("void {0} ({1} {2}, out {3} {4})", GetFunctionName(), ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType), arg1Name, ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType), arg2Name); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputSlotId }, new[] { OutputSlotId }); |
|||
string inputValue = GetSlotValue(InputSlotId, generationMode); |
|||
string outputValue = GetSlotValue(OutputSlotId, generationMode); |
|||
visitor.AddShaderChunk(string.Format("{0} {1};", ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId)), true); |
|||
visitor.AddShaderChunk(GetFunctionCallBody(inputValue, outputValue), true); |
|||
} |
|||
|
|||
protected string GetFunctionCallBody(string inputValue, string outputValue) |
|||
{ |
|||
return GetFunctionName() + " (" + inputValue + ", " + outputValue + ");"; |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk(GetFunctionPrototype("In", "Out"), false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
|
|||
outputString.AddShaderChunk(string.Format("{0}3 red = {0}3 ({1}, {2}, {3});", |
|||
precision, channelMixer.outChannels[0].inChannels[0], channelMixer.outChannels[0].inChannels[1], channelMixer.outChannels[0].inChannels[2]), true); |
|||
outputString.AddShaderChunk(string.Format("{0}3 green = {0}3 ({1}, {2}, {3});", |
|||
precision, channelMixer.outChannels[1].inChannels[0], channelMixer.outChannels[1].inChannels[1], channelMixer.outChannels[1].inChannels[2]), true); |
|||
outputString.AddShaderChunk(string.Format("{0}3 blue = {0}3 ({1}, {2}, {3});", |
|||
precision, channelMixer.outChannels[2].inChannels[0], channelMixer.outChannels[2].inChannels[1], channelMixer.outChannels[2].inChannels[2]), true); |
|||
|
|||
outputString.AddShaderChunk(string.Format("Out = {0} {1};", |
|||
ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType), |
|||
"(dot(In, red), dot(In, green), dot(In, blue))"), true); |
|||
|
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d8d3a2d8c96e5994696f30f658efebea |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Reflection; |
|||
using UnityEditor.Experimental.UIElements; |
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.UIElements; |
|||
using UnityEngine.Experimental.UIElements.StyleSheets; |
|||
using UnityEditor.ShaderGraph; |
|||
|
|||
namespace UnityEditor.ShaderGraph.Drawing.Controls |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Property)] |
|||
public class ChannelMixerControlAttribute : Attribute, IControlAttribute |
|||
{ |
|||
string m_Label; |
|||
float m_Minimum; |
|||
float m_Maximum; |
|||
|
|||
public ChannelMixerControlAttribute(string label = null, float minimum = -2f, float maximum = 2f) |
|||
{ |
|||
m_Label = label; |
|||
m_Minimum = minimum; |
|||
m_Maximum = maximum; |
|||
} |
|||
|
|||
public VisualElement InstantiateControl(AbstractMaterialNode node, PropertyInfo propertyInfo) |
|||
{ |
|||
return new ChannelMixerControlView(m_Label, m_Minimum, m_Maximum, node, propertyInfo); |
|||
} |
|||
} |
|||
|
|||
public class ChannelMixerControlView : VisualElement |
|||
{ |
|||
AbstractMaterialNode m_Node; |
|||
PropertyInfo m_PropertyInfo; |
|||
int m_OutChannel; |
|||
|
|||
Slider redSlider; |
|||
Slider greenSlider; |
|||
Slider blueSlider; |
|||
|
|||
float m_Minimum; |
|||
float m_Maximum; |
|||
|
|||
public ChannelMixerControlView(string label, float minimum, float maximum, AbstractMaterialNode node, PropertyInfo propertyInfo) |
|||
{ |
|||
m_Node = node; |
|||
m_PropertyInfo = propertyInfo; |
|||
m_OutChannel = 0; |
|||
|
|||
m_Minimum = minimum; |
|||
m_Maximum = maximum; |
|||
|
|||
if (propertyInfo.PropertyType != typeof(ChannelMixerNode.ChannelMixer)) |
|||
throw new ArgumentException("Property must be of type Channel Mixer.", "propertyInfo"); |
|||
label = label ?? ObjectNames.NicifyVariableName(propertyInfo.Name); |
|||
|
|||
if (!string.IsNullOrEmpty(label)) |
|||
Add(new Label(label)); |
|||
|
|||
Action changedOutputRed = () => OnClickButton(0); |
|||
var outputButtonRed = new Button(changedOutputRed); |
|||
Add(outputButtonRed); |
|||
|
|||
Action changedOutputGreen = () => OnClickButton(1); |
|||
var outputButtonGreen = new Button(changedOutputGreen); |
|||
Add(outputButtonGreen); |
|||
|
|||
Action changedOutputBlue = () => OnClickButton(2); |
|||
var outputButtonBlue = new Button(changedOutputBlue); |
|||
Add(outputButtonBlue); |
|||
|
|||
ChannelMixerNode.ChannelMixer channelMixer = (ChannelMixerNode.ChannelMixer)m_PropertyInfo.GetValue(m_Node, null); |
|||
|
|||
Add(new Label("Red")); |
|||
Action<float> changedRedIn = (s) => { OnChangeSlider(s, m_OutChannel, 0); }; |
|||
redSlider = new Slider(m_Minimum, m_Maximum, changedRedIn) { value = channelMixer.outChannels[m_OutChannel].inChannels[0] }; |
|||
redSlider.value = 1; // This refuses to initialize at its default value
|
|||
Add(redSlider); |
|||
|
|||
Add(new Label("Green")); |
|||
Action<float> changedGreenIn = (s) => { OnChangeSlider(s, m_OutChannel, 1); }; |
|||
greenSlider = new Slider(m_Minimum, m_Maximum, changedGreenIn) { value = channelMixer.outChannels[m_OutChannel].inChannels[1] }; |
|||
Add(greenSlider); |
|||
|
|||
Add(new Label("Blue")); |
|||
Action<float> changedBlueIn = (s) => { OnChangeSlider(s, m_OutChannel, 2); }; |
|||
blueSlider = new Slider(m_Minimum, m_Maximum, changedBlueIn) { value = channelMixer.outChannels[m_OutChannel].inChannels[2] }; |
|||
Add(blueSlider); |
|||
|
|||
ResetSliders(); |
|||
} |
|||
|
|||
void ResetSliders() |
|||
{ |
|||
ChannelMixerNode.ChannelMixer channelMixer = (ChannelMixerNode.ChannelMixer)m_PropertyInfo.GetValue(m_Node, null); |
|||
redSlider.value = channelMixer.outChannels[m_OutChannel].inChannels[0]; |
|||
greenSlider.value = channelMixer.outChannels[m_OutChannel].inChannels[1]; |
|||
blueSlider.value = channelMixer.outChannels[m_OutChannel].inChannels[2]; |
|||
} |
|||
|
|||
void OnChangeSlider(float value, int outChannel, int inChannel) |
|||
{ |
|||
m_Node.owner.owner.RegisterCompleteObjectUndo("Slider Change"); |
|||
ChannelMixerNode.ChannelMixer channelMixer = (ChannelMixerNode.ChannelMixer)m_PropertyInfo.GetValue(m_Node, null); |
|||
channelMixer.outChannels[outChannel].inChannels[inChannel] = value; |
|||
m_PropertyInfo.SetValue(m_Node, channelMixer, null); |
|||
Dirty(ChangeType.Repaint); |
|||
} |
|||
|
|||
void OnClickButton(int outChannel) |
|||
{ |
|||
m_Node.owner.owner.RegisterCompleteObjectUndo("Button Change"); |
|||
m_OutChannel = outChannel; |
|||
ResetSliders(); |
|||
Dirty(ChangeType.Repaint); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 74a26e3294ebad94fa5d78ee95751556 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue