/// --------------------------------------------- /// Ultimate Character Controller /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.UltimateCharacterController.Input.VirtualControls { using Opsive.Shared.Game; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; /// /// A virtual touchpad that will move the axis based on the position of the press relative to the starting press position. /// public class VirtualTouchpad : VirtualAxis, IDragHandler { [Tooltip("Should the input value be stopped if there is no movement on the touch pad?")] [SerializeField] protected bool m_RequireActiveDrag; [Tooltip("The value to dampen the drag value by when no longer dragging. The higher the value the quicker the drag value will decrease.")] [SerializeField] protected float m_ActiveDragDamping = 1f; private RectTransform m_RectTransform; private Vector2 m_LocalStartPosition; private Transform m_CanvasScalarTransform; private ScheduledEventBase m_ActiveDragScheduler; /// /// Initialize the default values. /// protected override void Awake() { base.Awake(); m_RectTransform = GetComponent(); m_CanvasScalarTransform = GetComponentInParent().transform; } /// /// Callback when a pointer has pressed on the button. /// /// The pointer data. public override void OnPointerDown(PointerEventData data) { base.OnPointerDown(data); RectTransformUtility.ScreenPointToLocalPointInRectangle(m_RectTransform, data.pressPosition, null, out m_LocalStartPosition); } /// /// Callback when a pointer has dragged the button. /// /// The pointer data. public void OnDrag(PointerEventData data) { if (RectTransformUtility.RectangleContainsScreenPoint(m_RectTransform, data.position, null)) { var canvasScale = m_CanvasScalarTransform == null ? Vector3.one : m_CanvasScalarTransform.localScale; m_DeltaPosition.x += data.delta.x / canvasScale.x; m_DeltaPosition.y += data.delta.y / canvasScale.y; Scheduler.Cancel(m_ActiveDragScheduler); if (m_RequireActiveDrag) { m_ActiveDragScheduler = Scheduler.Schedule(Time.fixedDeltaTime, DampenDeltaPosition); } } } /// /// Clears the delta drag position. /// private void DampenDeltaPosition() { m_DeltaPosition /= (1 + m_ActiveDragDamping); if (m_DeltaPosition.sqrMagnitude > 0.1f) { m_ActiveDragScheduler = Scheduler.Schedule(Time.fixedDeltaTime, DampenDeltaPosition); } } /// /// Returns the value of the axis. /// /// The name of the axis. /// The value of the axis. public override float GetAxis(string name) { if (!m_Pressed) { return 0; } if (name == m_HorizontalInputName) { return m_DeltaPosition.x / (m_RectTransform.sizeDelta.x - m_LocalStartPosition.x); } return m_DeltaPosition.y / (m_RectTransform.sizeDelta.y - m_LocalStartPosition.y); } } }