853 lines
28 KiB
C#
853 lines
28 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
namespace AibisDream
|
|
{
|
|
[ExecuteAlways]
|
|
[RequireComponent(typeof(RectTransform))]
|
|
public class SliderEx : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
|
{
|
|
/// <summary>
|
|
/// Setting that indicates one of four directions.
|
|
/// </summary>
|
|
public enum Direction
|
|
{
|
|
/// <summary>
|
|
/// From the left to the right
|
|
/// </summary>
|
|
LeftToRight,
|
|
|
|
/// <summary>
|
|
/// From the right to the left
|
|
/// </summary>
|
|
RightToLeft,
|
|
|
|
/// <summary>
|
|
/// From the bottom to the top.
|
|
/// </summary>
|
|
BottomToTop,
|
|
|
|
/// <summary>
|
|
/// From the top to the bottom.
|
|
/// </summary>
|
|
TopToBottom,
|
|
}
|
|
|
|
private bool _isHolding;
|
|
|
|
[SerializeField] private RectTransform m_FillRect;
|
|
|
|
/// <summary>
|
|
/// Optional RectTransform to use as fill for the slider.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
/// //Reference to new "RectTransform"(Child of FillArea).
|
|
/// public RectTransform newFillRect;
|
|
///
|
|
/// //Deactivates the old FillRect and assigns a new one.
|
|
/// void Start()
|
|
/// {
|
|
/// mainSlider.fillRect.gameObject.SetActive(false);
|
|
/// mainSlider.fillRect = newFillRect;
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public RectTransform fillRect
|
|
{
|
|
get => m_FillRect;
|
|
set
|
|
{
|
|
if (SetPropertyUtility.SetClass(ref m_FillRect, value))
|
|
{
|
|
UpdateCachedReferences();
|
|
UpdateVisuals();
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializeField] private RectTransform m_HandleRect;
|
|
|
|
/// <summary>
|
|
/// Optional RectTransform to use as a handle for the slider.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
/// //Reference to new "RectTransform" (Child of "Handle Slide Area").
|
|
/// public RectTransform handleHighlighted;
|
|
///
|
|
/// //Deactivates the old Handle, then assigns and enables the new one.
|
|
/// void Start()
|
|
/// {
|
|
/// mainSlider.handleRect.gameObject.SetActive(false);
|
|
/// mainSlider.handleRect = handleHighlighted;
|
|
/// mainSlider.handleRect.gameObject.SetActive(true);
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public RectTransform handleRect
|
|
{
|
|
get => m_HandleRect;
|
|
set
|
|
{
|
|
if (SetPropertyUtility.SetClass(ref m_HandleRect, value))
|
|
{
|
|
UpdateCachedReferences();
|
|
UpdateVisuals();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Space] [SerializeField] private Direction m_Direction = Direction.LeftToRight;
|
|
|
|
/// <summary>
|
|
/// The direction of the slider, from minimum to maximum value.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// public void Start()
|
|
/// {
|
|
/// //Changes the direction of the slider.
|
|
/// if (mainDirection == Direction.BottomToTop)
|
|
/// {
|
|
/// mainDirection = Direction.TopToBottom;
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public Direction direction
|
|
{
|
|
get => m_Direction;
|
|
set
|
|
{
|
|
if (SetPropertyUtility.SetStruct(ref m_Direction, value)) UpdateVisuals();
|
|
}
|
|
}
|
|
|
|
[SerializeField] private float m_MinValue = 0;
|
|
|
|
/// <summary>
|
|
/// The minimum allowed value of the slider.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// void Start()
|
|
/// {
|
|
/// // Changes the minimum value of the slider to 10;
|
|
/// mainSlider.minValue = 10;
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public float minValue
|
|
{
|
|
get => m_MinValue;
|
|
set
|
|
{
|
|
if (SetPropertyUtility.SetStruct(ref m_MinValue, value))
|
|
{
|
|
Set(m_Value);
|
|
UpdateVisuals();
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializeField] private float m_MaxValue = 1;
|
|
|
|
/// <summary>
|
|
/// The maximum allowed value of the slider.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// void Start()
|
|
/// {
|
|
/// // Changes the max value of the slider to 20;
|
|
/// mainSlider.maxValue = 20;
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public float maxValue
|
|
{
|
|
get => m_MaxValue;
|
|
set
|
|
{
|
|
if (SetPropertyUtility.SetStruct(ref m_MaxValue, value))
|
|
{
|
|
Set(m_Value);
|
|
UpdateVisuals();
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializeField] private bool m_WholeNumbers = false;
|
|
|
|
/// <summary>
|
|
/// Should the value only be allowed to be whole numbers?
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// public void Start()
|
|
/// {
|
|
/// //sets the slider's value to accept whole numbers only.
|
|
/// mainSlider.wholeNumbers = true;
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public bool wholeNumbers
|
|
{
|
|
get => m_WholeNumbers;
|
|
set
|
|
{
|
|
if (SetPropertyUtility.SetStruct(ref m_WholeNumbers, value))
|
|
{
|
|
Set(m_Value);
|
|
UpdateVisuals();
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializeField] protected float m_Value;
|
|
|
|
/// <summary>
|
|
/// The current value of the slider.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// //Invoked when a submit button is clicked.
|
|
/// public void SubmitSliderSetting()
|
|
/// {
|
|
/// //Displays the value of the slider in the console.
|
|
/// Debug.Log(mainSlider.value);
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public virtual float value
|
|
{
|
|
get => wholeNumbers ? Mathf.Round(m_Value) : m_Value;
|
|
set => Set(value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the value of the slider without invoking onValueChanged callback.
|
|
/// </summary>
|
|
/// <param name="input">The new value for the slider.</param>
|
|
public virtual void SetValueWithoutNotify(float input)
|
|
{
|
|
Set(input, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The current value of the slider normalized into a value between 0 and 1.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// //Set to invoke when "OnValueChanged" method is called.
|
|
/// void CheckNormalisedValue()
|
|
/// {
|
|
/// //Displays the normalised value of the slider everytime the value changes.
|
|
/// Debug.Log(mainSlider.normalizedValue);
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public float NormalizedValue
|
|
{
|
|
get
|
|
{
|
|
if (Mathf.Approximately(minValue, maxValue))
|
|
return 0;
|
|
return Mathf.InverseLerp(minValue, maxValue, value);
|
|
}
|
|
set => this.value = Mathf.Lerp(minValue, maxValue, value);
|
|
}
|
|
|
|
[Space] [SerializeField] private UnityEvent<float> m_OnValueChanged = new();
|
|
|
|
/// <summary>
|
|
/// Callback executed when the value of the slider is changed.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// public void Start()
|
|
/// {
|
|
/// //Adds a listener to the main slider and invokes a method when the value changes.
|
|
/// mainSlider.onValueChanged.AddListener(delegate {ValueChangeCheck(); });
|
|
/// }
|
|
///
|
|
/// // Invoked when the value of the slider changes.
|
|
/// public void ValueChangeCheck()
|
|
/// {
|
|
/// Debug.Log(mainSlider.value);
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
///</code>
|
|
/// </example>
|
|
public UnityEvent<float> onValueChanged
|
|
{
|
|
get => m_OnValueChanged;
|
|
set => m_OnValueChanged = value;
|
|
}
|
|
|
|
[SerializeField] private UnityEvent m_OnStartDrag = new();
|
|
public UnityEvent onStartDrag
|
|
{
|
|
get => m_OnStartDrag;
|
|
set => m_OnStartDrag = value;
|
|
}
|
|
|
|
[SerializeField] private UnityEvent<float> m_OnEndDrag = new();
|
|
public UnityEvent<float> onEndDrag
|
|
{
|
|
get => m_OnEndDrag;
|
|
set => m_OnEndDrag = value;
|
|
}
|
|
|
|
// Private fields
|
|
|
|
private Image m_FillImage;
|
|
private Transform m_FillTransform;
|
|
private RectTransform m_FillContainerRect;
|
|
private Transform m_HandleTransform;
|
|
private RectTransform m_HandleContainerRect;
|
|
|
|
// The offset from handle position to mouse down position
|
|
private Vector2 m_Offset = Vector2.zero;
|
|
|
|
// field is never assigned warning
|
|
#pragma warning disable 649
|
|
private DrivenRectTransformTracker m_Tracker;
|
|
#pragma warning restore 649
|
|
|
|
// This "delayed" mechanism is required for case 1037681.
|
|
private bool m_DelayedUpdateVisuals = false;
|
|
|
|
// Size of each step.
|
|
float stepSize => wholeNumbers ? 1 : (maxValue - minValue) * 0.1f;
|
|
|
|
protected SliderEx()
|
|
{
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
protected override void OnValidate()
|
|
{
|
|
base.OnValidate();
|
|
|
|
if (wholeNumbers)
|
|
{
|
|
m_MinValue = Mathf.Round(m_MinValue);
|
|
m_MaxValue = Mathf.Round(m_MaxValue);
|
|
}
|
|
|
|
//Onvalidate is called before OnEnabled. We need to make sure not to touch any other objects before OnEnable is run.
|
|
if (IsActive())
|
|
{
|
|
UpdateCachedReferences();
|
|
// Update rects in next update since other things might affect them even if value didn't change.
|
|
m_DelayedUpdateVisuals = true;
|
|
}
|
|
|
|
if (!UnityEditor.PrefabUtility.IsPartOfPrefabAsset(this) && !Application.isPlaying)
|
|
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
|
}
|
|
|
|
#endif // if UNITY_EDITOR
|
|
|
|
public virtual void Rebuild(CanvasUpdate executing)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (executing == CanvasUpdate.Prelayout)
|
|
onValueChanged.Invoke(value);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// See ICanvasElement.LayoutComplete
|
|
/// </summary>
|
|
public virtual void LayoutComplete()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// See ICanvasElement.GraphicUpdateComplete
|
|
/// </summary>
|
|
public virtual void GraphicUpdateComplete()
|
|
{
|
|
}
|
|
|
|
protected override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
UpdateCachedReferences();
|
|
Set(m_Value, false);
|
|
// Update rects since they need to be initialized correctly.
|
|
UpdateVisuals();
|
|
}
|
|
|
|
protected override void OnDisable()
|
|
{
|
|
m_Tracker.Clear();
|
|
base.OnDisable();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the rect based on the delayed update visuals.
|
|
/// Got around issue of calling sendMessage from onValidate.
|
|
/// </summary>
|
|
protected virtual void Update()
|
|
{
|
|
if (m_DelayedUpdateVisuals)
|
|
{
|
|
m_DelayedUpdateVisuals = false;
|
|
Set(m_Value, false);
|
|
UpdateVisuals();
|
|
}
|
|
}
|
|
|
|
protected override void OnDidApplyAnimationProperties()
|
|
{
|
|
// Has value changed? Various elements of the slider have the old normalisedValue assigned, we can use this to perform a comparison.
|
|
// We also need to ensure the value stays within min/max.
|
|
m_Value = ClampValue(m_Value);
|
|
float oldNormalizedValue = NormalizedValue;
|
|
if (m_FillContainerRect != null)
|
|
{
|
|
if (m_FillImage != null && m_FillImage.type == Image.Type.Filled)
|
|
oldNormalizedValue = m_FillImage.fillAmount;
|
|
else
|
|
oldNormalizedValue =
|
|
(ReverseValue ? 1 - m_FillRect.anchorMin[(int)axis] : m_FillRect.anchorMax[(int)axis]);
|
|
}
|
|
else if (m_HandleContainerRect != null)
|
|
oldNormalizedValue =
|
|
(ReverseValue ? 1 - m_HandleRect.anchorMin[(int)axis] : m_HandleRect.anchorMin[(int)axis]);
|
|
|
|
UpdateVisuals();
|
|
|
|
if (!Mathf.Approximately(oldNormalizedValue, NormalizedValue))
|
|
{
|
|
UISystemProfilerApi.AddMarker("Slider.value", this);
|
|
onValueChanged.Invoke(m_Value);
|
|
}
|
|
|
|
// UUM-34170 Apparently, some properties on slider such as IsInteractable and Normalcolor Animation is broken.
|
|
// We need to call base here to render the animation on Scene
|
|
base.OnDidApplyAnimationProperties();
|
|
}
|
|
|
|
void UpdateCachedReferences()
|
|
{
|
|
if (m_FillRect && m_FillRect != (RectTransform)transform)
|
|
{
|
|
m_FillTransform = m_FillRect.transform;
|
|
m_FillImage = m_FillRect.GetComponent<Image>();
|
|
if (m_FillTransform.parent != null)
|
|
m_FillContainerRect = m_FillTransform.parent.GetComponent<RectTransform>();
|
|
}
|
|
else
|
|
{
|
|
m_FillRect = null;
|
|
m_FillContainerRect = null;
|
|
m_FillImage = null;
|
|
}
|
|
|
|
if (m_HandleRect && m_HandleRect != (RectTransform)transform)
|
|
{
|
|
m_HandleTransform = m_HandleRect.transform;
|
|
if (m_HandleTransform.parent != null)
|
|
m_HandleContainerRect = m_HandleTransform.parent.GetComponent<RectTransform>();
|
|
}
|
|
else
|
|
{
|
|
m_HandleRect = null;
|
|
m_HandleContainerRect = null;
|
|
}
|
|
}
|
|
|
|
float ClampValue(float input)
|
|
{
|
|
float newValue = Mathf.Clamp(input, minValue, maxValue);
|
|
if (wholeNumbers)
|
|
newValue = Mathf.Round(newValue);
|
|
return newValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the value of the slider.
|
|
/// </summary>
|
|
/// <param name="input">The new value for the slider.</param>
|
|
/// <param name="sendCallback">If the OnValueChanged callback should be invoked.</param>
|
|
/// <remarks>
|
|
/// Process the input to ensure the value is between min and max value. If the input is different set the value and send the callback is required.
|
|
/// </remarks>
|
|
protected virtual void Set(float input, bool sendCallback = true)
|
|
{
|
|
// Clamp the input
|
|
float newValue = ClampValue(input);
|
|
|
|
// If the stepped value doesn't match the last one, it's time to update
|
|
if (Mathf.Approximately(m_Value, newValue))
|
|
return;
|
|
|
|
m_Value = newValue;
|
|
UpdateVisuals();
|
|
if (sendCallback)
|
|
{
|
|
UISystemProfilerApi.AddMarker("Slider.value", this);
|
|
m_OnValueChanged.Invoke(newValue);
|
|
}
|
|
}
|
|
|
|
protected override void OnRectTransformDimensionsChange()
|
|
{
|
|
base.OnRectTransformDimensionsChange();
|
|
|
|
//This can be invoked before OnEnabled is called. So we shouldn't be accessing other objects, before OnEnable is called.
|
|
if (!IsActive())
|
|
return;
|
|
|
|
UpdateVisuals();
|
|
}
|
|
|
|
enum Axis
|
|
{
|
|
Horizontal = 0,
|
|
Vertical = 1
|
|
}
|
|
|
|
Axis axis =>
|
|
m_Direction is Direction.LeftToRight or Direction.RightToLeft
|
|
? Axis.Horizontal
|
|
: Axis.Vertical;
|
|
|
|
private bool ReverseValue => m_Direction is Direction.RightToLeft or Direction.TopToBottom;
|
|
|
|
// Force-update the slider. Useful if you've changed the properties and want it to update visually.
|
|
private void UpdateVisuals()
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
UpdateCachedReferences();
|
|
#endif
|
|
|
|
m_Tracker.Clear();
|
|
|
|
if (m_FillContainerRect != null)
|
|
{
|
|
m_Tracker.Add(this, m_FillRect, DrivenTransformProperties.Anchors);
|
|
Vector2 anchorMin = Vector2.zero;
|
|
Vector2 anchorMax = Vector2.one;
|
|
|
|
if (m_FillImage != null && m_FillImage.type == Image.Type.Filled)
|
|
{
|
|
m_FillImage.fillAmount = NormalizedValue;
|
|
}
|
|
else
|
|
{
|
|
if (ReverseValue)
|
|
anchorMin[(int)axis] = 1 - NormalizedValue;
|
|
else
|
|
anchorMax[(int)axis] = NormalizedValue;
|
|
}
|
|
|
|
m_FillRect.anchorMin = anchorMin;
|
|
m_FillRect.anchorMax = anchorMax;
|
|
}
|
|
|
|
if (m_HandleContainerRect != null)
|
|
{
|
|
m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors);
|
|
Vector2 anchorMin = Vector2.zero;
|
|
Vector2 anchorMax = Vector2.one;
|
|
anchorMin[(int)axis] = anchorMax[(int)axis] = (ReverseValue ? (1 - NormalizedValue) : NormalizedValue);
|
|
m_HandleRect.anchorMin = anchorMin;
|
|
m_HandleRect.anchorMax = anchorMax;
|
|
}
|
|
}
|
|
|
|
// Update the slider's position based on the mouse.
|
|
void UpdateDrag(PointerEventData eventData, Camera cam)
|
|
{
|
|
RectTransform clickRect = m_HandleContainerRect ?? m_FillContainerRect;
|
|
if (clickRect != null && clickRect.rect.size[(int)axis] > 0)
|
|
{
|
|
Vector2 position = Vector2.zero;
|
|
if (!MultipleDisplayUtilities.GetRelativeMousePositionForDrag(eventData, ref position))
|
|
return;
|
|
|
|
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, position, cam,
|
|
out var localCursor))
|
|
return;
|
|
localCursor -= clickRect.rect.position;
|
|
|
|
float val = Mathf.Clamp01((localCursor - m_Offset)[(int)axis] / clickRect.rect.size[(int)axis]);
|
|
NormalizedValue = ReverseValue ? 1f - val : val;
|
|
}
|
|
}
|
|
|
|
private bool MayDrag(PointerEventData eventData)
|
|
{
|
|
return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left;
|
|
}
|
|
|
|
public override void OnPointerDown(PointerEventData eventData)
|
|
{
|
|
if (!MayDrag(eventData))
|
|
return;
|
|
|
|
base.OnPointerDown(eventData);
|
|
|
|
m_Offset = Vector2.zero;
|
|
if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect,
|
|
eventData.pointerPressRaycast.screenPosition, eventData.enterEventCamera))
|
|
{
|
|
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect,
|
|
eventData.pointerPressRaycast.screenPosition, eventData.pressEventCamera,
|
|
out var localMousePos))
|
|
m_Offset = localMousePos;
|
|
_isHolding = true;
|
|
|
|
m_OnStartDrag?.Invoke();
|
|
}
|
|
}
|
|
|
|
public override void OnPointerUp(PointerEventData eventData)
|
|
{
|
|
if (_isHolding)
|
|
{
|
|
_isHolding = false;
|
|
m_OnEndDrag?.Invoke(value);
|
|
}
|
|
|
|
if (!MayDrag(eventData)) return;
|
|
|
|
base.OnPointerUp(eventData);
|
|
}
|
|
|
|
public virtual void OnDrag(PointerEventData eventData)
|
|
{
|
|
if (!_isHolding || !MayDrag(eventData))
|
|
return;
|
|
|
|
UpdateDrag(eventData, eventData.pressEventCamera);
|
|
}
|
|
|
|
public override void OnMove(AxisEventData eventData)
|
|
{
|
|
if (!IsActive() || !IsInteractable())
|
|
{
|
|
base.OnMove(eventData);
|
|
return;
|
|
}
|
|
|
|
switch (eventData.moveDir)
|
|
{
|
|
case MoveDirection.Left:
|
|
if (axis == Axis.Horizontal && FindSelectableOnLeft() == null)
|
|
Set(ReverseValue ? value + stepSize : value - stepSize);
|
|
else
|
|
base.OnMove(eventData);
|
|
break;
|
|
case MoveDirection.Right:
|
|
if (axis == Axis.Horizontal && FindSelectableOnRight() == null)
|
|
Set(ReverseValue ? value - stepSize : value + stepSize);
|
|
else
|
|
base.OnMove(eventData);
|
|
break;
|
|
case MoveDirection.Up:
|
|
if (axis == Axis.Vertical && FindSelectableOnUp() == null)
|
|
Set(ReverseValue ? value - stepSize : value + stepSize);
|
|
else
|
|
base.OnMove(eventData);
|
|
break;
|
|
case MoveDirection.Down:
|
|
if (axis == Axis.Vertical && FindSelectableOnDown() == null)
|
|
Set(ReverseValue ? value + stepSize : value - stepSize);
|
|
else
|
|
base.OnMove(eventData);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// See Selectable.FindSelectableOnLeft
|
|
/// </summary>
|
|
public override Selectable FindSelectableOnLeft()
|
|
{
|
|
if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Horizontal)
|
|
return null;
|
|
return base.FindSelectableOnLeft();
|
|
}
|
|
|
|
/// <summary>
|
|
/// See Selectable.FindSelectableOnRight
|
|
/// </summary>
|
|
public override Selectable FindSelectableOnRight()
|
|
{
|
|
if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Horizontal)
|
|
return null;
|
|
return base.FindSelectableOnRight();
|
|
}
|
|
|
|
/// <summary>
|
|
/// See Selectable.FindSelectableOnUp
|
|
/// </summary>
|
|
public override Selectable FindSelectableOnUp()
|
|
{
|
|
if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Vertical)
|
|
return null;
|
|
return base.FindSelectableOnUp();
|
|
}
|
|
|
|
/// <summary>
|
|
/// See Selectable.FindSelectableOnDown
|
|
/// </summary>
|
|
public override Selectable FindSelectableOnDown()
|
|
{
|
|
if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Vertical)
|
|
return null;
|
|
return base.FindSelectableOnDown();
|
|
}
|
|
|
|
public virtual void OnInitializePotentialDrag(PointerEventData eventData)
|
|
{
|
|
eventData.useDragThreshold = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the direction of this slider, optionally changing the layout as well.
|
|
/// </summary>
|
|
/// <param name="vDirection">The direction of the slider</param>
|
|
/// <param name="includeRectLayouts">Should the layout be flipped together with the slider direction</param>
|
|
/// <example>
|
|
/// <code>
|
|
/// <![CDATA[
|
|
/// using UnityEngine;
|
|
/// using System.Collections;
|
|
/// using UnityEngine.UI; // Required when Using UI elements.
|
|
///
|
|
/// public class Example : MonoBehaviour
|
|
/// {
|
|
/// public Slider mainSlider;
|
|
///
|
|
/// public void Start()
|
|
/// {
|
|
/// mainSlider.SetDirection(Direction.LeftToRight, false);
|
|
/// }
|
|
/// }
|
|
/// ]]>
|
|
/// </code>
|
|
/// </example>
|
|
public void SetDirection(Direction vDirection, bool includeRectLayouts)
|
|
{
|
|
Axis oldAxis = axis;
|
|
bool oldReverse = ReverseValue;
|
|
this.direction = vDirection;
|
|
|
|
if (!includeRectLayouts)
|
|
return;
|
|
|
|
if (axis != oldAxis)
|
|
RectTransformUtility.FlipLayoutAxes(transform as RectTransform, true, true);
|
|
|
|
if (ReverseValue != oldReverse)
|
|
RectTransformUtility.FlipLayoutOnAxis(transform as RectTransform, (int)axis, true, true);
|
|
}
|
|
}
|
|
} |