summaryrefslogtreecommitdiff
path: root/Runtime/Export/SliderHandler.cs
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Export/SliderHandler.cs
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Export/SliderHandler.cs')
-rw-r--r--Runtime/Export/SliderHandler.cs330
1 files changed, 330 insertions, 0 deletions
diff --git a/Runtime/Export/SliderHandler.cs b/Runtime/Export/SliderHandler.cs
new file mode 100644
index 0000000..057ef70
--- /dev/null
+++ b/Runtime/Export/SliderHandler.cs
@@ -0,0 +1,330 @@
+using System;
+
+namespace UnityEngine
+{
+ // State for when we're dragging a slider.
+ internal class SliderState
+ {
+ public float dragStartPos;
+ public float dragStartValue;
+ public bool isDragging;
+ }
+
+ // TODO: Make the thumb positioning / sizing be right
+ internal struct SliderHandler
+ {
+ readonly Rect position;
+ readonly float currentValue;
+ readonly float size;
+ readonly float start;
+ readonly float end;
+ readonly GUIStyle slider;
+ readonly GUIStyle thumb;
+ readonly bool horiz;
+ readonly int id;
+
+ public SliderHandler(Rect position, float currentValue, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
+ {
+ this.position = position;
+ this.currentValue = currentValue;
+ this.size = size;
+ this.start = start;
+ this.end = end;
+ this.slider = slider;
+ this.thumb = thumb;
+ this.horiz = horiz;
+ this.id = id;
+ }
+
+ public float Handle()
+ {
+ if (slider == null || thumb == null)
+ return currentValue;
+
+ switch (CurrentEventType())
+ {
+ case EventType.MouseDown:
+ return OnMouseDown();
+
+ case EventType.MouseDrag:
+ return OnMouseDrag();
+
+ case EventType.MouseUp:
+ return OnMouseUp();
+
+ case EventType.Repaint:
+ return OnRepaint();
+ }
+ return currentValue;
+ }
+
+ private float OnMouseDown()
+ {
+ // if the click is outside this control, just bail out...
+ if (!position.Contains(CurrentEvent().mousePosition) || IsEmptySlider())
+ return currentValue;
+
+ GUI.scrollTroughSide = 0;
+ GUIUtility.hotControl = id;
+ CurrentEvent().Use();
+
+ if (ThumbSelectionRect().Contains(CurrentEvent().mousePosition))
+ {
+ // We have a mousedown on the thumb
+ // Record where we're draging from, so the user can get back.
+ StartDraggingWithValue(ClampedCurrentValue());
+ return currentValue;
+ }
+
+ GUI.changed = true;
+
+ // We're outside the thumb, but inside the trough.
+ // If we have a scrollSize, we do pgup/pgdn style movements
+ // if not, we just snap to the current position and begin tracking
+ if (SupportsPageMovements())
+ {
+ SliderState().isDragging = false;
+ GUI.nextScrollStepTime = SystemClock.now.AddMilliseconds(ScrollWaitDefinitions.firstWait);
+ GUI.scrollTroughSide = CurrentScrollTroughSide();
+ return PageMovementValue();
+ }
+
+ float newValue = ValueForCurrentMousePosition();
+ StartDraggingWithValue(newValue);
+ return Clamp(newValue);
+ }
+
+ private float OnMouseDrag()
+ {
+ if (GUIUtility.hotControl != id)
+ return currentValue;
+
+ var sliderState = SliderState();
+ if (!sliderState.isDragging)
+ return currentValue;
+
+ GUI.changed = true;
+ CurrentEvent().Use();
+
+ // Recalculate the value from the mouse position. this has the side effect that values are relative to the
+ // click point - no matter where inside the trough the original value was. Also means user can get back original value
+ // if he drags back to start position.
+ float deltaPos = MousePosition() - sliderState.dragStartPos;
+ var newValue = sliderState.dragStartValue + deltaPos / ValuesPerPixel();
+ return Clamp(newValue);
+ }
+
+ private float OnMouseUp()
+ {
+ if (GUIUtility.hotControl == id)
+ {
+ CurrentEvent().Use();
+ GUIUtility.hotControl = 0;
+ }
+ return currentValue;
+ }
+
+ private float OnRepaint()
+ {
+ slider.Draw(position, GUIContent.none, id);
+ thumb.Draw(ThumbRect(), GUIContent.none, id);
+
+ if (GUIUtility.hotControl != id || !position.Contains(CurrentEvent().mousePosition) || IsEmptySlider())
+ return currentValue;
+
+ if (ThumbRect().Contains(CurrentEvent().mousePosition))
+ {
+ if (GUI.scrollTroughSide != 0) // if was scrolling with "trough" and the thumb reached mouse - sliding action over
+ {
+ GUIUtility.hotControl = 0;
+ }
+
+ return currentValue;
+ }
+
+ GUI.InternalRepaintEditorWindow();
+
+ if (SystemClock.now < GUI.nextScrollStepTime)
+ return currentValue;
+
+ if (CurrentScrollTroughSide() != GUI.scrollTroughSide)
+ return currentValue;
+
+ GUI.nextScrollStepTime = SystemClock.now.AddMilliseconds(ScrollWaitDefinitions.regularWait);
+
+ if (SupportsPageMovements())
+ {
+ SliderState().isDragging = false;
+ GUI.changed = true;
+ return PageMovementValue();
+ }
+ return ClampedCurrentValue();
+ }
+
+ private EventType CurrentEventType()
+ {
+ return CurrentEvent().GetTypeForControl(id);
+ }
+
+ private int CurrentScrollTroughSide()
+ {
+ float mousePos = horiz ? CurrentEvent().mousePosition.x : CurrentEvent().mousePosition.y;
+ float thumbPos = horiz ? ThumbRect().x : ThumbRect().y;
+
+ return mousePos > thumbPos ? 1 : -1;
+ }
+
+ private bool IsEmptySlider()
+ {
+ return start == end;
+ }
+
+ private bool SupportsPageMovements()
+ {
+ return size != 0 && GUI.usePageScrollbars;
+ }
+
+ private float PageMovementValue()
+ {
+ var newValue = currentValue;
+ var sign = start > end ? -1 : 1;
+ if (MousePosition() > PageUpMovementBound())
+ newValue += size * sign * .9f;
+ else
+ newValue -= size * sign * .9f;
+ return Clamp(newValue);
+ }
+
+ private float PageUpMovementBound()
+ {
+ if (horiz)
+ return ThumbRect().xMax - position.x;
+ return ThumbRect().yMax - position.y;
+ }
+
+ private Event CurrentEvent()
+ {
+ return Event.current;
+ }
+
+ private float ValueForCurrentMousePosition()
+ {
+ if (horiz)
+ return (MousePosition() - ThumbRect().width * .5f) / ValuesPerPixel() + start - size * .5f;
+ return (MousePosition() - ThumbRect().height * .5f) / ValuesPerPixel() + start - size * .5f;
+ }
+
+ private float Clamp(float value)
+ {
+ return Mathf.Clamp(value, MinValue(), MaxValue());
+ }
+
+ private Rect ThumbSelectionRect()
+ {
+ var selectionRect = ThumbRect();
+#if UNITY_IPHONE
+ int minSize = 12;
+ if (selectionRect.width < minSize)
+ {
+ selectionRect.x -= (minSize - selectionRect.width) / 2;
+ selectionRect.width = minSize;
+ }
+ if (selectionRect.height < minSize)
+ {
+ selectionRect.y -= (minSize - selectionRect.height) / 2;
+ selectionRect.height = minSize;
+ }
+
+#endif
+ return selectionRect;
+ }
+
+ private void StartDraggingWithValue(float dragStartValue)
+ {
+ var state = SliderState();
+ state.dragStartPos = MousePosition();
+ state.dragStartValue = dragStartValue;
+ state.isDragging = true;
+ }
+
+ private SliderState SliderState()
+ {
+ return (SliderState)GUIUtility.GetStateObject(typeof(SliderState), id);
+ }
+
+ private Rect ThumbRect()
+ {
+ return horiz ? HorizontalThumbRect() : VerticalThumbRect();
+ }
+
+ private Rect VerticalThumbRect()
+ {
+ var valuesPerPixel = ValuesPerPixel();
+ if (start < end)
+ return new Rect(
+ position.x + slider.padding.left,
+ (ClampedCurrentValue() - start) * valuesPerPixel + position.y + slider.padding.top,
+ position.width - slider.padding.horizontal,
+ size * valuesPerPixel + ThumbSize());
+
+ return new Rect(
+ position.x + slider.padding.left,
+ (ClampedCurrentValue() + size - start) * valuesPerPixel + position.y + slider.padding.top,
+ position.width - slider.padding.horizontal,
+ size * -valuesPerPixel + ThumbSize());
+ }
+
+ private Rect HorizontalThumbRect()
+ {
+ var valuesPerPixel = ValuesPerPixel();
+ if (start < end)
+ return new Rect(
+ (ClampedCurrentValue() - start) * valuesPerPixel + position.x + slider.padding.left,
+ position.y + slider.padding.top,
+ size * valuesPerPixel + ThumbSize(),
+ position.height - slider.padding.vertical);
+
+ return new Rect(
+ (ClampedCurrentValue() + size - start) * valuesPerPixel + position.x + slider.padding.left,
+ position.y,
+ size * -valuesPerPixel + ThumbSize(),
+ position.height);
+ }
+
+ private float ClampedCurrentValue()
+ {
+ return Clamp(currentValue);
+ }
+
+ private float MousePosition()
+ {
+ if (horiz)
+ return CurrentEvent().mousePosition.x - position.x;
+ return CurrentEvent().mousePosition.y - position.y;
+ }
+
+ private float ValuesPerPixel()
+ {
+ if (horiz)
+ return (position.width - slider.padding.horizontal - ThumbSize()) / (end - start);
+ return (position.height - slider.padding.vertical - ThumbSize()) / (end - start);
+ }
+
+ private float ThumbSize()
+ {
+ if (horiz)
+ return thumb.fixedWidth != 0 ? thumb.fixedWidth : thumb.padding.horizontal;
+ return thumb.fixedHeight != 0 ? thumb.fixedHeight : thumb.padding.vertical;
+ }
+
+ private float MaxValue()
+ {
+ return Mathf.Max(start, end) - size;
+ }
+
+ private float MinValue()
+ {
+ return Mathf.Min(start, end);
+ }
+ }
+}