/// Credit Chris Trueman
/// Sourced from - http://forum.unity3d.com/threads/use-reticle-like-mouse-for-worldspace-uis.295271/
namespace UnityEngine.EventSystems.Extensions
{
[RequireComponent(typeof(EventSystem))]
[AddComponentMenu("Event/Extensions/Aimer Input Module")]
public class AimerInputModule : PointerInputModule
{
///
/// The Input axis name used to activate the object under the reticle.
///
public string activateAxis = "Submit";
///
/// The aimer offset position. Aimer is center screen use this offset to change that.
///
public Vector2 aimerOffset = new Vector2(0, 0);
///
/// The object under aimer. A static access field that lets you know what is under the aimer.
/// This field can return null.
///
public static GameObject objectUnderAimer;
protected AimerInputModule() { }
public override void ActivateModule()
{
StandaloneInputModule StandAloneSystem = GetComponent();
if (StandAloneSystem != null && StandAloneSystem.enabled)
{
Debug.LogError("Aimer Input Module is incompatible with the StandAloneInputSystem, " +
"please remove it from the Event System in this scene or disable it when this module is in use");
}
}
public override void Process()
{
bool pressed = Input.GetButtonDown(activateAxis);
bool released = Input.GetButtonUp(activateAxis);
PointerEventData pointer = GetAimerPointerEventData();
ProcessInteraction(pointer, pressed, released);
if (!released)
ProcessMove(pointer);
else
RemovePointerData(pointer);
}
protected virtual PointerEventData GetAimerPointerEventData()
{
PointerEventData pointerData;
//Not certain on the use of this.
//I know that -1 is the mouse and anything positive would be a finger/touch, 0 being the first finger, 1 beign the second and so one till the system limit is reached.
//So that is the reason I choose -2.
GetPointerData(-2, out pointerData, true);
pointerData.Reset();
pointerData.position = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f) + aimerOffset;
eventSystem.RaycastAll(pointerData, m_RaycastResultCache);
var raycast = FindFirstRaycast(m_RaycastResultCache);
pointerData.pointerCurrentRaycast = raycast;
m_RaycastResultCache.Clear();
return pointerData;
}
private void ProcessInteraction(PointerEventData pointer, bool pressed, bool released)
{
var currentOverGo = pointer.pointerCurrentRaycast.gameObject;
objectUnderAimer = ExecuteEvents.GetEventHandler(currentOverGo);//we only want objects that we can submit on.
if (pressed)
{
pointer.eligibleForClick = true;
pointer.delta = Vector2.zero;
pointer.pressPosition = pointer.position;
pointer.pointerPressRaycast = pointer.pointerCurrentRaycast;
// search for the control that will receive the press
// if we can't find a press handler set the press
// handler to be what would receive a click.
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointer, ExecuteEvents.submitHandler);
// didnt find a press handler... search for a click handler
if (newPressed == null)
{
newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointer, ExecuteEvents.pointerDownHandler);
if (newPressed == null)
newPressed = ExecuteEvents.GetEventHandler(currentOverGo);
}
else
{
pointer.eligibleForClick = false;
}
if (newPressed != pointer.pointerPress)
{
pointer.pointerPress = newPressed;
pointer.rawPointerPress = currentOverGo;
pointer.clickCount = 0;
}
// Save the drag handler as well
pointer.pointerDrag = ExecuteEvents.GetEventHandler(currentOverGo);
if (pointer.pointerDrag != null)
ExecuteEvents.Execute(pointer.pointerDrag, pointer, ExecuteEvents.beginDragHandler);
}
if (released)
{
//Debug.Log("Executing pressup on: " + pointer.pointerPress);
ExecuteEvents.Execute(pointer.pointerPress, pointer, ExecuteEvents.pointerUpHandler);
//Debug.Log("KeyCode: " + pointer.eventData.keyCode);
// see if we mouse up on the same element that we clicked on...
var pointerUpHandler = ExecuteEvents.GetEventHandler(currentOverGo);
// PointerClick
if (pointer.pointerPress == pointerUpHandler && pointer.eligibleForClick)
{
float time = Time.unscaledTime;
if (time - pointer.clickTime < 0.3f)
++pointer.clickCount;
else
pointer.clickCount = 1;
pointer.clickTime = time;
ExecuteEvents.Execute(pointer.pointerPress, pointer, ExecuteEvents.pointerClickHandler);
}
else if (pointer.pointerDrag != null)
{
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointer, ExecuteEvents.dropHandler);
}
pointer.eligibleForClick = false;
pointer.pointerPress = null;
pointer.rawPointerPress = null;
if (pointer.pointerDrag != null)
ExecuteEvents.Execute(pointer.pointerDrag, pointer, ExecuteEvents.endDragHandler);
pointer.pointerDrag = null;
}
}
public override void DeactivateModule()
{
base.DeactivateModule();
ClearSelection();
}
}
}