diff --git a/Editor/MinMaxSliderEditor.cs b/Editor/MinMaxSliderEditor.cs new file mode 100644 index 0000000..19f6457 --- /dev/null +++ b/Editor/MinMaxSliderEditor.cs @@ -0,0 +1,121 @@ +///Credit brogan89 +///Sourced from - https://github.com/brogan89/MinMaxSlider + +using System; +using UnityEditor; +using UnityEditor.UI; + +namespace UnityEngine.UI.Extensions +{ + [CustomEditor(typeof(MinMaxSlider), true)] + [CanEditMultipleObjects] + public class MinMaxSliderEditor : SelectableEditor + { + private SerializedProperty _customCamera; + private SerializedProperty _sliderBounds; + private SerializedProperty _minHandle; + private SerializedProperty _maxHandle; + private SerializedProperty _minText; + private SerializedProperty _maxText; + private SerializedProperty _textFormat; + private SerializedProperty _middleGraphic; + private SerializedProperty _minLimit; + private SerializedProperty _maxLimit; + private SerializedProperty _wholeNumbers; + private SerializedProperty _minValue; + private SerializedProperty _maxValue; + + private SerializedProperty _onValueChanged; + + private readonly GUIContent label = new GUIContent("Min Max Values"); + + protected override void OnEnable() + { + base.OnEnable(); + _customCamera = serializedObject.FindProperty("customCamera"); + _sliderBounds = serializedObject.FindProperty("sliderBounds"); + _minHandle = serializedObject.FindProperty("minHandle"); + _maxHandle = serializedObject.FindProperty("maxHandle"); + _minText = serializedObject.FindProperty("minText"); + _maxText = serializedObject.FindProperty("maxText"); + _textFormat = serializedObject.FindProperty("textFormat"); + _middleGraphic = serializedObject.FindProperty("middleGraphic"); + _minLimit = serializedObject.FindProperty("minLimit"); + _maxLimit = serializedObject.FindProperty("maxLimit"); + _wholeNumbers = serializedObject.FindProperty("wholeNumbers"); + _minValue = serializedObject.FindProperty("minValue"); + _maxValue = serializedObject.FindProperty("maxValue"); + _onValueChanged = serializedObject.FindProperty("onValueChanged"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + float minLimitOld = _minLimit.floatValue; + float maxLimitOld = _maxLimit.floatValue; + float minValueOld = _minValue.floatValue; + float maxValueOld = _maxValue.floatValue; + + EditorGUILayout.PropertyField(_customCamera); + EditorGUILayout.PropertyField(_sliderBounds); + EditorGUILayout.PropertyField(_minHandle); + EditorGUILayout.PropertyField(_maxHandle); + EditorGUILayout.PropertyField(_middleGraphic); + + EditorGUILayout.PropertyField(_minText); + EditorGUILayout.PropertyField(_maxText); + EditorGUILayout.PropertyField(_textFormat); + + EditorGUILayout.PropertyField(_minLimit); + EditorGUILayout.PropertyField(_maxLimit); + + EditorGUILayout.PropertyField(_wholeNumbers); + EditorGUILayout.PropertyField(_minValue); + EditorGUILayout.PropertyField(_maxValue); + + float minValue = Mathf.Clamp(_minValue.floatValue, _minLimit.floatValue, _maxLimit.floatValue); + float maxValue = Mathf.Clamp(_maxValue.floatValue, _minLimit.floatValue, _maxLimit.floatValue); + EditorGUILayout.MinMaxSlider(label, ref minValue, ref maxValue, _minLimit.floatValue, _maxLimit.floatValue); + + bool anyValueChanged = !IsEqualFloat(minValueOld, minValue) + || !IsEqualFloat(maxValueOld, maxValue) + || !IsEqualFloat(minLimitOld, _minLimit.floatValue) + || !IsEqualFloat(maxLimitOld, _maxLimit.floatValue); + + if (anyValueChanged) + { + MinMaxSlider slider = (MinMaxSlider)target; + + // force limits to ints if whole numbers. + // needed to do this here because it wouldn't set in component script for some reason + if (slider.wholeNumbers) + { + _minLimit.floatValue = Mathf.RoundToInt(_minLimit.floatValue); + _maxLimit.floatValue = Mathf.RoundToInt(_maxLimit.floatValue); + } + + // set slider values + slider.SetValues(minValue, maxValue, _minLimit.floatValue, _maxLimit.floatValue); + } + + EditorGUILayout.Space(); + EditorGUILayout.PropertyField(_onValueChanged); + + serializedObject.ApplyModifiedProperties(); + } + + /// + /// Returns true if floating point numbers are within 0.01f (close enough to be considered equal) + /// + /// + /// + /// + private static bool IsEqualFloat(float a, float b) + { + return Math.Abs(a - b) < 0.01f; + } + } +} \ No newline at end of file diff --git a/Editor/MinMaxSliderEditor.cs.meta b/Editor/MinMaxSliderEditor.cs.meta new file mode 100644 index 0000000..6730b44 --- /dev/null +++ b/Editor/MinMaxSliderEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69352ed1561021b48ac258f81f48a988 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/UIExtensionsMenuOptions.cs b/Editor/UIExtensionsMenuOptions.cs index b445a7b..9c718c8 100644 --- a/Editor/UIExtensionsMenuOptions.cs +++ b/Editor/UIExtensionsMenuOptions.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using TMPro; +using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using UnityEngine.UI.Extensions; @@ -1847,7 +1848,7 @@ namespace UnityEditor.UI #endregion #region Stepper - [MenuItem("GameObject/UI/Extensions/Stepper", false)] + [MenuItem("GameObject/UI/Extensions/Sliders/Stepper", false)] static public void AddStepper(MenuCommand menuCommand) { GameObject go = CreateUIElementRoot("Stepper", menuCommand, new Vector2(kWidth / 2, kThickHeight)); @@ -1891,7 +1892,7 @@ namespace UnityEditor.UI #endregion #region BoxSlider - [MenuItem("GameObject/UI/Extensions/Box Slider", false)] + [MenuItem("GameObject/UI/Extensions/Sliders/Box Slider", false)] static public void AddBoxSlider(MenuCommand menuCommand) { @@ -1946,7 +1947,7 @@ namespace UnityEditor.UI #endregion #region Radial Slider - [MenuItem("GameObject/UI/Extensions/Radial Slider", false)] + [MenuItem("GameObject/UI/Extensions/Sliders/Radial Slider", false)] static public void AddRadialSlider(MenuCommand menuCommand) { GameObject sliderRoot = CreateUIElementRoot("Radial Slider", menuCommand, s_ThickGUIElementSize); @@ -1984,21 +1985,21 @@ namespace UnityEditor.UI #endregion #region RangeSlider - [MenuItem("GameObject/UI/Extensions/Range Slider", false)] + [MenuItem("GameObject/UI/Extensions/Sliders/Range Slider", false)] static public void AddRangeSlider(MenuCommand menuCommand) { - GameObject rangeSliderRoot = CreateUIElementRoot("Range Slider", menuCommand, new Vector2(160, 20)); + GameObject minMaxSliderRoot = CreateUIElementRoot("Range Slider", menuCommand, new Vector2(160, 20)); - GameObject background = CreateUIObject("Background", rangeSliderRoot); + GameObject background = CreateUIObject("Background", minMaxSliderRoot); - GameObject fillArea = CreateUIObject("Fill Area", rangeSliderRoot); + GameObject fillArea = CreateUIObject("Fill Area", minMaxSliderRoot); GameObject fill = CreateUIObject("Fill", fillArea); - GameObject handleSlideArea = CreateUIObject("Handle Slide Area", rangeSliderRoot); - GameObject lowHandle = CreateUIObject("Low Handle", handleSlideArea); + GameObject handleSlideArea = CreateUIObject("Handle Slide Area", minMaxSliderRoot); + GameObject minHandle = CreateUIObject("Low Handle", handleSlideArea); GameObject highHandle = CreateUIObject("High Handle", handleSlideArea); - SetAnchorsAndStretch(rangeSliderRoot); + SetAnchorsAndStretch(minMaxSliderRoot); Image backgroundImage = background.AddComponent(); backgroundImage.sprite = AssetDatabase.GetBuiltinExtraResource(kBackgroundSpriteResourcePath); backgroundImage.type = Image.Type.Sliced; @@ -2029,8 +2030,8 @@ namespace UnityEditor.UI handleSlideRect.offsetMin = new Vector2(10, -10); handleSlideRect.offsetMax = new Vector2(-10, 10); - RectTransform lowHandleRect = SetAnchorsAndStretch(lowHandle); - Image lowHandleImage = lowHandle.AddComponent(); + RectTransform lowHandleRect = SetAnchorsAndStretch(minHandle); + Image lowHandleImage = minHandle.AddComponent(); lowHandleImage.sprite = AssetDatabase.GetBuiltinExtraResource(kKnobPath); lowHandleRect.sizeDelta = new Vector2(20, 0); @@ -2039,7 +2040,7 @@ namespace UnityEditor.UI highHandleImage.sprite = AssetDatabase.GetBuiltinExtraResource(kKnobPath); highHandleRect.sizeDelta = new Vector2(20, 0); - RangeSlider rangeSlider = rangeSliderRoot.AddComponent(); + RangeSlider rangeSlider = minMaxSliderRoot.AddComponent(); rangeSlider.FillRect = fillRect; rangeSlider.LowHandleRect = lowHandleRect; rangeSlider.HighHandleRect = highHandleRect; @@ -2047,7 +2048,7 @@ namespace UnityEditor.UI rangeSlider.HighValue = rangeSlider.MaxValue; rangeSlider.targetGraphic = fillImage; - Selection.activeGameObject = rangeSliderRoot; + Selection.activeGameObject = minMaxSliderRoot; } #endregion @@ -2062,6 +2063,80 @@ namespace UnityEditor.UI } #endregion + #region MinMaxSlider + [MenuItem("GameObject/UI/Extensions/Sliders/MinMax Slider", false)] + static public void AddMinMaxSlider(MenuCommand menuCommand) + { + GameObject minMaxSliderRoot = CreateUIElementRoot("MinMax Slider", menuCommand, new Vector2(390, 60)); + + //GameObject background = CreateUIObject("Background", rangeSliderRoot); + + GameObject sliderBounds = CreateUIObject("Slider Bounds", minMaxSliderRoot); + GameObject middleGraphic = CreateUIObject("Middle Graphic", minMaxSliderRoot); + + GameObject minHandle = CreateUIObject("Min Handle", minMaxSliderRoot); + GameObject minHandleText = CreateUIObject("Min Text", minHandle); + GameObject maxHandle = CreateUIObject("Max Handle", minMaxSliderRoot); + GameObject maxHandleText = CreateUIObject("Max Text", maxHandle); + + SetAnchorsAndStretch(minMaxSliderRoot); + Image backgroundImage = minMaxSliderRoot.AddComponent(); + backgroundImage.sprite = AssetDatabase.GetBuiltinExtraResource(kStandardSpritePath); + backgroundImage.type = Image.Type.Sliced; + backgroundImage.fillCenter = false; + backgroundImage.color = new Color(27, 41, 89); + + RectTransform backgroundRect = backgroundImage.rectTransform; + backgroundRect.anchorMin = new Vector2(0.5f, 0.5f); + backgroundRect.anchorMax = new Vector2(0.5f, 0.5f); + backgroundRect.sizeDelta = Vector2.zero; + + RectTransform sliderBoundsRect = SetAnchorsAndStretch(sliderBounds); + sliderBoundsRect.anchorMin = new Vector2(0, 0); + sliderBoundsRect.anchorMax = new Vector2(1, 1); + + RectTransform middleGraphicRect = SetAnchorsAndStretch(middleGraphic); + Image fillImage = middleGraphic.AddComponent(); + fillImage.sprite = AssetDatabase.GetBuiltinExtraResource(kStandardSpritePath); + fillImage.type = Image.Type.Sliced; + fillImage.fillCenter = true; + fillImage.color = new Color(41, 98, 164); + + RectTransform minHandleRect = SetAnchorsAndStretch(minHandle); + Image lowHandleImage = minHandle.AddComponent(); + lowHandleImage.sprite = AssetDatabase.GetBuiltinExtraResource(kStandardSpritePath); + minHandleRect.sizeDelta = new Vector2(30, 62); + + RectTransform minHandleTextRect = SetAnchorsAndStretch(minHandleText); + TextMeshProUGUI minHandleTextComponent = minHandleText.AddComponent(); + minHandleTextComponent.text = "0"; + minHandleTextComponent.fontSize = 36; + minHandleTextRect.sizeDelta = new Vector2(70, 50); + minHandleTextRect.position = new Vector3(0, -60,0); + + RectTransform maxHandleRect = SetAnchorsAndStretch(maxHandle); + Image maxHandleImage = maxHandle.AddComponent(); + maxHandleImage.sprite = AssetDatabase.GetBuiltinExtraResource(kStandardSpritePath); + maxHandleRect.sizeDelta = new Vector2(20, 0); + + RectTransform maxHandleTextRect = SetAnchorsAndStretch(maxHandleText); + TextMeshProUGUI maxHandleTextComponent = maxHandleText.AddComponent(); + maxHandleTextComponent.text = "0"; + maxHandleTextComponent.fontSize = 36; + maxHandleTextRect.sizeDelta = new Vector2(70, 50); + maxHandleTextRect.position = new Vector3(0, -60, 0); + + MinMaxSlider minMaxSlider = minMaxSliderRoot.AddComponent(); + minMaxSlider.SliderBounds = sliderBoundsRect; + minMaxSlider.MinHandle = minHandleRect; + minMaxSlider.MaxHandle = maxHandleRect; + minMaxSlider.MiddleGraphic = middleGraphicRect; + minMaxSlider.MinText = minHandleTextComponent; + minMaxSlider.MaxText = maxHandleTextComponent; + + Selection.activeGameObject = minMaxSliderRoot; + } + #endregion #endregion diff --git a/Editor/UnityUIExtensions.Editor.asmdef b/Editor/UnityUIExtensions.Editor.asmdef index a6ccce7..568a7e8 100644 --- a/Editor/UnityUIExtensions.Editor.asmdef +++ b/Editor/UnityUIExtensions.Editor.asmdef @@ -1,9 +1,11 @@ { "name": "UnityUIExtensions.editor", + "rootNamespace": "", "references": [ "GUID:343deaaf83e0cee4ca978e7df0b80d21", "GUID:2bafac87e7f4b9b418d9448d219b01ab", - "GUID:cf414061cae3a954baf92763590f3127" + "GUID:cf414061cae3a954baf92763590f3127", + "GUID:6055be8ebefd69e48b49212b09b47b2f" ], "includePlatforms": [ "Editor" @@ -14,5 +16,6 @@ "precompiledReferences": [], "autoReferenced": true, "defineConstraints": [], - "versionDefines": [] + "versionDefines": [], + "noEngineReferences": false } \ No newline at end of file diff --git a/Runtime/Scripts/Controls/Sliders.meta b/Runtime/Scripts/Controls/Sliders.meta new file mode 100644 index 0000000..6ae79ac --- /dev/null +++ b/Runtime/Scripts/Controls/Sliders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d7bdc7e70331fe24aba2c9549f84c657 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/Controls/BoxSlider.cs b/Runtime/Scripts/Controls/Sliders/BoxSlider.cs similarity index 96% rename from Runtime/Scripts/Controls/BoxSlider.cs rename to Runtime/Scripts/Controls/Sliders/BoxSlider.cs index dca4608..9360300 100644 --- a/Runtime/Scripts/Controls/BoxSlider.cs +++ b/Runtime/Scripts/Controls/Sliders/BoxSlider.cs @@ -1,371 +1,371 @@ -///Credit judah4 -///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/ - -using System; -using UnityEngine.Events; -using UnityEngine.EventSystems; - -namespace UnityEngine.UI.Extensions -{ - [RequireComponent(typeof(RectTransform))] - [AddComponentMenu("UI/Extensions/BoxSlider")] - public class BoxSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement - { - public enum Direction - { - LeftToRight, - RightToLeft, - BottomToTop, - TopToBottom, - } - - [Serializable] - public class BoxSliderEvent : UnityEvent { } - - [SerializeField] - private RectTransform m_HandleRect; - public RectTransform HandleRect { get { return m_HandleRect; } set { if (SetClass(ref m_HandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } } - - [Space(6)] - - [SerializeField] - private float m_MinValue = 0; - public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } } - - [SerializeField] - private float m_MaxValue = 1; - public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } } - - [SerializeField] - private bool m_WholeNumbers = false; - public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } } - - [SerializeField] - private float m_ValueX = 1f; - public float ValueX - { - get - { - if (WholeNumbers) - return Mathf.Round(m_ValueX); - return m_ValueX; - } - set - { - SetX(value); - } - } - - public float NormalizedValueX - { - get - { - if (Mathf.Approximately(MinValue, MaxValue)) - return 0; - return Mathf.InverseLerp(MinValue, MaxValue, ValueX); - } - set - { - this.ValueX = Mathf.Lerp(MinValue, MaxValue, value); - } - } - - [SerializeField] - private float m_ValueY = 1f; - public float ValueY - { - get - { - if (WholeNumbers) - return Mathf.Round(m_ValueY); - return m_ValueY; - } - set - { - SetY(value); - } - } - - public float NormalizedValueY - { - get - { - if (Mathf.Approximately(MinValue, MaxValue)) - return 0; - return Mathf.InverseLerp(MinValue, MaxValue, ValueY); - } - set - { - this.ValueY = Mathf.Lerp(MinValue, MaxValue, value); - } - } - - [Space(6)] - - // Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers. - [SerializeField] - private BoxSliderEvent m_OnValueChanged = new BoxSliderEvent(); - public BoxSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } } - - // Private fields - - private Transform m_HandleTransform; - private RectTransform m_HandleContainerRect; - - // The offset from handle position to mouse down position - private Vector2 m_Offset = Vector2.zero; - - private DrivenRectTransformTracker m_Tracker; - - // Size of each step. - float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } } - - protected BoxSlider() - { } - -#if UNITY_EDITOR - protected override void OnValidate() - { - base.OnValidate(); - - if (WholeNumbers) - { - m_MinValue = Mathf.Round(m_MinValue); - m_MaxValue = Mathf.Round(m_MaxValue); - } - UpdateCachedReferences(); - SetX(m_ValueX, false); - SetY(m_ValueY, false); - // Update rects since other things might affect them even if value didn't change. - if(!Application.isPlaying) UpdateVisuals(); - -#if UNITY_2018_3_OR_NEWER - if (!Application.isPlaying) -#else - var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this); - if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying) -#endif - { - CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this); - } - } - -#endif // if UNITY_EDITOR - - public virtual void Rebuild(CanvasUpdate executing) - { -#if UNITY_EDITOR - if (executing == CanvasUpdate.Prelayout) - OnValueChanged.Invoke(ValueX, ValueY); -#endif - } - - public void LayoutComplete() - { - - } - - public void GraphicUpdateComplete() - { - - } - - public static bool SetClass(ref T currentValue, T newValue) where T : class - { - if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue))) - return false; - - currentValue = newValue; - return true; - } - - public static bool SetStruct(ref T currentValue, T newValue) where T : struct - { - if (currentValue.Equals(newValue)) - return false; - - currentValue = newValue; - return true; - } - - protected override void OnEnable() - { - base.OnEnable(); - UpdateCachedReferences(); - SetX(m_ValueX, false); - SetY(m_ValueY, false); - // Update rects since they need to be initialized correctly. - UpdateVisuals(); - } - - protected override void OnDisable() - { - m_Tracker.Clear(); - base.OnDisable(); - } - - void UpdateCachedReferences() - { - - if (m_HandleRect) - { - m_HandleTransform = m_HandleRect.transform; - if (m_HandleTransform.parent != null) - m_HandleContainerRect = m_HandleTransform.parent.GetComponent(); - } - else - { - m_HandleContainerRect = null; - } - } - - // Set the valueUpdate the visible Image. - void SetX(float input) - { - SetX(input, true); - } - - void SetX(float input, bool sendCallback) - { - // Clamp the input - float newValue = Mathf.Clamp(input, MinValue, MaxValue); - if (WholeNumbers) - newValue = Mathf.Round(newValue); - - // If the stepped value doesn't match the last one, it's time to update - if (m_ValueX == newValue) - return; - - m_ValueX = newValue; - UpdateVisuals(); - if (sendCallback) - m_OnValueChanged.Invoke(newValue, ValueY); - } - - void SetY(float input) - { - SetY(input, true); - } - - void SetY(float input, bool sendCallback) - { - // Clamp the input - float newValue = Mathf.Clamp(input, MinValue, MaxValue); - if (WholeNumbers) - newValue = Mathf.Round(newValue); - - // If the stepped value doesn't match the last one, it's time to update - if (m_ValueY == newValue) - return; - - m_ValueY = newValue; - UpdateVisuals(); - if (sendCallback) - m_OnValueChanged.Invoke(ValueX, newValue); - } - - - protected override void OnRectTransformDimensionsChange() - { - base.OnRectTransformDimensionsChange(); - UpdateVisuals(); - } - - enum Axis - { - Horizontal = 0, - Vertical = 1 - } - - - // 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(); - - - //to business! - if (m_HandleContainerRect != null) - { - m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors); - Vector2 anchorMin = Vector2.zero; - Vector2 anchorMax = Vector2.one; - anchorMin[0] = anchorMax[0] = (NormalizedValueX); - anchorMin[1] = anchorMax[1] = (NormalizedValueY); - - if (Application.isPlaying) - { - 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; - if (clickRect != null && clickRect.rect.size[0] > 0) - { - Vector2 localCursor; - if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor)) - return; - localCursor -= clickRect.rect.position; - - float val = Mathf.Clamp01((localCursor - m_Offset)[0] / clickRect.rect.size[0]); - NormalizedValueX = (val); - - float valY = Mathf.Clamp01((localCursor - m_Offset)[1] / clickRect.rect.size[1]); - NormalizedValueY = (valY); - - } - } - - private bool CanDrag(PointerEventData eventData) - { - return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left; - } - - public override void OnPointerDown(PointerEventData eventData) - { - if (!CanDrag(eventData)) - return; - - base.OnPointerDown(eventData); - - m_Offset = Vector2.zero; - if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect, eventData.position, eventData.enterEventCamera)) - { - Vector2 localMousePos; - if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect, eventData.position, eventData.pressEventCamera, out localMousePos)) - m_Offset = localMousePos; - m_Offset.y = -m_Offset.y; - } - else - { - // Outside the slider handle - jump to this point instead - UpdateDrag(eventData, eventData.pressEventCamera); - } - } - - public virtual void OnDrag(PointerEventData eventData) - { - if (!CanDrag(eventData)) - return; - - UpdateDrag(eventData, eventData.pressEventCamera); - } - - public virtual void OnInitializePotentialDrag(PointerEventData eventData) - { - eventData.useDragThreshold = false; - } - - } -} +///Credit judah4 +///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/ + +using System; +using UnityEngine.Events; +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [RequireComponent(typeof(RectTransform))] + [AddComponentMenu("UI/Extensions/Sliders/BoxSlider")] + public class BoxSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement + { + public enum Direction + { + LeftToRight, + RightToLeft, + BottomToTop, + TopToBottom, + } + + [Serializable] + public class BoxSliderEvent : UnityEvent { } + + [SerializeField] + private RectTransform m_HandleRect; + public RectTransform HandleRect { get { return m_HandleRect; } set { if (SetClass(ref m_HandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } } + + [Space(6)] + + [SerializeField] + private float m_MinValue = 0; + public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } } + + [SerializeField] + private float m_MaxValue = 1; + public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } } + + [SerializeField] + private bool m_WholeNumbers = false; + public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } } + + [SerializeField] + private float m_ValueX = 1f; + public float ValueX + { + get + { + if (WholeNumbers) + return Mathf.Round(m_ValueX); + return m_ValueX; + } + set + { + SetX(value); + } + } + + public float NormalizedValueX + { + get + { + if (Mathf.Approximately(MinValue, MaxValue)) + return 0; + return Mathf.InverseLerp(MinValue, MaxValue, ValueX); + } + set + { + this.ValueX = Mathf.Lerp(MinValue, MaxValue, value); + } + } + + [SerializeField] + private float m_ValueY = 1f; + public float ValueY + { + get + { + if (WholeNumbers) + return Mathf.Round(m_ValueY); + return m_ValueY; + } + set + { + SetY(value); + } + } + + public float NormalizedValueY + { + get + { + if (Mathf.Approximately(MinValue, MaxValue)) + return 0; + return Mathf.InverseLerp(MinValue, MaxValue, ValueY); + } + set + { + this.ValueY = Mathf.Lerp(MinValue, MaxValue, value); + } + } + + [Space(6)] + + // Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers. + [SerializeField] + private BoxSliderEvent m_OnValueChanged = new BoxSliderEvent(); + public BoxSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } } + + // Private fields + + private Transform m_HandleTransform; + private RectTransform m_HandleContainerRect; + + // The offset from handle position to mouse down position + private Vector2 m_Offset = Vector2.zero; + + private DrivenRectTransformTracker m_Tracker; + + // Size of each step. + float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } } + + protected BoxSlider() + { } + +#if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + + if (WholeNumbers) + { + m_MinValue = Mathf.Round(m_MinValue); + m_MaxValue = Mathf.Round(m_MaxValue); + } + UpdateCachedReferences(); + SetX(m_ValueX, false); + SetY(m_ValueY, false); + // Update rects since other things might affect them even if value didn't change. + if(!Application.isPlaying) UpdateVisuals(); + +#if UNITY_2018_3_OR_NEWER + if (!Application.isPlaying) +#else + var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this); + if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying) +#endif + { + CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this); + } + } + +#endif // if UNITY_EDITOR + + public virtual void Rebuild(CanvasUpdate executing) + { +#if UNITY_EDITOR + if (executing == CanvasUpdate.Prelayout) + OnValueChanged.Invoke(ValueX, ValueY); +#endif + } + + public void LayoutComplete() + { + + } + + public void GraphicUpdateComplete() + { + + } + + public static bool SetClass(ref T currentValue, T newValue) where T : class + { + if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue))) + return false; + + currentValue = newValue; + return true; + } + + public static bool SetStruct(ref T currentValue, T newValue) where T : struct + { + if (currentValue.Equals(newValue)) + return false; + + currentValue = newValue; + return true; + } + + protected override void OnEnable() + { + base.OnEnable(); + UpdateCachedReferences(); + SetX(m_ValueX, false); + SetY(m_ValueY, false); + // Update rects since they need to be initialized correctly. + UpdateVisuals(); + } + + protected override void OnDisable() + { + m_Tracker.Clear(); + base.OnDisable(); + } + + void UpdateCachedReferences() + { + + if (m_HandleRect) + { + m_HandleTransform = m_HandleRect.transform; + if (m_HandleTransform.parent != null) + m_HandleContainerRect = m_HandleTransform.parent.GetComponent(); + } + else + { + m_HandleContainerRect = null; + } + } + + // Set the valueUpdate the visible Image. + void SetX(float input) + { + SetX(input, true); + } + + void SetX(float input, bool sendCallback) + { + // Clamp the input + float newValue = Mathf.Clamp(input, MinValue, MaxValue); + if (WholeNumbers) + newValue = Mathf.Round(newValue); + + // If the stepped value doesn't match the last one, it's time to update + if (m_ValueX == newValue) + return; + + m_ValueX = newValue; + UpdateVisuals(); + if (sendCallback) + m_OnValueChanged.Invoke(newValue, ValueY); + } + + void SetY(float input) + { + SetY(input, true); + } + + void SetY(float input, bool sendCallback) + { + // Clamp the input + float newValue = Mathf.Clamp(input, MinValue, MaxValue); + if (WholeNumbers) + newValue = Mathf.Round(newValue); + + // If the stepped value doesn't match the last one, it's time to update + if (m_ValueY == newValue) + return; + + m_ValueY = newValue; + UpdateVisuals(); + if (sendCallback) + m_OnValueChanged.Invoke(ValueX, newValue); + } + + + protected override void OnRectTransformDimensionsChange() + { + base.OnRectTransformDimensionsChange(); + UpdateVisuals(); + } + + enum Axis + { + Horizontal = 0, + Vertical = 1 + } + + + // 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(); + + + //to business! + if (m_HandleContainerRect != null) + { + m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors); + Vector2 anchorMin = Vector2.zero; + Vector2 anchorMax = Vector2.one; + anchorMin[0] = anchorMax[0] = (NormalizedValueX); + anchorMin[1] = anchorMax[1] = (NormalizedValueY); + + if (Application.isPlaying) + { + 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; + if (clickRect != null && clickRect.rect.size[0] > 0) + { + Vector2 localCursor; + if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor)) + return; + localCursor -= clickRect.rect.position; + + float val = Mathf.Clamp01((localCursor - m_Offset)[0] / clickRect.rect.size[0]); + NormalizedValueX = (val); + + float valY = Mathf.Clamp01((localCursor - m_Offset)[1] / clickRect.rect.size[1]); + NormalizedValueY = (valY); + + } + } + + private bool CanDrag(PointerEventData eventData) + { + return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left; + } + + public override void OnPointerDown(PointerEventData eventData) + { + if (!CanDrag(eventData)) + return; + + base.OnPointerDown(eventData); + + m_Offset = Vector2.zero; + if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect, eventData.position, eventData.enterEventCamera)) + { + Vector2 localMousePos; + if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect, eventData.position, eventData.pressEventCamera, out localMousePos)) + m_Offset = localMousePos; + m_Offset.y = -m_Offset.y; + } + else + { + // Outside the slider handle - jump to this point instead + UpdateDrag(eventData, eventData.pressEventCamera); + } + } + + public virtual void OnDrag(PointerEventData eventData) + { + if (!CanDrag(eventData)) + return; + + UpdateDrag(eventData, eventData.pressEventCamera); + } + + public virtual void OnInitializePotentialDrag(PointerEventData eventData) + { + eventData.useDragThreshold = false; + } + + } +} diff --git a/Runtime/Scripts/Controls/BoxSlider.cs.meta b/Runtime/Scripts/Controls/Sliders/BoxSlider.cs.meta similarity index 100% rename from Runtime/Scripts/Controls/BoxSlider.cs.meta rename to Runtime/Scripts/Controls/Sliders/BoxSlider.cs.meta diff --git a/Runtime/Scripts/Controls/Sliders/MinMaxSlider.cs b/Runtime/Scripts/Controls/Sliders/MinMaxSlider.cs new file mode 100644 index 0000000..0550f13 --- /dev/null +++ b/Runtime/Scripts/Controls/Sliders/MinMaxSlider.cs @@ -0,0 +1,347 @@ +///Credit brogan89 +///Sourced from - https://github.com/brogan89/MinMaxSlider + +using System; +using TMPro; +using UnityEngine.Events; +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [RequireComponent(typeof(RectTransform))] + [AddComponentMenu("UI/Extensions/Sliders/MinMax Slider")] + public class MinMaxSlider : Selectable, IBeginDragHandler, IDragHandler, IEndDragHandler + { + private enum DragState + { + Both, + Min, + Max + } + + [Header("UI Controls")] + [SerializeField] private Camera customCamera = null; + [SerializeField] private RectTransform sliderBounds = null; + [SerializeField] private RectTransform minHandle = null; + [SerializeField] private RectTransform maxHandle = null; + [SerializeField] private RectTransform middleGraphic = null; + + // text components (optional) + [Header("Display Text (Optional)")] + [SerializeField] private TextMeshProUGUI minText = null; + [SerializeField] private TextMeshProUGUI maxText = null; + [SerializeField] private string textFormat = "0"; + + // values + [Header("Limits")] + [SerializeField] private float minLimit = 0; + [SerializeField] private float maxLimit = 100; + + [Header("Values")] + public bool wholeNumbers; + [SerializeField] private float minValue = 25; + [SerializeField] private float maxValue = 75; + + public MinMaxValues Values => new MinMaxValues(minValue, maxValue, minLimit, maxLimit); + + public RectTransform SliderBounds { get => sliderBounds; set => sliderBounds = value; } + public RectTransform MinHandle { get => minHandle; set => minHandle = value; } + public RectTransform MaxHandle { get => maxHandle; set => maxHandle = value; } + public RectTransform MiddleGraphic { get => middleGraphic; set => middleGraphic = value; } + public TextMeshProUGUI MinText { get => minText; set => minText = value; } + public TextMeshProUGUI MaxText { get => maxText; set => maxText = value; } + + /// + /// Event invoked when either slider value has changed + /// + /// T0 = min, T1 = max + /// + [Serializable] + public class SliderEvent : UnityEvent { } + + public SliderEvent onValueChanged = new SliderEvent(); + + private Vector2 dragStartPosition; + private float dragStartMinValue01; + private float dragStartMaxValue01; + private DragState dragState; + private bool passDragEvents; // this allows drag events to be passed through to scrollers + + private Camera mainCamera; + private Canvas parentCanvas; + private bool isOverlayCanvas; + + protected override void Start() + { + base.Start(); + + if (!sliderBounds) + { + sliderBounds = transform as RectTransform; + } + + parentCanvas = GetComponentInParent(); + isOverlayCanvas = parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay; + mainCamera = customCamera != null ? customCamera : Camera.main; + } + + public void SetLimits(float minLimit, float maxLimit) + { + this.minLimit = wholeNumbers ? Mathf.RoundToInt(minLimit) : minLimit; + this.maxLimit = wholeNumbers ? Mathf.RoundToInt(maxLimit) : maxLimit; + } + + public void SetValues(MinMaxValues values, bool notify = true) + { + SetValues(values.minValue, values.maxValue, values.minLimit, values.maxLimit, notify); + } + + public void SetValues(float minValue, float maxValue, bool notify = true) + { + SetValues(minValue, maxValue, minLimit, maxLimit, notify); + } + + public void SetValues(float minValue, float maxValue, float minLimit, float maxLimit, bool notify = true) + { + this.minValue = wholeNumbers ? Mathf.RoundToInt(minValue) : minValue; + this.maxValue = wholeNumbers ? Mathf.RoundToInt(maxValue) : maxValue; + SetLimits(minLimit, maxLimit); + + RefreshSliders(); + UpdateText(); + UpdateMiddleGraphic(); + + if (notify) + { + // event + onValueChanged.Invoke(this.minValue, this.maxValue); + } + } + + private void RefreshSliders() + { + SetSliderAnchors(); + + float clampedMin = Mathf.Clamp(minValue, minLimit, maxLimit); + SetMinHandleValue01(minHandle, GetPercentage(minLimit, maxLimit, clampedMin)); + + float clampedMax = Mathf.Clamp(maxValue, minLimit, maxLimit); + SetMaxHandleValue01(maxHandle, GetPercentage(minLimit, maxLimit, clampedMax)); + } + + private void SetSliderAnchors() + { + minHandle.anchorMin = new Vector2(0, 0.5f); + minHandle.anchorMax = new Vector2(0, 0.5f); + minHandle.pivot = new Vector2(0.5f, 0.5f); + + maxHandle.anchorMin = new Vector2(1, 0.5f); + maxHandle.anchorMax = new Vector2(1, 0.5f); + maxHandle.pivot = new Vector2(0.5f, 0.5f); + } + + private void UpdateText() + { + if (minText) + { + minText.SetText(minValue.ToString(textFormat)); + } + + if (maxText) + { + maxText.SetText(maxValue.ToString(textFormat)); + } + } + + private void UpdateMiddleGraphic() + { + if (!middleGraphic) return; + + middleGraphic.anchorMin = Vector2.zero; + middleGraphic.anchorMax = Vector2.one; + middleGraphic.offsetMin = new Vector2(minHandle.anchoredPosition.x, 0); + middleGraphic.offsetMax = new Vector2(maxHandle.anchoredPosition.x, 0); + } + + #region IDragHandler + public void OnBeginDrag(PointerEventData eventData) + { + passDragEvents = Math.Abs(eventData.delta.x) < Math.Abs(eventData.delta.y); + + if (passDragEvents) + { + PassDragEvents(x => x.OnBeginDrag(eventData)); + } + else + { + Camera uiCamera = isOverlayCanvas ? null : mainCamera; + RectTransformUtility.ScreenPointToLocalPointInRectangle(sliderBounds, eventData.position, uiCamera, out dragStartPosition); + + float dragStartValue = GetValueOfPointInSliderBounds01(dragStartPosition); + dragStartMinValue01 = GetMinHandleValue01(minHandle); + dragStartMaxValue01 = GetMaxHandleValue01(maxHandle); + + // set drag state + if (dragStartValue < dragStartMinValue01 || RectTransformUtility.RectangleContainsScreenPoint(minHandle, eventData.position, uiCamera)) + { + dragState = DragState.Min; + minHandle.SetAsLastSibling(); + } + else if (dragStartValue > dragStartMaxValue01 || RectTransformUtility.RectangleContainsScreenPoint(maxHandle, eventData.position, uiCamera)) + { + dragState = DragState.Max; + maxHandle.SetAsLastSibling(); + } + else + { + dragState = DragState.Both; + } + } + } + + public void OnDrag(PointerEventData eventData) + { + if (passDragEvents) + { + PassDragEvents(x => x.OnDrag(eventData)); + } + else if (minHandle && maxHandle) + { + RectTransformUtility.ScreenPointToLocalPointInRectangle(sliderBounds, eventData.position, isOverlayCanvas ? null : mainCamera, out Vector2 clickPosition); + + SetSliderAnchors(); + + if (dragState == DragState.Min || dragState == DragState.Max) + { + float dragPosition01 = GetValueOfPointInSliderBounds01(clickPosition); + float minHandleValue = GetMinHandleValue01(minHandle); + float maxHandleValue = GetMaxHandleValue01(maxHandle); + + if (dragState == DragState.Min) + SetMinHandleValue01(minHandle, Mathf.Clamp(dragPosition01, 0, maxHandleValue)); + else if (dragState == DragState.Max) + SetMaxHandleValue01(maxHandle, Mathf.Clamp(dragPosition01, minHandleValue, 1)); + } + else + { + float distancePercent = (clickPosition.x - dragStartPosition.x) / sliderBounds.rect.width; + SetMinHandleValue01(minHandle, dragStartMinValue01 + distancePercent); + SetMaxHandleValue01(maxHandle, dragStartMaxValue01 + distancePercent); + } + + // set values + float min = Mathf.Lerp(minLimit, maxLimit, GetMinHandleValue01(minHandle)); + float max = Mathf.Lerp(minLimit, maxLimit, GetMaxHandleValue01(maxHandle)); + SetValues(min, max); + + UpdateText(); + UpdateMiddleGraphic(); + } + } + + public void OnEndDrag(PointerEventData eventData) + { + if (passDragEvents) + { + PassDragEvents(x => x.OnEndDrag(eventData)); + } + else + { + float minHandleValue = GetMinHandleValue01(minHandle); + float maxHandleValue = GetMaxHandleValue01(maxHandle); + + // this safe guards a possible situation where the slides can get stuck + if (Math.Abs(minHandleValue) < MinMaxValues.FLOAT_TOL && Math.Abs(maxHandleValue) < MinMaxValues.FLOAT_TOL) + { + maxHandle.SetAsLastSibling(); + } + else if (Math.Abs(minHandleValue - 1) < MinMaxValues.FLOAT_TOL && Math.Abs(maxHandleValue - 1) < MinMaxValues.FLOAT_TOL) + { + minHandle.SetAsLastSibling(); + } + } + } + #endregion IDragHandler + + private void PassDragEvents(Action callback) where T : IEventSystemHandler + { + Transform parent = transform.parent; + + while (parent != null) + { + foreach (var component in parent.GetComponents()) + { + if (!(component is T)) continue; + + callback.Invoke((T)(IEventSystemHandler)component); + return; + } + + parent = parent.parent; + } + } + + /// + /// Sets position of max handle RectTransform + /// + /// + /// Normalized handle position + private void SetMaxHandleValue01(RectTransform handle, float value01) + { + handle.anchoredPosition = new Vector2(value01 * sliderBounds.rect.width - sliderBounds.rect.width + sliderBounds.offsetMax.x, handle.anchoredPosition.y); + } + + /// + /// Sets position of min handle RectTransform + /// + /// + /// Normalized handle position + private void SetMinHandleValue01(RectTransform handle, float value01) + { + handle.anchoredPosition = new Vector2(value01 * sliderBounds.rect.width + sliderBounds.offsetMin.x, handle.anchoredPosition.y); + } + + /// + /// Returns normalized position of max handle RectTransform + /// + /// + /// Normalized position of max handle RectTransform + private float GetMaxHandleValue01(RectTransform handle) + { + return 1 + (handle.anchoredPosition.x - sliderBounds.offsetMax.x) / sliderBounds.rect.width; + } + + /// + /// Returns normalized position of min handle RectTransform + /// + /// + /// Normalized position of min handle RectTransform + private float GetMinHandleValue01(RectTransform handle) + { + return (handle.anchoredPosition.x - sliderBounds.offsetMin.x) / sliderBounds.rect.width; + } + + /// + /// Returns normalized position of a point in a slider bounds rectangle + /// + /// + /// Normalized position of a point in a slider bounds rectangle + private float GetValueOfPointInSliderBounds01(Vector2 position) + { + var width = sliderBounds.rect.width; + return Mathf.Clamp((position.x + width / 2) / width, 0, 1); + } + + /// + /// Returns percentage of input based on min and max values + /// + /// + /// + /// + /// + private static float GetPercentage(float min, float max, float input) + { + return (input - min) / (max - min); + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/Controls/Sliders/MinMaxSlider.cs.meta b/Runtime/Scripts/Controls/Sliders/MinMaxSlider.cs.meta new file mode 100644 index 0000000..05e3a83 --- /dev/null +++ b/Runtime/Scripts/Controls/Sliders/MinMaxSlider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9f9954231c8bab419504a7ac5ff133e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/Controls/RadialSlider.cs b/Runtime/Scripts/Controls/Sliders/RadialSlider.cs similarity index 99% rename from Runtime/Scripts/Controls/RadialSlider.cs rename to Runtime/Scripts/Controls/Sliders/RadialSlider.cs index 7bb5672..669c994 100644 --- a/Runtime/Scripts/Controls/RadialSlider.cs +++ b/Runtime/Scripts/Controls/Sliders/RadialSlider.cs @@ -8,8 +8,8 @@ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { - [AddComponentMenu("UI/Extensions/Radial Slider")] [RequireComponent(typeof(Image))] + [AddComponentMenu("UI/Extensions/Sliders/Radial Slider")] public class RadialSlider : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler { private bool isPointerDown, isPointerReleased, lerpInProgress; diff --git a/Runtime/Scripts/Controls/RadialSlider.cs.meta b/Runtime/Scripts/Controls/Sliders/RadialSlider.cs.meta similarity index 100% rename from Runtime/Scripts/Controls/RadialSlider.cs.meta rename to Runtime/Scripts/Controls/Sliders/RadialSlider.cs.meta diff --git a/Runtime/Scripts/Controls/RangeSlider.cs b/Runtime/Scripts/Controls/Sliders/RangeSlider.cs similarity index 99% rename from Runtime/Scripts/Controls/RangeSlider.cs rename to Runtime/Scripts/Controls/Sliders/RangeSlider.cs index d21d337..75e4890 100644 --- a/Runtime/Scripts/Controls/RangeSlider.cs +++ b/Runtime/Scripts/Controls/Sliders/RangeSlider.cs @@ -9,9 +9,9 @@ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { - [AddComponentMenu("UI/Extensions/Range Slider", 34)] [ExecuteInEditMode] [RequireComponent(typeof(RectTransform))] + [AddComponentMenu("UI/Extensions/Sliders/Range Slider", 34)] public class RangeSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement { public enum Direction diff --git a/Runtime/Scripts/Controls/RangeSlider.cs.meta b/Runtime/Scripts/Controls/Sliders/RangeSlider.cs.meta similarity index 100% rename from Runtime/Scripts/Controls/RangeSlider.cs.meta rename to Runtime/Scripts/Controls/Sliders/RangeSlider.cs.meta diff --git a/Runtime/Scripts/Controls/Stepper.cs b/Runtime/Scripts/Controls/Sliders/Stepper.cs similarity index 99% rename from Runtime/Scripts/Controls/Stepper.cs rename to Runtime/Scripts/Controls/Sliders/Stepper.cs index 6d920d8..d7720c6 100644 --- a/Runtime/Scripts/Controls/Stepper.cs +++ b/Runtime/Scripts/Controls/Sliders/Stepper.cs @@ -9,8 +9,8 @@ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { // Stepper control - [AddComponentMenu("UI/Extensions/Stepper")] [RequireComponent(typeof(RectTransform))] + [AddComponentMenu("UI/Extensions/Sliders/Stepper")] public class Stepper : UIBehaviour { private Selectable[] _sides; diff --git a/Runtime/Scripts/Controls/Stepper.cs.meta b/Runtime/Scripts/Controls/Sliders/Stepper.cs.meta similarity index 100% rename from Runtime/Scripts/Controls/Stepper.cs.meta rename to Runtime/Scripts/Controls/Sliders/Stepper.cs.meta diff --git a/Runtime/Scripts/Controls/StepperSide.cs b/Runtime/Scripts/Controls/Sliders/StepperSide.cs similarity index 100% rename from Runtime/Scripts/Controls/StepperSide.cs rename to Runtime/Scripts/Controls/Sliders/StepperSide.cs diff --git a/Runtime/Scripts/Controls/StepperSide.cs.meta b/Runtime/Scripts/Controls/Sliders/StepperSide.cs.meta similarity index 100% rename from Runtime/Scripts/Controls/StepperSide.cs.meta rename to Runtime/Scripts/Controls/Sliders/StepperSide.cs.meta diff --git a/Runtime/Scripts/Utilities/MinMaxValues.cs b/Runtime/Scripts/Utilities/MinMaxValues.cs new file mode 100644 index 0000000..48cb616 --- /dev/null +++ b/Runtime/Scripts/Utilities/MinMaxValues.cs @@ -0,0 +1,50 @@ +///Credit brogan89 +///Sourced from - https://github.com/brogan89/MinMaxSlider + +using System; + +namespace UnityEngine.UI.Extensions +{ + [Serializable] + public struct MinMaxValues + { + /// + /// Floating point tolerance + /// + public const float FLOAT_TOL = 0.01f; + + public float minValue, maxValue, minLimit, maxLimit; + public static MinMaxValues DEFUALT = new MinMaxValues(25, 75, 0, 100); + + public MinMaxValues(float minValue, float maxValue, float minLimit, float maxLimit) + { + this.minValue = minValue; + this.maxValue = maxValue; + this.minLimit = minLimit; + this.maxLimit = maxLimit; + } + + /// + /// Constructor for when values equal limits + /// + /// + /// + public MinMaxValues(float minValue, float maxValue) + { + this.minValue = minValue; + this.maxValue = maxValue; + this.minLimit = minValue; + this.maxLimit = maxValue; + } + + public bool IsAtMinAndMax() + { + return Math.Abs(minValue - minLimit) < FLOAT_TOL && Math.Abs(maxValue - maxLimit) < FLOAT_TOL; + } + + public override string ToString() + { + return $"Values(min:{minValue}, max:{maxValue}) | Limits(min:{minLimit}, max:{maxLimit})"; + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/Utilities/MinMaxValues.cs.meta b/Runtime/Scripts/Utilities/MinMaxValues.cs.meta new file mode 100644 index 0000000..3171a39 --- /dev/null +++ b/Runtime/Scripts/Utilities/MinMaxValues.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44af036687d1cdb4da5686d3431d2c3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: