2026-05-06 15:07:56 +02:00

239 lines
8.3 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
/* REMOVE COMMENT TO MAKE FUNCTIONAL
using UnityStandardAssets.CrossPlatformInput;
*/
namespace DuloGames.UI
{
[AddComponentMenu("UI/Joystick", 36), RequireComponent(typeof(RectTransform))]
public class UIJoystick : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler, IPointerDownHandler, IPointerUpHandler
{
public enum AxisOption
{
// Options for which axes to use
Both, // Use both
OnlyHorizontal, // Only horizontal
OnlyVertical // Only vertical
}
[SerializeField, Tooltip("The child graphic that will be moved around.")]
private RectTransform m_Handle;
public RectTransform Handle
{
get { return this.m_Handle; }
set
{
this.m_Handle = value;
UpdateHandle();
}
}
[SerializeField, Tooltip("The handling area that the handle is allowed to be moved in.")]
private RectTransform m_HandlingArea;
public RectTransform HandlingArea
{
get { return this.m_HandlingArea; }
set { this.m_HandlingArea = value; }
}
[SerializeField, Tooltip("The child graphic that will be shown when the joystick is active.")]
private Image m_ActiveGraphic;
public Image ActiveGraphic
{
get { return this.m_ActiveGraphic; }
set { this.m_ActiveGraphic = value; }
}
[SerializeField] private Vector2 m_Axis;
/* REMOVE COMMENT TO MAKE FUNCTIONAL
[SerializeField] private AxisOption m_AxesToUse = AxisOption.Both; // The options for the axes that the still will use
*/
[SerializeField, Tooltip("How fast the joystick will go back to the center")]
private float m_Spring = 25f;
public float Spring
{
get { return this.m_Spring; }
set { this.m_Spring = value; }
}
[SerializeField, Tooltip("How close to the center that the axis will be output as 0")]
private float m_DeadZone = 0.1f;
public float DeadZone
{
get { return this.m_DeadZone; }
set { this.m_DeadZone = value; }
}
[Tooltip("Customize the output that is sent in OnValueChange")]
public AnimationCurve outputCurve = new AnimationCurve(new Keyframe(0, 0, 1, 1), new Keyframe(1, 1, 1, 1));
private bool m_IsDragging = false;
/* REMOVE COMMENT TO MAKE FUNCTIONAL
[SerializeField] private string m_HorizontalAxisName = "Horizontal"; // The name given to the horizontal axis for the cross platform input
[SerializeField] private string m_VerticalAxisName = "Vertical"; // The name given to the vertical axis for the cross platform input
private bool m_UseX; // Toggle for using the x axis
private bool m_UseY; // Toggle for using the Y axis
private CrossPlatformInputManager.VirtualAxis m_HorizontalVirtualAxis; // Reference to the joystick in the cross platform input
private CrossPlatformInputManager.VirtualAxis m_VerticalVirtualAxis; // Reference to the joystick in the cross platform input
*/
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
// Fix anchors
if (this.m_HandlingArea != null)
{
this.m_HandlingArea.anchorMin = new Vector2(0.5f, 0.5f);
this.m_HandlingArea.anchorMax = new Vector2(0.5f, 0.5f);
}
// Hide active
if (this.m_ActiveGraphic != null)
this.m_ActiveGraphic.canvasRenderer.SetAlpha(0f);
this.UpdateHandle();
}
#endif
protected override void OnEnable()
{
base.OnEnable();
this.CreateVirtualAxes();
if (this.m_HandlingArea == null)
this.m_HandlingArea = this.transform as RectTransform;
if (this.m_ActiveGraphic != null)
this.m_ActiveGraphic.canvasRenderer.SetAlpha(0f);
}
protected void CreateVirtualAxes()
{
/* REMOVE COMMENT TO MAKE FUNCTIONAL
// set axes to use
this.m_UseX = (this.m_AxesToUse == AxisOption.Both || this.m_AxesToUse == AxisOption.OnlyHorizontal);
this.m_UseY = (this.m_AxesToUse == AxisOption.Both || this.m_AxesToUse == AxisOption.OnlyVertical);
if (this.m_UseX)
{
this.m_HorizontalVirtualAxis = new CrossPlatformInputManager.VirtualAxis(this.m_HorizontalAxisName);
CrossPlatformInputManager.RegisterVirtualAxis(this.m_HorizontalVirtualAxis);
}
if (this.m_UseY)
{
this.m_VerticalVirtualAxis = new CrossPlatformInputManager.VirtualAxis(this.m_VerticalAxisName);
CrossPlatformInputManager.RegisterVirtualAxis(this.m_VerticalVirtualAxis);
}
*/
}
protected void LateUpdate()
{
if (this.isActiveAndEnabled && !this.m_IsDragging)
{
if (this.m_Axis != Vector2.zero)
{
Vector2 newAxis = this.m_Axis - (this.m_Axis * Time.unscaledDeltaTime * this.m_Spring);
if (newAxis.sqrMagnitude <= .0001f)
newAxis = Vector2.zero;
this.SetAxis(newAxis);
}
}
}
public Vector2 JoystickAxis
{
get
{
Vector2 outputPoint = this.m_Axis.magnitude > this.m_DeadZone ? this.m_Axis : Vector2.zero;
float magnitude = outputPoint.magnitude;
outputPoint *= outputCurve.Evaluate(magnitude);
return outputPoint;
}
set { this.SetAxis(value); }
}
public void SetAxis(Vector2 axis)
{
this.m_Axis = Vector2.ClampMagnitude(axis, 1);
Vector2 outputPoint = this.m_Axis.magnitude > this.m_DeadZone ? this.m_Axis : Vector2.zero;
float magnitude = outputPoint.magnitude;
outputPoint *= outputCurve.Evaluate(magnitude);
/* REMOVE COMMENT TO MAKE FUNCTIONAL
if (this.m_UseX) this.m_HorizontalVirtualAxis.Update(outputPoint.x);
if (this.m_UseY) this.m_VerticalVirtualAxis.Update(outputPoint.y);
*/
this.UpdateHandle();
}
public void OnBeginDrag(PointerEventData eventData)
{
if (!this.IsActive() || this.m_HandlingArea == null)
return;
Vector2 newAxis = this.m_HandlingArea.InverseTransformPoint(eventData.position);
newAxis.x /= this.m_HandlingArea.sizeDelta.x * 0.5f;
newAxis.y /= this.m_HandlingArea.sizeDelta.y * 0.5f;
this.SetAxis(newAxis);
this.m_IsDragging = true;
}
public void OnEndDrag(PointerEventData eventData)
{
this.m_IsDragging = false;
}
public void OnDrag(PointerEventData eventData)
{
if (this.m_HandlingArea == null)
return;
Vector2 axis = Vector2.zero;
RectTransformUtility.ScreenPointToLocalPointInRectangle(this.m_HandlingArea, eventData.position, eventData.pressEventCamera, out axis);
axis -= this.m_HandlingArea.rect.center;
axis.x /= this.m_HandlingArea.sizeDelta.x * 0.5f;
axis.y /= this.m_HandlingArea.sizeDelta.y * 0.5f;
this.SetAxis(axis);
}
private void UpdateHandle()
{
if (this.m_Handle && this.m_HandlingArea)
{
this.m_Handle.anchoredPosition = new Vector2(this.m_Axis.x * this.m_HandlingArea.sizeDelta.x * 0.5f, this.m_Axis.y * this.m_HandlingArea.sizeDelta.y * 0.5f);
}
}
public void OnPointerDown(PointerEventData eventData)
{
if (this.m_ActiveGraphic != null)
this.m_ActiveGraphic.CrossFadeAlpha(1f, 0.2f, false);
}
public void OnPointerUp(PointerEventData eventData)
{
if (this.m_ActiveGraphic != null)
this.m_ActiveGraphic.CrossFadeAlpha(0f, 0.2f, false);
}
}
}