Merged in RangeSlider-upgrade (pull request #131)
Upgraded RangeSlider to work in both Horizontal and Verticle setups, just like regular slider. Approved-by: Simon Jacksonpull/413/head
commit
ca090d1797
|
@ -12,6 +12,7 @@ namespace UnityEngine.UI.Extensions
|
|||
[CanEditMultipleObjects]
|
||||
public class RangeSliderEditor : SelectableEditor
|
||||
{
|
||||
SerializedProperty m_Direction;
|
||||
SerializedProperty m_LowHandleRect;
|
||||
SerializedProperty m_HighHandleRect;
|
||||
SerializedProperty m_FillRect;
|
||||
|
@ -36,6 +37,7 @@ namespace UnityEngine.UI.Extensions
|
|||
m_LowHandleRect = serializedObject.FindProperty("m_LowHandleRect");
|
||||
m_HighHandleRect = serializedObject.FindProperty("m_HighHandleRect");
|
||||
m_FillRect = serializedObject.FindProperty("m_FillRect");
|
||||
m_Direction = serializedObject.FindProperty("m_Direction");
|
||||
|
||||
m_MinValue = serializedObject.FindProperty("m_MinValue");
|
||||
m_MaxValue = serializedObject.FindProperty("m_MaxValue");
|
||||
|
@ -66,6 +68,16 @@ namespace UnityEngine.UI.Extensions
|
|||
if (m_LowHandleRect.objectReferenceValue != null && m_HighHandleRect.objectReferenceValue != null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_Direction);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
RangeSlider.Direction direction = (RangeSlider.Direction)m_Direction.enumValueIndex;
|
||||
foreach (var obj in serializedObject.targetObjects)
|
||||
{
|
||||
RangeSlider rangeSlider = obj as RangeSlider;
|
||||
rangeSlider.SetDirection(direction, true);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(m_MinValue);
|
||||
EditorGUILayout.PropertyField(m_MaxValue);
|
||||
|
@ -120,4 +132,3 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -14,45 +14,124 @@ namespace UnityEngine.UI.Extensions
|
|||
[RequireComponent(typeof(RectTransform))]
|
||||
public class RangeSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
||||
{
|
||||
public enum Direction
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class RangeSliderEvent : UnityEvent<float, float> { }
|
||||
public class RangeSliderEvent : UnityEvent<float, float>
|
||||
{
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_FillRect;
|
||||
[SerializeField] private RectTransform m_FillRect;
|
||||
|
||||
public RectTransform FillRect { get { return m_FillRect; } set { if (SetClass(ref m_FillRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
public RectTransform FillRect
|
||||
{
|
||||
get { return m_FillRect; }
|
||||
set
|
||||
{
|
||||
if (SetClass(ref m_FillRect, value))
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_LowHandleRect;
|
||||
[SerializeField] private RectTransform m_LowHandleRect;
|
||||
|
||||
public RectTransform LowHandleRect { get { return m_LowHandleRect; } set { if (SetClass(ref m_LowHandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
public RectTransform LowHandleRect
|
||||
{
|
||||
get { return m_LowHandleRect; }
|
||||
set
|
||||
{
|
||||
if (SetClass(ref m_LowHandleRect, value))
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_HighHandleRect;
|
||||
[SerializeField] private RectTransform m_HighHandleRect;
|
||||
|
||||
public RectTransform HighHandleRect { get { return m_HighHandleRect; } set { if (SetClass(ref m_HighHandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
public RectTransform HighHandleRect
|
||||
{
|
||||
get { return m_HighHandleRect; }
|
||||
set
|
||||
{
|
||||
if (SetClass(ref m_HighHandleRect, value))
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Space]
|
||||
[Space] [SerializeField] private Direction m_Direction = Direction.Horizontal;
|
||||
|
||||
[SerializeField]
|
||||
private float m_MinValue = 0;
|
||||
public Direction direction
|
||||
{
|
||||
get { return m_Direction; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetStruct(ref m_Direction, value)) UpdateVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetLow(m_LowValue); SetHigh(m_HighValue); UpdateVisuals(); } } }
|
||||
[SerializeField] private float m_MinValue = 0;
|
||||
|
||||
public float MinValue
|
||||
{
|
||||
get { return m_MinValue; }
|
||||
set
|
||||
{
|
||||
if (SetStruct(ref m_MinValue, value))
|
||||
{
|
||||
SetLow(m_LowValue);
|
||||
SetHigh(m_HighValue);
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
private float m_MaxValue = 1;
|
||||
[SerializeField] private float m_MaxValue = 1;
|
||||
|
||||
public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetLow(m_LowValue); SetHigh(m_HighValue); UpdateVisuals(); } } }
|
||||
public float MaxValue
|
||||
{
|
||||
get { return m_MaxValue; }
|
||||
set
|
||||
{
|
||||
if (SetStruct(ref m_MaxValue, value))
|
||||
{
|
||||
SetLow(m_LowValue);
|
||||
SetHigh(m_HighValue);
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_WholeNumbers = false;
|
||||
[SerializeField] private bool m_WholeNumbers = false;
|
||||
|
||||
public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetLow(m_LowValue); SetHigh(m_HighValue); UpdateVisuals(); } } }
|
||||
public bool WholeNumbers
|
||||
{
|
||||
get { return m_WholeNumbers; }
|
||||
set
|
||||
{
|
||||
if (SetStruct(ref m_WholeNumbers, value))
|
||||
{
|
||||
SetLow(m_LowValue);
|
||||
SetHigh(m_HighValue);
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private float m_LowValue;
|
||||
|
||||
[SerializeField]
|
||||
private float m_LowValue;
|
||||
public virtual float LowValue
|
||||
{
|
||||
get
|
||||
|
@ -78,6 +157,7 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Mathf.InverseLerp(MinValue, MaxValue, LowValue);
|
||||
}
|
||||
set
|
||||
|
@ -87,8 +167,8 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
private float m_HighValue;
|
||||
[SerializeField] private float m_HighValue;
|
||||
|
||||
public virtual float HighValue
|
||||
{
|
||||
get
|
||||
|
@ -114,6 +194,7 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Mathf.InverseLerp(MinValue, MaxValue, HighValue);
|
||||
}
|
||||
set
|
||||
|
@ -132,10 +213,7 @@ namespace UnityEngine.UI.Extensions
|
|||
SetHigh(high, false);
|
||||
}
|
||||
|
||||
[Space]
|
||||
|
||||
[SerializeField]
|
||||
private RangeSliderEvent m_OnValueChanged = new RangeSliderEvent();
|
||||
[Space] [SerializeField] private RangeSliderEvent m_OnValueChanged = new RangeSliderEvent();
|
||||
|
||||
public RangeSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }
|
||||
|
||||
|
@ -162,10 +240,8 @@ namespace UnityEngine.UI.Extensions
|
|||
private Transform m_LowHandleTransform;
|
||||
private RectTransform m_LowHandleContainerRect;
|
||||
|
||||
// The offset from handle position to mouse down position
|
||||
private Vector2 m_LowOffset = Vector2.zero;
|
||||
// The offset from handle position to mouse down position
|
||||
private Vector2 m_HighOffset = Vector2.zero;
|
||||
// The offset from interacted component position to mouse down position
|
||||
private Vector2 m_Offset = Vector2.zero;
|
||||
|
||||
private DrivenRectTransformTracker m_Tracker;
|
||||
|
||||
|
@ -176,7 +252,8 @@ namespace UnityEngine.UI.Extensions
|
|||
float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } }
|
||||
|
||||
protected RangeSlider()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
|
@ -219,13 +296,15 @@ namespace UnityEngine.UI.Extensions
|
|||
/// See ICanvasElement.LayoutComplete
|
||||
/// </summary>
|
||||
public virtual void LayoutComplete()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See ICanvasElement.GraphicUpdateComplete
|
||||
/// </summary>
|
||||
public virtual void GraphicUpdateComplete()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
|
||||
{
|
||||
|
@ -321,7 +400,7 @@ namespace UnityEngine.UI.Extensions
|
|||
m_LowHandleContainerRect = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetLow(float input)
|
||||
{
|
||||
SetLow(input, true);
|
||||
|
@ -388,6 +467,13 @@ namespace UnityEngine.UI.Extensions
|
|||
UpdateVisuals();
|
||||
}
|
||||
|
||||
enum Axis
|
||||
{
|
||||
Horizontal = 0,
|
||||
Vertical = 1
|
||||
}
|
||||
|
||||
Axis axis { get { return m_Direction == Direction.Horizontal ? Axis.Horizontal : Axis.Vertical; } }
|
||||
|
||||
// Force-update the slider. Useful if you've changed the properties and want it to update visually.
|
||||
private void UpdateVisuals()
|
||||
|
@ -407,8 +493,8 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
//this is where some new magic must happen. Slider just uses a filled image
|
||||
//and changes the % of fill. We must move the image anchors to be between the two handles.
|
||||
anchorMin[0] = NormalizedLowValue;
|
||||
anchorMax[0] = NormalizedHighValue;
|
||||
anchorMin[(int)axis] = NormalizedLowValue;
|
||||
anchorMax[(int)axis] = NormalizedHighValue;
|
||||
|
||||
m_FillRect.anchorMin = anchorMin;
|
||||
m_FillRect.anchorMax = anchorMax;
|
||||
|
@ -419,7 +505,7 @@ namespace UnityEngine.UI.Extensions
|
|||
m_Tracker.Add(this, m_LowHandleRect, DrivenTransformProperties.Anchors);
|
||||
Vector2 anchorMin = Vector2.zero;
|
||||
Vector2 anchorMax = Vector2.one;
|
||||
anchorMin[0] = anchorMax[0] = NormalizedLowValue;
|
||||
anchorMin[(int)axis] = anchorMax[(int)axis] = NormalizedLowValue;
|
||||
m_LowHandleRect.anchorMin = anchorMin;
|
||||
m_LowHandleRect.anchorMax = anchorMax;
|
||||
}
|
||||
|
@ -429,7 +515,7 @@ namespace UnityEngine.UI.Extensions
|
|||
m_Tracker.Add(this, m_HighHandleRect, DrivenTransformProperties.Anchors);
|
||||
Vector2 anchorMin = Vector2.zero;
|
||||
Vector2 anchorMax = Vector2.one;
|
||||
anchorMin[0] = anchorMax[0] = NormalizedHighValue;
|
||||
anchorMin[(int)axis] = anchorMax[(int)axis] = NormalizedHighValue;
|
||||
m_HighHandleRect.anchorMin = anchorMin;
|
||||
m_HighHandleRect.anchorMax = anchorMax;
|
||||
}
|
||||
|
@ -446,10 +532,10 @@ namespace UnityEngine.UI.Extensions
|
|||
switch (interactionState)
|
||||
{
|
||||
case InteractionState.Low:
|
||||
NormalizedLowValue = CalculateDrag(eventData, cam, m_LowHandleContainerRect, m_LowOffset);
|
||||
NormalizedLowValue = CalculateDrag(eventData, cam, m_LowHandleContainerRect);
|
||||
break;
|
||||
case InteractionState.High:
|
||||
NormalizedHighValue = CalculateDrag(eventData, cam, m_HighHandleContainerRect, m_HighOffset);
|
||||
NormalizedHighValue = CalculateDrag(eventData, cam, m_HighHandleContainerRect);
|
||||
break;
|
||||
case InteractionState.Bar:
|
||||
//special case
|
||||
|
@ -460,35 +546,40 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
private float CalculateDrag(PointerEventData eventData, Camera cam, RectTransform containerRect, Vector2 offset)
|
||||
{
|
||||
private float CalculateDrag(PointerEventData eventData, Camera cam, RectTransform containerRect)
|
||||
{
|
||||
RectTransform clickRect = containerRect ?? m_FillContainerRect;
|
||||
if (clickRect != null && clickRect.rect.size[0] > 0)
|
||||
if (clickRect != null && clickRect.rect.size[(int)axis] > 0)
|
||||
{
|
||||
Vector2 localCursor;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam,
|
||||
out localCursor))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
localCursor -= clickRect.rect.position;
|
||||
|
||||
float val = Mathf.Clamp01((localCursor - offset)[0] / clickRect.rect.size[0]);
|
||||
float val = Mathf.Clamp01((localCursor - m_Offset)[(int)axis] / clickRect.rect.size[(int)axis]);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void CalculateBarDrag(PointerEventData eventData, Camera cam)
|
||||
{
|
||||
RectTransform clickRect = m_FillContainerRect;
|
||||
if (clickRect != null && clickRect.rect.size[0] > 0)
|
||||
if (clickRect != null && clickRect.rect.size[(int)axis] > 0)
|
||||
{
|
||||
Vector2 localCursor;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam,
|
||||
out localCursor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
localCursor -= clickRect.rect.position;
|
||||
|
||||
//now we need to get the delta drag on the bar
|
||||
|
@ -497,9 +588,9 @@ namespace UnityEngine.UI.Extensions
|
|||
if (NormalizedLowValue >= 0 && NormalizedHighValue <= 1)
|
||||
{
|
||||
//find the mid point on the current bar
|
||||
float mid = (NormalizedHighValue + NormalizedLowValue)/2;
|
||||
float mid = (NormalizedHighValue + NormalizedLowValue) / 2;
|
||||
//find where the new mid point should be
|
||||
float val = Mathf.Clamp01((localCursor)[0] / clickRect.rect.size[0]);
|
||||
float val = Mathf.Clamp01((localCursor - m_Offset)[(int)axis] / clickRect.rect.size[(int)axis]);
|
||||
//calculate the delta
|
||||
float delta = val - mid;
|
||||
//check the clamp range
|
||||
|
@ -529,9 +620,8 @@ namespace UnityEngine.UI.Extensions
|
|||
if (!MayDrag(eventData))
|
||||
return;
|
||||
|
||||
|
||||
//HANDLE DRAG EVENTS
|
||||
m_LowOffset = m_HighOffset = Vector2.zero;
|
||||
m_Offset = Vector2.zero;
|
||||
if(m_LowHandleRect != null && LowValue == MaxValue && RectTransformUtility.RectangleContainsScreenPoint(m_LowHandleRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
SetToMoveLowValueHandle(m_LowHandleRect, eventData);
|
||||
|
@ -544,19 +634,27 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
SetToMoveLowValueHandle(m_LowHandleRect, eventData);
|
||||
}
|
||||
else
|
||||
else if (m_FillRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_FillRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
//outside the handles, move the entire slider along
|
||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||
if (eventData.pointerCurrentRaycast.gameObject == m_FillRect.gameObject)
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_FillRect, eventData.position, eventData.pressEventCamera, out var localMousePos))
|
||||
{
|
||||
interactionState = InteractionState.Bar;
|
||||
m_Offset = localMousePos;
|
||||
}
|
||||
|
||||
interactionState = InteractionState.Bar;
|
||||
|
||||
|
||||
if (transition == Transition.ColorTint)
|
||||
{
|
||||
targetGraphic = m_FillImage;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//outside the handles, move the entire slider along
|
||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||
}
|
||||
|
||||
base.OnPointerDown(eventData);
|
||||
}
|
||||
|
||||
|
@ -565,7 +663,7 @@ namespace UnityEngine.UI.Extensions
|
|||
//dragging the low value handle
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(transform, eventData.position, eventData.pressEventCamera, out var localMousePos))
|
||||
{
|
||||
m_LowOffset = localMousePos;
|
||||
m_Offset = localMousePos;
|
||||
}
|
||||
interactionState = InteractionState.Low;
|
||||
if (transition == Transition.ColorTint)
|
||||
|
@ -579,7 +677,7 @@ namespace UnityEngine.UI.Extensions
|
|||
//dragging the low value handle
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(transform, eventData.position, eventData.pressEventCamera, out var localMousePos))
|
||||
{
|
||||
m_HighOffset = localMousePos;
|
||||
m_Offset = localMousePos;
|
||||
}
|
||||
interactionState = InteractionState.High;
|
||||
if (transition == Transition.ColorTint)
|
||||
|
@ -613,5 +711,17 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
eventData.useDragThreshold = false;
|
||||
}
|
||||
|
||||
public void SetDirection(Direction direction, bool includeRectLayouts)
|
||||
{
|
||||
Axis oldAxis = axis;
|
||||
this.direction = direction;
|
||||
|
||||
if (!includeRectLayouts)
|
||||
return;
|
||||
|
||||
if (axis != oldAxis)
|
||||
RectTransformUtility.FlipLayoutAxes(transform as RectTransform, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue