您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

168 行
6.3 KiB

using System;
using System.Reflection;
using UnityEditor.Experimental.UIElements;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph.Drawing.Controls
{
[AttributeUsage(AttributeTargets.Property)]
public class SliderControlAttribute : Attribute, IControlAttribute
{
string m_Label;
bool m_DisplayMinMax;
public SliderControlAttribute(string label = null, bool displayMinMax = false)
{
m_Label = label;
m_DisplayMinMax = displayMinMax;
}
public VisualElement InstantiateControl(AbstractMaterialNode node, PropertyInfo propertyInfo)
{
return new SliderControlView(m_Label, m_DisplayMinMax, node, propertyInfo);
}
}
public class SliderControlView : VisualElement, INodeModificationListener
{
AbstractMaterialNode m_Node;
PropertyInfo m_PropertyInfo;
bool m_DisplayMinMax;
int m_UndoGroup = -1;
Vector3 m_Value;
VisualElement m_SliderPanel;
Slider m_Slider;
FloatField m_SliderInput;
public SliderControlView(string label, bool displayMinMax, AbstractMaterialNode node, PropertyInfo propertyInfo)
{
m_Node = node;
m_PropertyInfo = propertyInfo;
AddStyleSheetPath("Styles/Controls/SliderControlView");
m_DisplayMinMax = displayMinMax;
if (propertyInfo.PropertyType != typeof(Vector3))
throw new ArgumentException("Property must be of type Vector3.", "propertyInfo");
new GUIContent(label ?? ObjectNames.NicifyVariableName(propertyInfo.Name));
m_Value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
m_SliderPanel = new VisualElement { name = "SliderPanel" };
if (!string.IsNullOrEmpty(label))
m_SliderPanel.Add(new Label(label));
Action<float> changedSlider = (s) => { OnChangeSlider(s); };
m_Slider = new Slider(m_Value.y, m_Value.z, changedSlider);
m_Slider.value = m_Value.x;
m_SliderPanel.Add(m_Slider);
m_SliderInput = AddField(m_SliderPanel, "", 0, m_Value);
Add(m_SliderPanel);
if(m_DisplayMinMax)
{
var fieldsPanel = new VisualElement { name = "FieldsPanel" };
AddField(fieldsPanel, "Min", 1, m_Value);
AddField(fieldsPanel, "Max", 2, m_Value);
Add(fieldsPanel);
}
}
public void OnNodeModified(ModificationScope scope)
{
if (scope == ModificationScope.Graph)
{
this.MarkDirtyRepaint();
}
}
void OnChangeSlider(float newValue)
{
m_Node.owner.owner.RegisterCompleteObjectUndo("Slider Change");
var value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
value.x = newValue;
m_PropertyInfo.SetValue(m_Node, value, null);
if(m_SliderInput != null)
m_SliderInput.value = newValue;
this.MarkDirtyRepaint();
}
FloatField AddField(VisualElement panel, string label, int index, Vector3 initValiue)
{
var field = new FloatField { userData = index, value = initValiue[index] };
if(label != "")
{
var l = new Label(label);
panel.Add(l);
var dragger = new FieldMouseDragger<double>(field);
dragger.SetDragZone(l);
}
field.RegisterCallback<MouseDownEvent>(Repaint);
field.RegisterCallback<MouseMoveEvent>(Repaint);
field.OnValueChanged(evt =>
{
var value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
value[index] = (float)evt.newValue;
m_PropertyInfo.SetValue(m_Node, value, null);
m_UndoGroup = -1;
UpdateSlider(m_SliderPanel, index, value);
this.MarkDirtyRepaint();
});
field.RegisterCallback<InputEvent>(evt =>
{
if (m_UndoGroup == -1)
{
m_UndoGroup = Undo.GetCurrentGroup();
m_Node.owner.owner.RegisterCompleteObjectUndo("Change " + m_Node.name);
}
float newValue;
if (!float.TryParse(evt.newData, out newValue))
newValue = 0f;
var value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
value[index] = newValue;
m_PropertyInfo.SetValue(m_Node, value, null);
this.MarkDirtyRepaint();
});
field.RegisterCallback<KeyDownEvent>(evt =>
{
if (evt.keyCode == KeyCode.Escape && m_UndoGroup > -1)
{
Undo.RevertAllDownToGroup(m_UndoGroup);
m_UndoGroup = -1;
m_Value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
UpdateSlider(m_SliderPanel, index, m_Value);
evt.StopPropagation();
}
this.MarkDirtyRepaint();
});
panel.Add(field);
return field;
}
void UpdateSlider(VisualElement panel, int index, Vector3 value)
{
value.x = Mathf.Max(Mathf.Min(value.x, value.z), value.y);
panel.Remove(m_Slider);
Action<float> changedSlider = (s) => { OnChangeSlider(s); };
m_Slider = new Slider(value.y, value.z, changedSlider);
m_Slider.lowValue = value.y;
m_Slider.highValue = value.z;
m_Slider.value = value.x;
panel.Add(m_Slider);
panel.Remove(m_SliderInput);
if(index != 0)
m_SliderInput = AddField(panel, "", 0, value);
m_SliderInput.value = value.x;
panel.Add(m_SliderInput);
}
void Repaint<T>(MouseEventBase<T> evt) where T : MouseEventBase<T>, new()
{
evt.StopPropagation();
this.MarkDirtyRepaint();
}
}
}