215 lines
7.7 KiB
C#
215 lines
7.7 KiB
C#
|
using System;
|
||
|
using System.Reflection;
|
||
|
using UnityEngine;
|
||
|
|
||
|
using UnityEngine.UIElements;
|
||
|
|
||
|
namespace UnityEditor.ShaderGraph.Drawing.Controls
|
||
|
{
|
||
|
[AttributeUsage(AttributeTargets.Property)]
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class ChannelMixerControlView : VisualElement
|
||
|
{
|
||
|
AbstractMaterialNode m_Node;
|
||
|
PropertyInfo m_PropertyInfo;
|
||
|
ChannelMixerNode.ChannelMixer m_ChannelMixer;
|
||
|
int m_OutChannel;
|
||
|
|
||
|
Slider m_RedSlider;
|
||
|
Slider m_GreenSlider;
|
||
|
Slider m_BlueSlider;
|
||
|
|
||
|
FloatField m_RedInputField;
|
||
|
FloatField m_GreenInputField;
|
||
|
FloatField m_BlueInputField;
|
||
|
|
||
|
float m_Minimum;
|
||
|
float m_Maximum;
|
||
|
bool m_Initialized;
|
||
|
|
||
|
public ChannelMixerControlView(string label, float minimum, float maximum, AbstractMaterialNode node, PropertyInfo propertyInfo)
|
||
|
{
|
||
|
m_Node = node;
|
||
|
m_PropertyInfo = propertyInfo;
|
||
|
styleSheets.Add(Resources.Load<StyleSheet>("Styles/Controls/ChannelMixerControlView"));
|
||
|
m_ChannelMixer = (ChannelMixerNode.ChannelMixer)m_PropertyInfo.GetValue(m_Node, null);
|
||
|
m_OutChannel = 0;
|
||
|
|
||
|
m_Minimum = minimum;
|
||
|
m_Maximum = maximum;
|
||
|
|
||
|
if (propertyInfo.PropertyType != typeof(ChannelMixerNode.ChannelMixer))
|
||
|
throw new ArgumentException("Property must be of type ChannelMixer.", "propertyInfo");
|
||
|
label = label ?? ObjectNames.NicifyVariableName(propertyInfo.Name);
|
||
|
|
||
|
if (!string.IsNullOrEmpty(label))
|
||
|
Add(new Label(label));
|
||
|
|
||
|
var buttonPanel = new VisualElement { name = "buttonPanel" };
|
||
|
|
||
|
Action changedOutputRed = () => OnClickButton(0);
|
||
|
var outputButtonRed = new Button(changedOutputRed);
|
||
|
outputButtonRed.Add(new Label("R"));
|
||
|
buttonPanel.Add(outputButtonRed);
|
||
|
|
||
|
Action changedOutputGreen = () => OnClickButton(1);
|
||
|
var outputButtonGreen = new Button(changedOutputGreen);
|
||
|
outputButtonGreen.Add(new Label("G"));
|
||
|
buttonPanel.Add(outputButtonGreen);
|
||
|
|
||
|
Action changedOutputBlue = () => OnClickButton(2);
|
||
|
var outputButtonBlue = new Button(changedOutputBlue);
|
||
|
outputButtonBlue.Add(new Label("B"));
|
||
|
buttonPanel.Add(outputButtonBlue);
|
||
|
|
||
|
Add(buttonPanel);
|
||
|
|
||
|
var redSliderPanel = new VisualElement { name = "sliderPanel" };
|
||
|
redSliderPanel.Add(new Label("R"));
|
||
|
Action<float> changedRedIn = (s) => { OnChangeSlider(s, 0); };
|
||
|
m_RedSlider = new Slider(m_Minimum, m_Maximum);
|
||
|
m_RedSlider.RegisterValueChangedCallback((evt) => OnChangeSlider(evt.newValue, 0));
|
||
|
|
||
|
redSliderPanel.Add(m_RedSlider);
|
||
|
m_RedInputField = new FloatField { value = m_ChannelMixer.outRed.x };
|
||
|
m_RedInputField.RegisterCallback<ChangeEvent<double>, int>(OnChangeInputField, 0);
|
||
|
redSliderPanel.Add(m_RedInputField);
|
||
|
Add(redSliderPanel);
|
||
|
|
||
|
var greenSliderPanel = new VisualElement { name = "sliderPanel" };
|
||
|
greenSliderPanel.Add(new Label("G"));
|
||
|
m_GreenSlider = new Slider(m_Minimum, m_Maximum);
|
||
|
m_GreenSlider.RegisterValueChangedCallback((evt) => OnChangeSlider(evt.newValue, 1));
|
||
|
greenSliderPanel.Add(m_GreenSlider);
|
||
|
m_GreenInputField = new FloatField { value = m_ChannelMixer.outRed.y };
|
||
|
m_GreenInputField.RegisterCallback<ChangeEvent<double>, int>(OnChangeInputField, 1);
|
||
|
greenSliderPanel.Add(m_GreenInputField);
|
||
|
Add(greenSliderPanel);
|
||
|
|
||
|
var blueSliderPanel = new VisualElement { name = "sliderPanel" };
|
||
|
blueSliderPanel.Add(new Label("B"));
|
||
|
m_BlueSlider = new Slider(m_Minimum, m_Maximum);
|
||
|
m_BlueSlider.RegisterValueChangedCallback((evt) => OnChangeSlider(evt.newValue, 2));
|
||
|
blueSliderPanel.Add(m_BlueSlider);
|
||
|
m_BlueInputField = new FloatField { value = m_ChannelMixer.outRed.z };
|
||
|
m_BlueInputField.RegisterCallback<ChangeEvent<double>, int>(OnChangeInputField, 2);
|
||
|
blueSliderPanel.Add(m_BlueInputField);
|
||
|
Add(blueSliderPanel);
|
||
|
|
||
|
m_Initialized = true;
|
||
|
ResetSliders();
|
||
|
}
|
||
|
|
||
|
void ResetSliders()
|
||
|
{
|
||
|
Vector3 outputChannel = GetOutputChannel();
|
||
|
m_RedSlider.value = outputChannel[0];
|
||
|
m_GreenSlider.value = outputChannel[1];
|
||
|
m_BlueSlider.value = outputChannel[2];
|
||
|
}
|
||
|
|
||
|
void OnChangeSlider(float value, int inChannel)
|
||
|
{
|
||
|
if (!m_Initialized)
|
||
|
return;
|
||
|
m_Node.owner.owner.RegisterCompleteObjectUndo("Slider Change");
|
||
|
switch (m_OutChannel)
|
||
|
{
|
||
|
case 1:
|
||
|
m_ChannelMixer.outGreen[inChannel] = value;
|
||
|
break;
|
||
|
case 2:
|
||
|
m_ChannelMixer.outBlue[inChannel] = value;
|
||
|
break;
|
||
|
default:
|
||
|
m_ChannelMixer.outRed[inChannel] = value;
|
||
|
break;
|
||
|
}
|
||
|
switch (inChannel)
|
||
|
{
|
||
|
case 1:
|
||
|
m_GreenInputField.value = value;
|
||
|
break;
|
||
|
case 2:
|
||
|
m_BlueInputField.value = value;
|
||
|
break;
|
||
|
default:
|
||
|
m_RedInputField.value = value;
|
||
|
break;
|
||
|
}
|
||
|
m_PropertyInfo.SetValue(m_Node, m_ChannelMixer, null);
|
||
|
}
|
||
|
|
||
|
void OnChangeInputField(ChangeEvent<double> evt, int inChannel)
|
||
|
{
|
||
|
if (!m_Initialized)
|
||
|
return;
|
||
|
var value = Mathf.Max(Mathf.Min((float)evt.newValue, m_Maximum), m_Minimum);
|
||
|
m_Node.owner.owner.RegisterCompleteObjectUndo("Input Field Change");
|
||
|
switch (m_OutChannel)
|
||
|
{
|
||
|
case 1:
|
||
|
m_ChannelMixer.outGreen[inChannel] = value;
|
||
|
break;
|
||
|
case 2:
|
||
|
m_ChannelMixer.outBlue[inChannel] = value;
|
||
|
break;
|
||
|
default:
|
||
|
m_ChannelMixer.outRed[inChannel] = value;
|
||
|
break;
|
||
|
}
|
||
|
switch (inChannel)
|
||
|
{
|
||
|
case 1:
|
||
|
m_GreenSlider.value = value;
|
||
|
break;
|
||
|
case 2:
|
||
|
m_BlueSlider.value = value;
|
||
|
break;
|
||
|
default:
|
||
|
m_RedSlider.value = value;
|
||
|
break;
|
||
|
}
|
||
|
m_PropertyInfo.SetValue(m_Node, m_ChannelMixer, null);
|
||
|
this.MarkDirtyRepaint();
|
||
|
}
|
||
|
|
||
|
void OnClickButton(int outChannel)
|
||
|
{
|
||
|
m_OutChannel = outChannel;
|
||
|
ResetSliders();
|
||
|
}
|
||
|
|
||
|
Vector3 GetOutputChannel()
|
||
|
{
|
||
|
switch (m_OutChannel)
|
||
|
{
|
||
|
case 1:
|
||
|
return m_ChannelMixer.outGreen;
|
||
|
case 2:
|
||
|
return m_ChannelMixer.outBlue;
|
||
|
default:
|
||
|
return m_ChannelMixer.outRed;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|