26 [RequireComponent(typeof(
Image))]
27 [AddComponentMenu(
"UI/Extensions/UI_Knob")]
28 public class UI_Knob : Selectable, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, IDragHandler, IInitializePotentialDragHandler
31 [Tooltip(
"Direction of rotation CW - clockwise, CCW - counterClockwise")]
35 [Tooltip(
"Max value of the knob, maximum RAW output value knob can reach, overrides snap step, IF set to 0 or higher than loops, max value will be set by loops")]
37 [Tooltip(
"How many rotations knob can do, if higher than max value, the latter will limit max value")]
39 [Tooltip(
"Clamp output value between 0 and 1, useful with loops > 1")]
41 [Tooltip(
"snap to position?")]
43 [Tooltip(
"Number of positions to snap")]
47 private float _currentLoops = 0;
48 private float _previousValue = 0;
49 private float _initAngle;
50 private float _currentAngle;
51 private Vector2 _currentVector;
52 private Quaternion _initRotation;
53 private bool _canDrag =
false;
54 private bool _screenSpaceOverlay;
58 _screenSpaceOverlay = GetComponentInParent<Canvas>().rootCanvas.renderMode == RenderMode.ScreenSpaceOverlay;
79 base.OnPointerDown(eventData);
81 _initRotation = transform.rotation;
82 if (_screenSpaceOverlay)
84 _currentVector = eventData.position - (Vector2)transform.position;
88 _currentVector = eventData.position - (Vector2)Camera.main.WorldToScreenPoint(transform.position);
90 _initAngle = Mathf.Atan2(_currentVector.y, _currentVector.x) * Mathf.Rad2Deg;
93 public void OnDrag(PointerEventData eventData)
101 if (_screenSpaceOverlay)
103 _currentVector = eventData.position - (Vector2)transform.position;
107 _currentVector = eventData.position - (Vector2)Camera.main.WorldToScreenPoint(transform.position);
109 _currentAngle = Mathf.Atan2(_currentVector.y, _currentVector.x) * Mathf.Rad2Deg;
111 Quaternion addRotation = Quaternion.AngleAxis(_currentAngle - _initAngle, this.transform.forward);
112 addRotation.eulerAngles =
new Vector3(0, 0, addRotation.eulerAngles.z);
114 Quaternion finalRotation = _initRotation * addRotation;
118 knobValue = 1 - (finalRotation.eulerAngles.z / 360f);
123 finalRotation.eulerAngles =
new Vector3(0, 0, 360 - 360 *
knobValue);
128 knobValue = (finalRotation.eulerAngles.z / 360f);
133 finalRotation.eulerAngles =
new Vector3(0, 0, 360 *
knobValue);
138 if (Mathf.Abs(
knobValue - _previousValue) > 0.5f)
140 if (knobValue < 0.5f && loops > 1 && _currentLoops <
loops - 1)
144 else if (
knobValue > 0.5f && _currentLoops >= 1)
150 if (
knobValue > 0.5f && _currentLoops == 0)
153 transform.localEulerAngles = Vector3.zero;
160 transform.localEulerAngles = Vector3.zero;
174 transform.localEulerAngles =
new Vector3(0, 0, maxAngle);
180 transform.rotation = finalRotation;
185 private void SnapToPosition(ref
float knobValue)
188 float newValue = Mathf.Round(
knobValue / snapStep) * snapStep;
191 private void InvokeEvents(
float value)
200 eventData.useDragThreshold =
false;
204 [System.Serializable]
System.Drawing.Image Image
override void OnPointerEnter(PointerEventData eventData)
void OnDrag(PointerEventData eventData)
virtual void OnInitializePotentialDrag(PointerEventData eventData)
override void OnPointerExit(PointerEventData eventData)
override void OnPointerDown(PointerEventData eventData)
KnobFloatValueEvent OnValueChanged
override void OnPointerUp(PointerEventData eventData)
Credit Erdener Gonenc - @PixelEnvision.