| | 1 | | using System; |
| | 2 | | using UnityEngine; |
| | 3 | | using UnityEngine.Events; |
| | 4 | | using UnityEngine.EventSystems; |
| | 5 | | using UnityEngine.UI; |
| | 6 | |
|
| | 7 | | namespace UIComponents.Scripts.Components.RangeSlider |
| | 8 | | { |
| | 9 | | /// <summary> |
| | 10 | | /// Credit Ben MacKinnon @Dover8 |
| | 11 | | /// Sourced from - https://github.com/Dover8/Unity-UI-Extensions/tree/range-slider |
| | 12 | | /// Usage: Extension of the standard slider. Two handles determine a low and high value between a Min and Max. |
| | 13 | | /// Raises a UnityEvent passing the low and high values |
| | 14 | | /// </summary> |
| | 15 | | [AddComponentMenu("UI/Range Slider", 34)] |
| | 16 | | [ExecuteInEditMode] |
| | 17 | | [RequireComponent(typeof(RectTransform))] |
| | 18 | | public class RangeSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement |
| | 19 | | { |
| | 20 | | [Serializable] |
| | 21 | | public class RangeSliderEvent : UnityEvent<float, float> { } |
| | 22 | |
|
| | 23 | | [SerializeField] |
| | 24 | | private RectTransform m_FillRect; |
| | 25 | |
|
| 0 | 26 | | public RectTransform FillRect { get { return m_FillRect; } set { if (SetClass(ref m_FillRect, value)) { UpdateCa |
| | 27 | |
|
| | 28 | | [SerializeField] |
| | 29 | | private RectTransform m_LowHandleRect; |
| | 30 | |
|
| 0 | 31 | | public RectTransform LowHandleRect { get { return m_LowHandleRect; } set { if (SetClass(ref m_LowHandleRect, val |
| | 32 | |
|
| | 33 | | [SerializeField] |
| | 34 | | private RectTransform m_HighHandleRect; |
| | 35 | |
|
| 0 | 36 | | public RectTransform HighHandleRect { get { return m_HighHandleRect; } set { if (SetClass(ref m_HighHandleRect, |
| | 37 | |
|
| | 38 | | [Space] |
| | 39 | |
|
| | 40 | | [SerializeField] |
| | 41 | | private float m_MinValue = 0; |
| | 42 | |
|
| 207 | 43 | | public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetLow(m_LowVal |
| | 44 | |
|
| | 45 | |
|
| | 46 | | [SerializeField] |
| 54 | 47 | | private float m_MaxValue = 1; |
| | 48 | |
|
| 207 | 49 | | public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetLow(m_LowVal |
| | 50 | |
|
| | 51 | | [SerializeField] |
| | 52 | | private bool m_WholeNumbers = false; |
| | 53 | |
|
| 633 | 54 | | public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetL |
| | 55 | |
|
| | 56 | | [SerializeField] |
| | 57 | | private float m_LowValue; |
| | 58 | | public virtual float LowValue |
| | 59 | | { |
| | 60 | | get |
| | 61 | | { |
| 105 | 62 | | if (WholeNumbers) |
| | 63 | | { |
| 105 | 64 | | return Mathf.Round(m_LowValue); |
| | 65 | | } |
| | 66 | |
|
| 0 | 67 | | return m_LowValue; |
| | 68 | | } |
| | 69 | | set |
| | 70 | | { |
| 105 | 71 | | SetLow(value); |
| 105 | 72 | | } |
| | 73 | | } |
| | 74 | |
|
| | 75 | | public float NormalizedLowValue |
| | 76 | | { |
| | 77 | | get |
| | 78 | | { |
| 0 | 79 | | if (Mathf.Approximately(MinValue, MaxValue)) |
| | 80 | | { |
| 0 | 81 | | return 0; |
| | 82 | | } |
| 0 | 83 | | return Mathf.InverseLerp(MinValue, MaxValue, LowValue); |
| | 84 | | } |
| | 85 | | set |
| | 86 | | { |
| 0 | 87 | | this.LowValue = Mathf.Lerp(MinValue, MaxValue, value); |
| 0 | 88 | | } |
| | 89 | | } |
| | 90 | |
|
| | 91 | |
|
| | 92 | | [SerializeField] |
| | 93 | | private float m_HighValue; |
| | 94 | | public virtual float HighValue |
| | 95 | | { |
| | 96 | | get |
| | 97 | | { |
| 105 | 98 | | if (WholeNumbers) |
| | 99 | | { |
| 105 | 100 | | return Mathf.Round(m_HighValue); |
| | 101 | | } |
| | 102 | |
|
| 0 | 103 | | return m_HighValue; |
| | 104 | | } |
| | 105 | | set |
| | 106 | | { |
| 105 | 107 | | SetHigh(value); |
| 105 | 108 | | } |
| | 109 | | } |
| | 110 | |
|
| | 111 | | public float NormalizedHighValue |
| | 112 | | { |
| | 113 | | get |
| | 114 | | { |
| 0 | 115 | | if (Mathf.Approximately(MinValue, MaxValue)) |
| | 116 | | { |
| 0 | 117 | | return 0; |
| | 118 | | } |
| 0 | 119 | | return Mathf.InverseLerp(MinValue, MaxValue, HighValue); |
| | 120 | | } |
| | 121 | | set |
| | 122 | | { |
| 0 | 123 | | this.HighValue = Mathf.Lerp(MinValue, MaxValue, value); |
| 0 | 124 | | } |
| | 125 | | } |
| | 126 | |
|
| | 127 | | /// <summary> |
| | 128 | | /// Set the value of the slider without invoking onValueChanged callback. |
| | 129 | | /// </summary> |
| | 130 | | /// <param name="input">The new value for the slider.</param> |
| | 131 | | public virtual void SetValueWithoutNotify(float low, float high) |
| | 132 | | { |
| 0 | 133 | | SetLow(low, false); |
| 0 | 134 | | SetHigh(high, false); |
| 0 | 135 | | } |
| | 136 | |
|
| | 137 | | [Space] |
| | 138 | |
|
| | 139 | | [SerializeField] |
| 54 | 140 | | private RangeSliderEvent m_OnValueChanged = new RangeSliderEvent(); |
| | 141 | |
|
| 155 | 142 | | public RangeSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } } |
| | 143 | |
|
| | 144 | | // Private fields |
| | 145 | |
|
| | 146 | | /// <summary> |
| | 147 | | /// An Enum that says in what state we and interacting with the slider |
| | 148 | | /// </summary> |
| | 149 | | private enum InteractionState |
| | 150 | | { |
| | 151 | | Low, |
| | 152 | | High, |
| | 153 | | Bar, |
| | 154 | | None |
| | 155 | | } |
| | 156 | |
|
| 54 | 157 | | private InteractionState interactionState = InteractionState.None; |
| | 158 | |
|
| | 159 | | private Image m_FillImage; |
| | 160 | | private Transform m_FillTransform; |
| | 161 | | private RectTransform m_FillContainerRect; |
| | 162 | | private Transform m_HighHandleTransform; |
| | 163 | | private RectTransform m_HighHandleContainerRect; |
| | 164 | | private Transform m_LowHandleTransform; |
| | 165 | | private RectTransform m_LowHandleContainerRect; |
| | 166 | |
|
| | 167 | | // The offset from handle position to mouse down position |
| 54 | 168 | | private Vector2 m_LowOffset = Vector2.zero; |
| | 169 | | // The offset from handle position to mouse down position |
| 54 | 170 | | private Vector2 m_HighOffset = Vector2.zero; |
| | 171 | |
|
| | 172 | | private DrivenRectTransformTracker m_Tracker; |
| | 173 | |
|
| | 174 | | // This "delayed" mechanism is required for case 1037681. |
| | 175 | | private bool m_DelayedUpdateVisuals = false; |
| | 176 | |
|
| | 177 | | // Size of each step. |
| 0 | 178 | | float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } } |
| | 179 | |
|
| 54 | 180 | | protected RangeSlider() |
| 54 | 181 | | { } |
| | 182 | |
|
| | 183 | | #if UNITY_EDITOR |
| | 184 | | protected override void OnValidate() |
| | 185 | | { |
| 3 | 186 | | base.OnValidate(); |
| | 187 | |
|
| 3 | 188 | | if (WholeNumbers) |
| | 189 | | { |
| 3 | 190 | | m_MinValue = Mathf.Round(m_MinValue); |
| 3 | 191 | | m_MaxValue = Mathf.Round(m_MaxValue); |
| | 192 | | } |
| | 193 | |
|
| 3 | 194 | | if (IsActive()) |
| | 195 | | { |
| 0 | 196 | | UpdateCachedReferences(); |
| 0 | 197 | | SetLow(m_LowValue, false); |
| 0 | 198 | | SetHigh(m_HighValue, false); |
| | 199 | | //Update rects since other things might affect them even if value didn't change |
| 0 | 200 | | m_DelayedUpdateVisuals = true; |
| | 201 | | } |
| | 202 | |
|
| 3 | 203 | | if (!UnityEditor.PrefabUtility.IsPartOfPrefabAsset(this) && !Application.isPlaying) |
| | 204 | | { |
| 0 | 205 | | CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this); |
| | 206 | | } |
| 3 | 207 | | } |
| | 208 | | #endif |
| | 209 | |
|
| | 210 | | public virtual void Rebuild(CanvasUpdate executing) |
| | 211 | | { |
| | 212 | | #if UNITY_EDITOR |
| 0 | 213 | | if (executing == CanvasUpdate.Prelayout) |
| | 214 | | { |
| 0 | 215 | | OnValueChanged.Invoke(LowValue, HighValue); |
| | 216 | | } |
| | 217 | | #endif |
| 0 | 218 | | } |
| | 219 | |
|
| | 220 | | /// <summary> |
| | 221 | | /// See ICanvasElement.LayoutComplete |
| | 222 | | /// </summary> |
| | 223 | | public virtual void LayoutComplete() |
| 0 | 224 | | { } |
| | 225 | |
|
| | 226 | | /// <summary> |
| | 227 | | /// See ICanvasElement.GraphicUpdateComplete |
| | 228 | | /// </summary> |
| | 229 | | public virtual void GraphicUpdateComplete() |
| 0 | 230 | | { } |
| | 231 | |
|
| | 232 | | public static bool SetClass<T>(ref T currentValue, T newValue) where T : class |
| | 233 | | { |
| 0 | 234 | | if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue))) |
| 0 | 235 | | return false; |
| | 236 | |
|
| 0 | 237 | | currentValue = newValue; |
| 0 | 238 | | return true; |
| | 239 | | } |
| | 240 | |
|
| | 241 | | public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct |
| | 242 | | { |
| 207 | 243 | | if (currentValue.Equals(newValue)) |
| 207 | 244 | | return false; |
| | 245 | |
|
| 0 | 246 | | currentValue = newValue; |
| 0 | 247 | | return true; |
| | 248 | | } |
| | 249 | |
|
| | 250 | | protected override void OnEnable() |
| | 251 | | { |
| 0 | 252 | | base.OnEnable(); |
| 0 | 253 | | UpdateCachedReferences(); |
| 0 | 254 | | SetLow(LowValue, false); |
| 0 | 255 | | SetHigh(HighValue, false); |
| | 256 | | // Update rects since they need to be initialized correctly. |
| 0 | 257 | | UpdateVisuals(); |
| 0 | 258 | | } |
| | 259 | |
|
| | 260 | | protected override void OnDisable() |
| | 261 | | { |
| 0 | 262 | | m_Tracker.Clear(); |
| 0 | 263 | | base.OnDisable(); |
| 0 | 264 | | } |
| | 265 | |
|
| | 266 | | /// <summary> |
| | 267 | | /// Update the rect based on the delayed update visuals. |
| | 268 | | /// Got around issue of calling sendMessage from onValidate. |
| | 269 | | /// </summary> |
| | 270 | | protected virtual void Update() |
| | 271 | | { |
| 0 | 272 | | if (m_DelayedUpdateVisuals) |
| | 273 | | { |
| 0 | 274 | | m_DelayedUpdateVisuals = false; |
| 0 | 275 | | UpdateVisuals(); |
| | 276 | | } |
| 0 | 277 | | } |
| | 278 | |
|
| | 279 | | protected override void OnDidApplyAnimationProperties() |
| | 280 | | { |
| 0 | 281 | | base.OnDidApplyAnimationProperties(); |
| 0 | 282 | | } |
| | 283 | |
|
| | 284 | | void UpdateCachedReferences() |
| | 285 | | { |
| 0 | 286 | | if (m_FillRect && m_FillRect != (RectTransform)transform) |
| | 287 | | { |
| 0 | 288 | | m_FillTransform = m_FillRect.transform; |
| 0 | 289 | | m_FillImage = m_FillRect.GetComponent<Image>(); |
| 0 | 290 | | if (m_FillTransform.parent != null) |
| 0 | 291 | | m_FillContainerRect = m_FillTransform.parent.GetComponent<RectTransform>(); |
| | 292 | | } |
| | 293 | | else |
| | 294 | | { |
| 0 | 295 | | m_FillRect = null; |
| 0 | 296 | | m_FillContainerRect = null; |
| 0 | 297 | | m_FillImage = null; |
| | 298 | | } |
| | 299 | |
|
| 0 | 300 | | if (m_HighHandleRect && m_HighHandleRect != (RectTransform)transform) |
| | 301 | | { |
| 0 | 302 | | m_HighHandleTransform = m_HighHandleRect.transform; |
| 0 | 303 | | if (m_HighHandleTransform.parent != null) |
| 0 | 304 | | m_HighHandleContainerRect = m_HighHandleTransform.parent.GetComponent<RectTransform>(); |
| | 305 | | } |
| | 306 | | else |
| | 307 | | { |
| 0 | 308 | | m_HighHandleRect = null; |
| 0 | 309 | | m_HighHandleContainerRect = null; |
| | 310 | | } |
| | 311 | |
|
| 0 | 312 | | if (m_LowHandleRect && m_LowHandleRect != (RectTransform)transform) |
| | 313 | | { |
| 0 | 314 | | m_LowHandleTransform = m_LowHandleRect.transform; |
| 0 | 315 | | if (m_LowHandleTransform.parent != null) |
| | 316 | | { |
| 0 | 317 | | m_LowHandleContainerRect = m_LowHandleTransform.parent.GetComponent<RectTransform>(); |
| | 318 | | } |
| | 319 | | } |
| | 320 | | else |
| | 321 | | { |
| 0 | 322 | | m_LowHandleRect = null; |
| 0 | 323 | | m_LowHandleContainerRect = null; |
| | 324 | | } |
| 0 | 325 | | } |
| | 326 | |
|
| | 327 | | void SetLow(float input) |
| | 328 | | { |
| 105 | 329 | | SetLow(input, true); |
| 105 | 330 | | } |
| | 331 | |
|
| | 332 | | protected virtual void SetLow(float input, bool sendCallback) |
| | 333 | | { |
| | 334 | | // Clamp the input |
| 105 | 335 | | float newValue = Mathf.Clamp(input, MinValue, HighValue); //clamp between min and High |
| 105 | 336 | | if (WholeNumbers) |
| | 337 | | { |
| 105 | 338 | | newValue = Mathf.Round(newValue); |
| | 339 | | } |
| | 340 | |
|
| | 341 | | // If the stepped value doesn't match the last one, it's time to update |
| 105 | 342 | | if (m_LowValue == newValue) |
| 105 | 343 | | return; |
| | 344 | |
|
| 0 | 345 | | m_LowValue = newValue; |
| 0 | 346 | | UpdateVisuals(); |
| 0 | 347 | | if (sendCallback) |
| | 348 | | { |
| 0 | 349 | | UISystemProfilerApi.AddMarker("RangeSlider.lowValue", this); |
| 0 | 350 | | m_OnValueChanged.Invoke(newValue, HighValue); |
| | 351 | | } |
| 0 | 352 | | } |
| | 353 | |
|
| | 354 | | void SetHigh(float input) |
| | 355 | | { |
| 105 | 356 | | SetHigh(input, true); |
| 105 | 357 | | } |
| | 358 | |
|
| | 359 | | protected virtual void SetHigh(float input, bool sendCallback) |
| | 360 | | { |
| | 361 | | // Clamp the input |
| 105 | 362 | | float newValue = Mathf.Clamp(input, LowValue, MaxValue); //clamp between min and High |
| 105 | 363 | | if (WholeNumbers) |
| | 364 | | { |
| 105 | 365 | | newValue = Mathf.Round(newValue); |
| | 366 | | } |
| | 367 | |
|
| | 368 | | // If the stepped value doesn't match the last one, it's time to update |
| 105 | 369 | | if (m_HighValue == newValue) |
| 105 | 370 | | return; |
| | 371 | |
|
| 0 | 372 | | m_HighValue = newValue; |
| 0 | 373 | | UpdateVisuals(); |
| 0 | 374 | | if (sendCallback) |
| | 375 | | { |
| 0 | 376 | | UISystemProfilerApi.AddMarker("RangeSlider.highValue", this); |
| 0 | 377 | | m_OnValueChanged.Invoke(LowValue, newValue); |
| | 378 | | } |
| 0 | 379 | | } |
| | 380 | |
|
| | 381 | |
|
| | 382 | | protected override void OnRectTransformDimensionsChange() |
| | 383 | | { |
| 277 | 384 | | base.OnRectTransformDimensionsChange(); |
| | 385 | |
|
| | 386 | | //This can be invoked before OnEnabled is called. So we shouldn't be accessing other objects, before OnEnabl |
| 277 | 387 | | if (!IsActive()) |
| 277 | 388 | | return; |
| | 389 | |
|
| 0 | 390 | | UpdateVisuals(); |
| 0 | 391 | | } |
| | 392 | |
|
| | 393 | |
|
| | 394 | | // Force-update the slider. Useful if you've changed the properties and want it to update visually. |
| | 395 | | private void UpdateVisuals() |
| | 396 | | { |
| | 397 | | #if UNITY_EDITOR |
| 0 | 398 | | if (!Application.isPlaying) |
| 0 | 399 | | UpdateCachedReferences(); |
| | 400 | | #endif |
| | 401 | |
|
| 0 | 402 | | m_Tracker.Clear(); |
| | 403 | |
|
| 0 | 404 | | if (m_FillContainerRect != null) |
| | 405 | | { |
| 0 | 406 | | m_Tracker.Add(this, m_FillRect, DrivenTransformProperties.Anchors); |
| 0 | 407 | | Vector2 anchorMin = Vector2.zero; |
| 0 | 408 | | Vector2 anchorMax = Vector2.one; |
| | 409 | |
|
| | 410 | | //this is where some new magic must happen. Slider just uses a filled image |
| | 411 | | //and changes the % of fill. We must move the image anchors to be between the two handles. |
| 0 | 412 | | anchorMin[0] = NormalizedLowValue; |
| 0 | 413 | | anchorMax[0] = NormalizedHighValue; |
| | 414 | |
|
| 0 | 415 | | m_FillRect.anchorMin = anchorMin; |
| 0 | 416 | | m_FillRect.anchorMax = anchorMax; |
| | 417 | | } |
| | 418 | |
|
| 0 | 419 | | if (m_LowHandleContainerRect != null) |
| | 420 | | { |
| 0 | 421 | | m_Tracker.Add(this, m_LowHandleRect, DrivenTransformProperties.Anchors); |
| 0 | 422 | | Vector2 anchorMin = Vector2.zero; |
| 0 | 423 | | Vector2 anchorMax = Vector2.one; |
| 0 | 424 | | anchorMin[0] = anchorMax[0] = NormalizedLowValue; |
| 0 | 425 | | m_LowHandleRect.anchorMin = anchorMin; |
| 0 | 426 | | m_LowHandleRect.anchorMax = anchorMax; |
| | 427 | | } |
| | 428 | |
|
| 0 | 429 | | if (m_HighHandleContainerRect != null) |
| | 430 | | { |
| 0 | 431 | | m_Tracker.Add(this, m_HighHandleRect, DrivenTransformProperties.Anchors); |
| 0 | 432 | | Vector2 anchorMin = Vector2.zero; |
| 0 | 433 | | Vector2 anchorMax = Vector2.one; |
| 0 | 434 | | anchorMin[0] = anchorMax[0] = NormalizedHighValue; |
| 0 | 435 | | m_HighHandleRect.anchorMin = anchorMin; |
| 0 | 436 | | m_HighHandleRect.anchorMax = anchorMax; |
| | 437 | | } |
| 0 | 438 | | } |
| | 439 | |
|
| | 440 | | // Update the slider's position based on the mouse. |
| | 441 | | void UpdateDrag(PointerEventData eventData, Camera cam) |
| | 442 | | { |
| | 443 | | //this needs to differ from slider in that we have two handles, and need to move the right one. |
| | 444 | | //and if it was neither handle, we will have a seperate case where both handles move uniformly |
| | 445 | | //moving the entire range |
| | 446 | |
|
| | 447 | | //this is where we use our interationState |
| 0 | 448 | | switch (interactionState) |
| | 449 | | { |
| | 450 | | case InteractionState.Low: |
| 0 | 451 | | NormalizedLowValue = CalculateDrag(eventData, cam, m_LowHandleContainerRect, m_LowOffset); |
| 0 | 452 | | break; |
| | 453 | | case InteractionState.High: |
| 0 | 454 | | NormalizedHighValue = CalculateDrag(eventData, cam, m_HighHandleContainerRect, m_HighOffset); |
| 0 | 455 | | break; |
| | 456 | | case InteractionState.Bar: |
| | 457 | | //special case |
| 0 | 458 | | CalculateBarDrag(eventData, cam); |
| | 459 | | break; |
| | 460 | | case InteractionState.None: |
| | 461 | | break; |
| | 462 | | } |
| 0 | 463 | | } |
| | 464 | |
|
| | 465 | | private float CalculateDrag(PointerEventData eventData, Camera cam, RectTransform containerRect, Vector2 offset) |
| | 466 | | { |
| 0 | 467 | | RectTransform clickRect = containerRect ?? m_FillContainerRect; |
| 0 | 468 | | if (clickRect != null && clickRect.rect.size[0] > 0) |
| | 469 | | { |
| | 470 | | Vector2 localCursor; |
| 0 | 471 | | if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out loc |
| | 472 | | { |
| 0 | 473 | | return 0f; |
| | 474 | | } |
| 0 | 475 | | localCursor -= clickRect.rect.position; |
| | 476 | |
|
| 0 | 477 | | float val = Mathf.Clamp01((localCursor - offset)[0] / clickRect.rect.size[0]); |
| | 478 | |
|
| 0 | 479 | | return val; |
| | 480 | | } |
| 0 | 481 | | return 0; |
| | 482 | | } |
| | 483 | |
|
| | 484 | | private void CalculateBarDrag(PointerEventData eventData, Camera cam) |
| | 485 | | { |
| 0 | 486 | | RectTransform clickRect = m_FillContainerRect; |
| 0 | 487 | | if (clickRect != null && clickRect.rect.size[0] > 0) |
| | 488 | | { |
| | 489 | | Vector2 localCursor; |
| 0 | 490 | | if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out loc |
| | 491 | | { |
| 0 | 492 | | return; |
| | 493 | | } |
| 0 | 494 | | localCursor -= clickRect.rect.position; |
| | 495 | |
|
| | 496 | | //now we need to get the delta drag on the bar |
| | 497 | | //and move both the normalized low and high values by this amount |
| | 498 | | //but also check that neither is going beyond the bounds |
| 0 | 499 | | if (NormalizedLowValue >= 0 && NormalizedHighValue <= 1) |
| | 500 | | { |
| | 501 | | //find the mid point on the current bar |
| 0 | 502 | | float mid = (NormalizedHighValue + NormalizedLowValue)/2; |
| | 503 | | //find where the new mid point should be |
| 0 | 504 | | float val = Mathf.Clamp01((localCursor)[0] / clickRect.rect.size[0]); |
| | 505 | | //calculate the delta |
| 0 | 506 | | float delta = val - mid; |
| | 507 | | //check the clamp range |
| 0 | 508 | | if (NormalizedLowValue + delta < 0) |
| | 509 | | { |
| 0 | 510 | | delta = -NormalizedLowValue; |
| | 511 | | } |
| 0 | 512 | | else if (NormalizedHighValue + delta > 1) |
| | 513 | | { |
| 0 | 514 | | delta = 1 - NormalizedHighValue; |
| | 515 | | } |
| | 516 | |
|
| | 517 | | //adjust both ends |
| 0 | 518 | | NormalizedLowValue += delta; |
| 0 | 519 | | NormalizedHighValue += delta; |
| | 520 | | } |
| | 521 | | } |
| 0 | 522 | | } |
| | 523 | |
|
| | 524 | | private bool MayDrag(PointerEventData eventData) |
| | 525 | | { |
| 0 | 526 | | return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left; |
| | 527 | | } |
| | 528 | |
|
| | 529 | | public override void OnPointerDown(PointerEventData eventData) |
| | 530 | | { |
| 0 | 531 | | if (!MayDrag(eventData)) |
| 0 | 532 | | return; |
| | 533 | |
|
| | 534 | |
|
| | 535 | | //HANDLE DRAG EVENTS |
| 0 | 536 | | m_LowOffset = m_HighOffset = Vector2.zero; |
| | 537 | | Vector2 localMousePos; |
| 0 | 538 | | if (m_HighHandleRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HighHandleRect, eventDat |
| | 539 | | { |
| | 540 | | //dragging the high value handle |
| 0 | 541 | | if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HighHandleRect, eventData.position, eventD |
| | 542 | | { |
| 0 | 543 | | m_HighOffset = localMousePos; |
| | 544 | | } |
| 0 | 545 | | interactionState = InteractionState.High; |
| 0 | 546 | | if (transition == Transition.ColorTint) |
| | 547 | | { |
| 0 | 548 | | targetGraphic = m_HighHandleRect.GetComponent<Graphic>(); |
| | 549 | | } |
| | 550 | | } |
| 0 | 551 | | else if (m_LowHandleRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_LowHandleRect, event |
| | 552 | | { |
| | 553 | | //dragging the low value handle |
| 0 | 554 | | if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_LowHandleRect, eventData.position, eventDa |
| | 555 | | { |
| 0 | 556 | | m_LowOffset = localMousePos; |
| | 557 | | } |
| 0 | 558 | | interactionState = InteractionState.Low; |
| 0 | 559 | | if (transition == Transition.ColorTint) |
| | 560 | | { |
| 0 | 561 | | targetGraphic = m_LowHandleRect.GetComponent<Graphic>(); |
| | 562 | | } |
| | 563 | | } |
| | 564 | | else |
| | 565 | | { |
| | 566 | | //outside the handles, move the entire slider along |
| 0 | 567 | | UpdateDrag(eventData, eventData.pressEventCamera); |
| 0 | 568 | | interactionState = InteractionState.Bar; |
| 0 | 569 | | if (transition == Transition.ColorTint) |
| | 570 | | { |
| 0 | 571 | | targetGraphic = m_FillImage; |
| | 572 | | } |
| | 573 | | } |
| 0 | 574 | | base.OnPointerDown(eventData); |
| 0 | 575 | | } |
| | 576 | |
|
| | 577 | | public virtual void OnDrag(PointerEventData eventData) |
| | 578 | | { |
| 0 | 579 | | if (!MayDrag(eventData)) |
| | 580 | | { |
| 0 | 581 | | return; |
| | 582 | | } |
| 0 | 583 | | UpdateDrag(eventData, eventData.pressEventCamera); |
| 0 | 584 | | } |
| | 585 | |
|
| | 586 | | public override void OnPointerUp(PointerEventData eventData) |
| | 587 | | { |
| 0 | 588 | | base.OnPointerUp(eventData); |
| 0 | 589 | | interactionState = InteractionState.None; |
| 0 | 590 | | } |
| | 591 | |
|
| | 592 | | public override void OnMove(AxisEventData eventData) |
| | 593 | | { |
| | 594 | | //this requires further investigation |
| 0 | 595 | | } |
| | 596 | |
|
| | 597 | | public virtual void OnInitializePotentialDrag(PointerEventData eventData) |
| | 598 | | { |
| 0 | 599 | | eventData.useDragThreshold = false; |
| 0 | 600 | | } |
| | 601 | | } |
| | 602 | | } |