Last active
July 3, 2022 17:05
-
-
Save OwenMagelssen/b3390a3da0446480fe9989496d54ca25 to your computer and use it in GitHub Desktop.
Provides missing functionality from Unity's new input system for MonoBehaviour.OnMouseDown/Drag/Enter/Exit/Over/Up/UpButton events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.InputSystem; | |
using UnityEngine.Events; | |
public class CursorRaycaster : MonoBehaviour | |
{ | |
public UnityEvent onClickNothing; | |
private const float DragThreshold = 1.0f; | |
private Ray ray; | |
private RaycastHit hit; | |
private Camera cam; | |
private GameObject previousHitObject; | |
private GameObject clickedObject; | |
private float dragDistance; | |
private bool dragging; | |
private const string MouseDown = "OnMouseDown"; | |
private const string MouseDrag = "OnMouseDrag"; | |
private const string MouseEnter = "OnMouseEnter"; | |
private const string MouseExit = "OnMouseExit"; | |
private const string MouseOver = "OnMouseOver"; | |
private const string MouseUp = "OnMouseUp"; | |
private const string MouseUpAsButton = "OnMouseUpAsButton"; | |
private bool clicked; | |
private bool released; | |
private bool down; | |
private Vector2 delta; | |
private Vector2 screenspaceRayOrigin; | |
public BindInputActions(InputAction clickAction, InputAction moveDeltaAction) | |
{ | |
clickAction.performed += Click; | |
clickAction.canceled += Release; | |
move = moveDeltaAction; | |
moveDeltaAction.performed += Move; | |
} | |
private void Click(InputAction.CallbackContext context) | |
{ | |
clicked = true; | |
down = true; | |
} | |
private void Release(InputAction.CallbackContext context) | |
{ | |
released = true; | |
down = false; | |
} | |
private void Move(InputAction.CallbackContext context) => delta += context.ReadValue<Vector2>(); | |
private void UpdateCursorPosition() => screenspaceRayOrigin = Mouse.current.position.ReadValue(); | |
private void Awake() => cam = Camera.main; | |
private void ConsumeInputs() | |
{ | |
clicked = false; | |
released = false; | |
delta = Vector2.zero; | |
} | |
private void OnDownNoHit() | |
{ | |
Debug.Log("Clicked Nothing"); | |
onClickNothing?.Invoke(); | |
} | |
private void OnDown(GameObject go) => previousHitObject.SendMessage(MouseDown, SendMessageOptions.DontRequireReceiver); | |
private void OnDrag() | |
{ | |
if (dragging) | |
{ | |
clickedObject.SendMessage(MouseDrag, SendMessageOptions.DontRequireReceiver); | |
return; | |
} | |
dragDistance += delta.sqrMagnitude; | |
dragging = dragDistance > DragThreshold; | |
} | |
private void OnEnter(GameObject go) | |
{ | |
go.SendMessage(MouseEnter, SendMessageOptions.DontRequireReceiver); | |
previousHitObject = go; | |
} | |
private void OnExit() | |
{ | |
previousHitObject.SendMessage(MouseExit, SendMessageOptions.DontRequireReceiver); | |
previousHitObject = null; | |
} | |
private void OnOver() => previousHitObject.SendMessage(MouseOver, SendMessageOptions.DontRequireReceiver); | |
private void OnUp() => previousHitObject.SendMessage(MouseUp, SendMessageOptions.DontRequireReceiver); | |
private void OnUpButton() => previousHitObject.SendMessage(MouseUpAsButton, SendMessageOptions.DontRequireReceiver); | |
public void FixedUpdate() | |
{ | |
UpdateCursorPosition(); | |
if (down && clickedObject) | |
OnDrag(); | |
ray = cam.ScreenPointToRay(screenspaceRayOrigin); | |
if (Physics.Raycast(ray, out hit, cam.farClipPlane)) | |
{ | |
var hitObject = hit.collider.gameObject; | |
if (clicked) | |
{ | |
OnDown(hitObject); | |
clickedObject = hitObject; | |
} | |
if (released) | |
{ | |
OnUp(); | |
if (clickedObject && ReferenceEquals(clickedObject, hitObject)) | |
OnUpButton(); | |
clickedObject = null; | |
dragging = false; | |
dragDistance = 0; | |
} | |
if (!previousHitObject) | |
{ | |
OnEnter(hitObject); | |
ConsumeInputs(); | |
return; | |
} | |
if (ReferenceEquals(previousHitObject, hitObject)) | |
{ | |
OnOver(); | |
ConsumeInputs(); | |
return; | |
} | |
OnExit(); | |
OnEnter(hitObject); | |
} | |
else if (previousHitObject) | |
{ | |
OnExit(); | |
} | |
if (clicked) | |
OnDownNoHit(); | |
ConsumeInputs(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment