|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.EventSystems;
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace MoreMountains.Tools
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Add this component to a UI rectangle and it'll act as a detection zone for a joystick.
|
|
|
|
|
/// Note that this component extends the MMTouchJoystick class so you don't need to add another joystick to it. It's both the detection zone and the stick itself.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[AddComponentMenu("More Mountains/Tools/Controls/MMTouchRepositionableJoystick")]
|
|
|
|
|
public class MMTouchRepositionableJoystick : MMTouchJoystick, IPointerDownHandler
|
|
|
|
|
{
|
|
|
|
|
[MMInspectorGroup("Repositionable Joystick", true, 22)]
|
|
|
|
|
/// the canvas group to use as the joystick's knob
|
|
|
|
|
[Tooltip("the canvas group to use as the joystick's knob")]
|
|
|
|
|
public CanvasGroup KnobCanvasGroup;
|
|
|
|
|
/// the canvas group to use as the joystick's background
|
|
|
|
|
[Tooltip("the canvas group to use as the joystick's background")]
|
|
|
|
|
public CanvasGroup BackgroundCanvasGroup;
|
|
|
|
|
/// if this is true, the joystick won't be able to travel beyond the bounds of the top level canvas
|
|
|
|
|
[Tooltip("if this is true, the joystick won't be able to travel beyond the bounds of the top level canvas")]
|
|
|
|
|
public bool ConstrainToInitialRectangle = true;
|
|
|
|
|
/// if this is true, the joystick will return back to its initial position when released
|
|
|
|
|
[Tooltip("if this is true, the joystick will return back to its initial position when released")]
|
|
|
|
|
public bool ResetPositionToInitialOnRelease = false;
|
|
|
|
|
|
|
|
|
|
protected Vector3 _initialPosition;
|
|
|
|
|
protected Vector3 _newPosition;
|
|
|
|
|
protected CanvasGroup _knobCanvasGroup;
|
|
|
|
|
protected RectTransform _rectTransform;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// On Start, we instantiate our joystick's image if there's one
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected override void Start()
|
|
|
|
|
{
|
|
|
|
|
base.Start();
|
|
|
|
|
|
|
|
|
|
// we store the detection zone's initial position
|
|
|
|
|
_rectTransform = GetComponent<RectTransform>();
|
|
|
|
|
_initialPosition = _rectTransform.position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// On init we set our knob transform
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
{
|
|
|
|
|
base.Initialize();
|
|
|
|
|
SetKnobTransform(KnobCanvasGroup.transform);
|
|
|
|
|
_canvasGroup = KnobCanvasGroup;
|
|
|
|
|
_initialOpacity = _canvasGroup.alpha;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// When the zone is pressed, we move our joystick accordingly
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Data.</param>
|
|
|
|
|
public override void OnPointerDown(PointerEventData data)
|
|
|
|
|
{
|
|
|
|
|
base.OnPointerDown(data);
|
|
|
|
|
|
|
|
|
|
// if we're in "screen space - camera" render mode
|
|
|
|
|
if (ParentCanvasRenderMode == RenderMode.ScreenSpaceCamera)
|
|
|
|
|
{
|
|
|
|
|
_newPosition = TargetCamera.ScreenToWorldPoint(data.position);
|
|
|
|
|
}
|
|
|
|
|
// otherwise
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_newPosition = data.position;
|
|
|
|
|
}
|
|
|
|
|
_newPosition.z = this.transform.position.z;
|
|
|
|
|
|
|
|
|
|
if (!WithinBounds())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we define a new neutral position
|
|
|
|
|
BackgroundCanvasGroup.transform.position = _newPosition;
|
|
|
|
|
SetNeutralPosition(_newPosition);
|
|
|
|
|
_knobTransform.position = _newPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns true if the joystick's new position is within the bounds of the top level canvas
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected virtual bool WithinBounds()
|
|
|
|
|
{
|
|
|
|
|
if (!ConstrainToInitialRectangle)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return RectTransformUtility.RectangleContainsScreenPoint(_rectTransform, _newPosition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// When the player lets go of the stick, we restore our stick's position if needed
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="eventData">Event data.</param>
|
|
|
|
|
public override void OnPointerUp(PointerEventData eventData)
|
|
|
|
|
{
|
|
|
|
|
base.OnPointerUp(eventData);
|
|
|
|
|
|
|
|
|
|
if (ResetPositionToInitialOnRelease)
|
|
|
|
|
{
|
|
|
|
|
BackgroundCanvasGroup.transform.position = _initialPosition;
|
|
|
|
|
_knobTransform.position = _initialPosition;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws gizmos if needed
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected override void OnDrawGizmos()
|
|
|
|
|
{
|
|
|
|
|
if (!DrawGizmos)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Handles.color = MMColors.Orange;
|
|
|
|
|
if (!Application.isPlaying)
|
|
|
|
|
{
|
|
|
|
|
if (KnobCanvasGroup != null)
|
|
|
|
|
{
|
|
|
|
|
Handles.DrawWireDisc(KnobCanvasGroup.transform.position, Vector3.forward, ComputedMaxRange);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Handles.DrawWireDisc(this.transform.position, Vector3.forward, ComputedMaxRange);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Handles.DrawWireDisc(_neutralPosition, Vector3.forward, ComputedMaxRange);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|