EscapeShooter/My project/Assets/Project Files/Modules/Control/Scripts/Joystick/Joystick.cs

232 lines
7.3 KiB
C#
Raw Normal View History

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Watermelon
{
[RequireComponent(typeof(Animator))]
public class Joystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler, IControlBehavior
{
public static Joystick Instance { get; private set; }
[Header("Joystick")]
[SerializeField] protected Image backgroundImage;
[SerializeField] protected Image handleImage;
[Space]
[SerializeField] Color backgroundActiveColor = Color.white;
[SerializeField] Color backgroundDisableColor = Color.white;
[SerializeField] Color handleActiveColor = Color.white;
[SerializeField] Color handleDisableColor = Color.white;
[Space]
[SerializeField] float handleRange = 1;
[SerializeField] float deadZone = 0;
[Header("Tutorial")]
[SerializeField] bool useTutorial;
[SerializeField] GameObject pointerGameObject;
private RectTransform baseRectTransform;
private RectTransform backgroundRectTransform;
private RectTransform handleRectTransform;
private bool isActive;
public bool IsMovementInputNonZero => isActive;
private bool canDrag;
private Canvas canvas;
private Camera canvasCamera;
protected Vector2 input = Vector2.zero;
public Vector3 Input => input;
public Vector3 MovementInput => new Vector3(input.x, 0, input.y);
private Vector2 defaultAnchoredPosition;
public bool IsLookInputNonZero => false;
public Vector3 LookInput => Vector3.zero;
private Animator joystickAnimator;
private bool isTutorialDisplayed;
private bool hideVisualsActive;
// Events
public event SimpleCallback OnMovementInputActivated;
public void Init(Canvas canvas)
{
this.canvas = canvas;
Instance = this;
joystickAnimator = GetComponent<Animator>();
baseRectTransform = GetComponent<RectTransform>();
backgroundRectTransform = backgroundImage.rectTransform;
handleRectTransform = handleImage.rectTransform;
if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
canvasCamera = canvas.worldCamera;
Vector2 center = new Vector2(0.5f, 0.5f);
backgroundRectTransform.pivot = center;
handleRectTransform.anchorMin = center;
handleRectTransform.anchorMax = center;
handleRectTransform.pivot = center;
handleRectTransform.anchoredPosition = Vector2.zero;
isActive = false;
if(useTutorial)
{
joystickAnimator.enabled = true;
isTutorialDisplayed = true;
pointerGameObject.SetActive(true);
}
else
{
joystickAnimator.enabled = false;
isTutorialDisplayed = false;
pointerGameObject.SetActive(false);
}
backgroundImage.color = backgroundDisableColor.SetAlpha(hideVisualsActive ? 0f : backgroundDisableColor.a);
handleImage.color = handleDisableColor.SetAlpha(hideVisualsActive ? 0f : backgroundDisableColor.a);
defaultAnchoredPosition = backgroundRectTransform.anchoredPosition;
if (Control.InputType == InputType.UIJoystick)
{
Control.SetControl(this);
}
else
{
gameObject.SetActive(false);
}
}
public void OnPointerDown(PointerEventData eventData)
{
canDrag = !WorldSpaceRaycaster.Raycast(eventData);
if (!canDrag) return;
if (!isTutorialDisplayed)
{
isTutorialDisplayed = true;
joystickAnimator.enabled = false;
pointerGameObject.SetActive(false);
}
backgroundRectTransform.anchoredPosition = ScreenPointToAnchoredPosition(eventData.position);
backgroundImage.color = backgroundActiveColor.SetAlpha(hideVisualsActive ? 0f : backgroundDisableColor.a);
handleImage.color = handleActiveColor.SetAlpha(hideVisualsActive ? 0f : backgroundDisableColor.a);
isActive = true;
OnMovementInputActivated?.Invoke();
OnDrag(eventData);
}
public void OnDrag(PointerEventData eventData)
{
if (!isActive || !canDrag)
return;
Vector2 position = RectTransformUtility.WorldToScreenPoint(canvasCamera, backgroundRectTransform.position);
Vector2 radius = backgroundRectTransform.sizeDelta / 2;
input = (eventData.position - position) / (radius * canvas.scaleFactor);
HandleInput(input.magnitude, input.normalized, radius, canvasCamera);
handleRectTransform.anchoredPosition = input * radius * handleRange;
}
protected void HandleInput(float magnitude, Vector2 normalised, Vector2 radius, Camera cam)
{
if (magnitude > deadZone)
{
if (magnitude > 1)
input = normalised;
}
else
{
input = Vector2.zero;
}
}
public void OnPointerUp(PointerEventData eventData)
{
WorldSpaceRaycaster.OnPointerUp(eventData);
if (!isActive)
return;
isActive = false;
ResetControl();
}
public void ResetControl()
{
isActive = false;
backgroundImage.color = backgroundDisableColor.SetAlpha(hideVisualsActive ? 0f : backgroundDisableColor.a);
handleImage.color = handleDisableColor.SetAlpha(hideVisualsActive ? 0f : backgroundDisableColor.a);
backgroundRectTransform.anchoredPosition = defaultAnchoredPosition;
input = Vector2.zero;
handleRectTransform.anchoredPosition = Vector2.zero;
}
protected Vector2 ScreenPointToAnchoredPosition(Vector2 screenPosition)
{
Vector2 localPoint = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(baseRectTransform, screenPosition, canvasCamera, out localPoint))
{
Vector2 pivotOffset = baseRectTransform.pivot * baseRectTransform.sizeDelta;
return localPoint - (backgroundRectTransform.anchorMax * baseRectTransform.sizeDelta) + pivotOffset;
}
return Vector2.zero;
}
public void EnableMovementControl()
{
gameObject.SetActive(true);
}
public void DisableMovementControl()
{
gameObject.SetActive(false);
isActive = false;
ResetControl();
}
public void HideVisuals()
{
hideVisualsActive = true;
backgroundImage.color = backgroundImage.color.SetAlpha(0f);
handleImage.color = backgroundImage.color.SetAlpha(0f);
}
public void ShowVisuals()
{
hideVisualsActive = false;
backgroundImage.color = backgroundImage.color.SetAlpha(1f);
handleImage.color = backgroundImage.color.SetAlpha(1f);
}
public delegate void OnJoystickTouchedCallback();
}
}