319 lines
9.3 KiB
C#
319 lines
9.3 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using UnityEditor.UIElements;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
using Action = System.Action;
|
|
|
|
namespace UnityEditor.VFX.UI
|
|
{
|
|
abstract class VFXBaseSliderField<T> : VisualElement, INotifyValueChanged<T>
|
|
{
|
|
protected Slider m_Slider;
|
|
protected INotifyValueChanged<T> m_Field;
|
|
|
|
|
|
class StartFinishSliderManipulator : Manipulator
|
|
{
|
|
VFXBaseSliderField<T> m_Slider;
|
|
bool m_InDrag;
|
|
protected override void RegisterCallbacksOnTarget()
|
|
{
|
|
m_Slider = target.GetFirstOfType<VFXBaseSliderField<T>>();
|
|
|
|
target.RegisterCallback<MouseDownEvent>(OnMouseDown, TrickleDown.TrickleDown);
|
|
target.RegisterCallback<MouseUpEvent>(OnMouseUp, TrickleDown.TrickleDown);
|
|
}
|
|
|
|
protected override void UnregisterCallbacksFromTarget()
|
|
{
|
|
target.UnregisterCallback<MouseDownEvent>(OnMouseDown, TrickleDown.TrickleDown);
|
|
target.UnregisterCallback<MouseUpEvent>(OnMouseUp, TrickleDown.TrickleDown);
|
|
}
|
|
|
|
void OnMouseDown(MouseDownEvent e)
|
|
{
|
|
target.RegisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);
|
|
}
|
|
|
|
void OnMouseMove(MouseMoveEvent e)
|
|
{
|
|
if (!m_InDrag)
|
|
{
|
|
m_InDrag = true;
|
|
m_Slider.ValueDragStarted();
|
|
target.UnregisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown); //we care only about the first drag event
|
|
}
|
|
}
|
|
|
|
void OnMouseUp(MouseUpEvent e)
|
|
{
|
|
if (m_InDrag)
|
|
m_Slider.ValueDragFinished();
|
|
else
|
|
target.UnregisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);
|
|
m_InDrag = false;
|
|
}
|
|
}
|
|
|
|
protected void ValueDragFinished()
|
|
{
|
|
if (onValueDragFinished != null)
|
|
onValueDragFinished();
|
|
}
|
|
|
|
protected void ValueDragStarted()
|
|
{
|
|
if (onValueDragStarted != null)
|
|
onValueDragStarted();
|
|
}
|
|
|
|
public Action onValueDragFinished;
|
|
public Action onValueDragStarted;
|
|
|
|
public VFXBaseSliderField()
|
|
{
|
|
AddToClassList("sliderField");
|
|
}
|
|
|
|
protected void RegisterCallBack()
|
|
{
|
|
(m_Field as VisualElement).RegisterCallback<BlurEvent>(OnFocusLost);
|
|
|
|
m_Slider.Children().First().AddManipulator(new StartFinishSliderManipulator());
|
|
}
|
|
|
|
void OnFocusLost(BlurEvent e)
|
|
{
|
|
//forward the focus lost event
|
|
using (BlurEvent newE = BlurEvent.GetPooled(this, e.relatedTarget, e.direction, panel.focusController))
|
|
{
|
|
SendEvent(newE);
|
|
}
|
|
|
|
e.StopPropagation();
|
|
}
|
|
|
|
public T m_Value;
|
|
|
|
public T value
|
|
{
|
|
get
|
|
{
|
|
return m_Value;
|
|
}
|
|
|
|
set
|
|
{
|
|
SetValueAndNotify(value);
|
|
}
|
|
}
|
|
|
|
protected abstract float ValueToFloat(T value);
|
|
|
|
|
|
private Vector2 m_Range;
|
|
|
|
public Vector2 range
|
|
{
|
|
get
|
|
{
|
|
return m_Range;
|
|
}
|
|
set
|
|
{
|
|
m_Range = value;
|
|
m_IgnoreNotification = true;
|
|
if (m_Slider.lowValue != m_Range.x || m_Slider.highValue != m_Range.y)
|
|
{
|
|
m_Slider.lowValue = m_Range.x;
|
|
m_Slider.highValue = m_Range.y;
|
|
|
|
m_Slider.value = m_Range.x;
|
|
m_Slider.value = m_Range.y;
|
|
m_Slider.value = ValueToFloat(this.value);
|
|
}
|
|
m_IgnoreNotification = false;
|
|
}
|
|
}
|
|
|
|
protected bool m_IgnoreNotification;
|
|
|
|
public abstract bool hasFocus { get; }
|
|
public void OnValueChanged(EventCallback<ChangeEvent<T>> callback)
|
|
{
|
|
RegisterCallback(callback);
|
|
}
|
|
|
|
public void RemoveOnValueChanged(EventCallback<ChangeEvent<T>> callback)
|
|
{
|
|
UnregisterCallback(callback);
|
|
}
|
|
|
|
public void SetValueAndNotify(T newValue)
|
|
{
|
|
if (!EqualityComparer<T>.Default.Equals(value, newValue))
|
|
{
|
|
using (ChangeEvent<T> evt = ChangeEvent<T>.GetPooled(value, newValue))
|
|
{
|
|
evt.target = this;
|
|
SetValueWithoutNotify(newValue);
|
|
SendEvent(evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetValueWithoutNotify(T newValue)
|
|
{
|
|
m_IgnoreNotification = true;
|
|
m_Value = newValue;
|
|
tooltip = newValue.ToString();
|
|
if (!hasFocus)
|
|
m_Field.value = newValue;
|
|
m_Slider.value = ValueToFloat(value);
|
|
m_IgnoreNotification = false;
|
|
}
|
|
|
|
protected void ValueChanged(ChangeEvent<T> e)
|
|
{
|
|
e.StopPropagation();
|
|
if (!m_IgnoreNotification)
|
|
SetValueAndNotify(e.newValue);
|
|
}
|
|
}
|
|
class VFXFloatSliderField : VFXBaseSliderField<float>
|
|
{
|
|
public VFXFloatSliderField()
|
|
{
|
|
m_Slider = new Slider(0, 1, SliderDirection.Horizontal);
|
|
m_Slider.AddToClassList("textfield");
|
|
m_Slider.RegisterValueChangedCallback(evt => ValueChanged(evt.newValue));
|
|
|
|
m_FloatField = new FloatField();
|
|
m_FloatField.RegisterValueChangedCallback(ValueChanged);
|
|
m_FloatField.name = "Field";
|
|
m_Field = m_FloatField;
|
|
|
|
m_IndeterminateLabel = new Label()
|
|
{
|
|
name = "indeterminate",
|
|
text = VFXControlConstants.indeterminateText
|
|
};
|
|
m_IndeterminateLabel.SetEnabled(false);
|
|
|
|
Add(m_Slider);
|
|
Add(m_FloatField);
|
|
RegisterCallBack();
|
|
}
|
|
|
|
VisualElement m_IndeterminateLabel;
|
|
FloatField m_FloatField;
|
|
|
|
public override bool hasFocus
|
|
{
|
|
get { return ((FloatField)m_Field).HasFocus() || (panel != null && panel.focusController.focusedElement == m_Field as VisualElement); }
|
|
}
|
|
|
|
protected override float ValueToFloat(float value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
void ValueChanged(float newValue)
|
|
{
|
|
if (!m_IgnoreNotification)
|
|
SetValueAndNotify(newValue);
|
|
}
|
|
|
|
public bool indeterminate
|
|
{
|
|
get { return m_FloatField.parent == null; }
|
|
|
|
set
|
|
{
|
|
if (indeterminate != value)
|
|
{
|
|
if (value)
|
|
{
|
|
m_FloatField.RemoveFromHierarchy();
|
|
Add(m_IndeterminateLabel);
|
|
}
|
|
else
|
|
{
|
|
m_IndeterminateLabel.RemoveFromHierarchy();
|
|
Add(m_FloatField);
|
|
}
|
|
m_Slider.SetEnabled(!value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
class VFXIntSliderField : VFXBaseSliderField<int>
|
|
{
|
|
public VFXIntSliderField()
|
|
{
|
|
m_Slider = new Slider(0, 1, SliderDirection.Horizontal);
|
|
m_Slider.AddToClassList("textfield");
|
|
m_Slider.RegisterValueChangedCallback(evt => ValueChanged(evt.newValue));
|
|
|
|
var integerField = new IntegerField();
|
|
integerField.RegisterValueChangedCallback(ValueChanged);
|
|
integerField.name = "Field";
|
|
m_Field = integerField;
|
|
|
|
Add(m_Slider);
|
|
Add(integerField);
|
|
RegisterCallBack();
|
|
}
|
|
|
|
public override bool hasFocus
|
|
{
|
|
get { return ((IntegerField)m_Field).HasFocus() || (panel != null && panel.focusController.focusedElement == m_Field as VisualElement); }
|
|
}
|
|
|
|
protected override float ValueToFloat(int value)
|
|
{
|
|
return (float)value;
|
|
}
|
|
|
|
void ValueChanged(float newValue)
|
|
{
|
|
SetValueAndNotify((int)newValue);
|
|
}
|
|
}
|
|
class VFXLongSliderField : VFXBaseSliderField<long>
|
|
{
|
|
public VFXLongSliderField()
|
|
{
|
|
m_Slider = new Slider(0, 1, SliderDirection.Horizontal);
|
|
m_Slider.AddToClassList("textfield");
|
|
m_Slider.RegisterValueChangedCallback(evt => ValueChanged(evt.newValue));
|
|
|
|
var integerField = new LongField();
|
|
integerField.RegisterValueChangedCallback(ValueChanged);
|
|
integerField.name = "Field";
|
|
m_Field = integerField;
|
|
|
|
Add(m_Slider);
|
|
Add(integerField);
|
|
RegisterCallBack();
|
|
}
|
|
|
|
public override bool hasFocus
|
|
{
|
|
get { return ((LongField)m_Field).HasFocus() || (panel != null && panel.focusController.focusedElement == m_Field as VisualElement); }
|
|
}
|
|
|
|
protected override float ValueToFloat(long value)
|
|
{
|
|
return (float)value;
|
|
}
|
|
|
|
void ValueChanged(float newValue)
|
|
{
|
|
SetValueAndNotify((long)newValue);
|
|
}
|
|
}
|
|
}
|