You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			261 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			261 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
| 
								 
											1 year ago
										 
									 | 
							
								using System;
							 | 
						||
| 
								 | 
							
								using System.Collections;
							 | 
						||
| 
								 | 
							
								using System.Collections.Generic;
							 | 
						||
| 
								 | 
							
								using UnityEngine;
							 | 
						||
| 
								 | 
							
								using UnityEngine.Events;
							 | 
						||
| 
								 | 
							
								using UnityEngine.EventSystems;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace Autohand
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    [Serializable]
							 | 
						||
| 
								 | 
							
								    public class UnityCanvasPointerEvent : UnityEvent<Vector3, GameObject> { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    [HelpURL("https://app.gitbook.com/s/5zKO0EvOjzUDeT2aiFk3/auto-hand/extras/ui-interaction")]
							 | 
						||
| 
								 | 
							
								    public class HandCanvasPointer : MonoBehaviour
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [Header("References")]
							 | 
						||
| 
								 | 
							
								        public GameObject hitPointMarker;
							 | 
						||
| 
								 | 
							
								        private LineRenderer lineRenderer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        [Header("Ray settings")]
							 | 
						||
| 
								 | 
							
								        public float raycastLength = 8.0f;
							 | 
						||
| 
								 | 
							
								        public bool autoShowTarget = true;
							 | 
						||
| 
								 | 
							
								        public LayerMask UILayer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        [Header("Events")]
							 | 
						||
| 
								 | 
							
								        public UnityCanvasPointerEvent StartSelect;
							 | 
						||
| 
								 | 
							
								        public UnityCanvasPointerEvent StopSelect;
							 | 
						||
| 
								 | 
							
								        public UnityCanvasPointerEvent StartPoint;
							 | 
						||
| 
								 | 
							
								        public UnityCanvasPointerEvent StopPoint;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public GameObject _currTarget;
							 | 
						||
| 
								 | 
							
								        public GameObject currTarget
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            get { return _currTarget; }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public RaycastHit lastHit { get; private set; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Internal variables
							 | 
						||
| 
								 | 
							
								        private bool hover = false;
							 | 
						||
| 
								 | 
							
								        AutoInputModule inputModule = null;
							 | 
						||
| 
								 | 
							
								        float lineSegements = 10f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        static Camera cam = null;
							 | 
						||
| 
								 | 
							
								        public static Camera UICamera
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            get
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (cam == null)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    cam = new GameObject("Camera Canvas Pointer (I AM CREATED AT RUNTIME FOR UI CANVAS INTERACTION, I AM NOT RENDERING ANYTHING, I AM NOT CREATING ADDITIONAL OVERHEAD)").AddComponent<Camera>();
							 | 
						||
| 
								 | 
							
								                    cam.clearFlags = CameraClearFlags.Nothing;
							 | 
						||
| 
								 | 
							
								                    cam.stereoTargetEye = StereoTargetEyeMask.None;
							 | 
						||
| 
								 | 
							
								                    cam.orthographic = true;
							 | 
						||
| 
								 | 
							
								                    cam.orthographicSize = 0.001f;
							 | 
						||
| 
								 | 
							
								                    cam.cullingMask = 0;
							 | 
						||
| 
								 | 
							
								                    cam.nearClipPlane = 0.01f;
							 | 
						||
| 
								 | 
							
								                    cam.depth = 0f;
							 | 
						||
| 
								 | 
							
								                    cam.allowHDR = false;
							 | 
						||
| 
								 | 
							
								                    cam.enabled = false;
							 | 
						||
| 
								 | 
							
								                    cam.fieldOfView = 0.00001f;
							 | 
						||
| 
								 | 
							
								                    cam.transform.parent = AutoHandExtensions.transformParent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if (UNITY_2020_3_OR_NEWER)
							 | 
						||
| 
								 | 
							
								                    var canvases = AutoHandExtensions.CanFindObjectsOfType<Canvas>(true);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								                    var canvases = FindObjectsOfType<Canvas>();
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								                    foreach (var canvas in canvases)
							 | 
						||
| 
								 | 
							
								                        if (canvas.renderMode == RenderMode.WorldSpace)
							 | 
						||
| 
								 | 
							
								                            canvas.worldCamera = cam;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                return cam;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        int pointerIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void OnEnable()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            lineRenderer.positionCount = (int)lineSegements;
							 | 
						||
| 
								 | 
							
								            if (inputModule.Instance != null)
							 | 
						||
| 
								 | 
							
								                pointerIndex = inputModule.Instance.AddPointer(this);
							 | 
						||
| 
								 | 
							
								            ShowRay(false);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void OnDisable()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if(inputModule) inputModule.Instance?.RemovePointer(this);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public void SetIndex(int index)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            pointerIndex = index;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        internal void Preprocess()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            UICamera.transform.position = transform.position;
							 | 
						||
| 
								 | 
							
								            UICamera.transform.forward = transform.forward;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public void Press()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            // Handle the UI events
							 | 
						||
| 
								 | 
							
								            if(inputModule) inputModule.ProcessPress(pointerIndex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Show the ray when they attemp to press
							 | 
						||
| 
								 | 
							
								            if (!autoShowTarget && hover) ShowRay(true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (lastHit.collider != null)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                // Fire the Unity event
							 | 
						||
| 
								 | 
							
								                StartSelect?.Invoke(lastHit.point, lastHit.transform.gameObject);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                PointerEventData data = inputModule.GetData(pointerIndex);
							 | 
						||
| 
								 | 
							
								                float targetLength = data.pointerCurrentRaycast.distance == 0 ? raycastLength : data.pointerCurrentRaycast.distance;
							 | 
						||
| 
								 | 
							
								                StartSelect?.Invoke(transform.position + (transform.forward * targetLength), null);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public void Release()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            // Handle the UI events
							 | 
						||
| 
								 | 
							
								            if(inputModule) inputModule.ProcessRelease(pointerIndex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (lastHit.collider != null)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                // Fire the Unity event
							 | 
						||
| 
								 | 
							
								                StopSelect?.Invoke(lastHit.point, lastHit.transform.gameObject);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                PointerEventData data = inputModule.GetData(pointerIndex);
							 | 
						||
| 
								 | 
							
								                float targetLength = data.pointerCurrentRaycast.distance == 0 ? raycastLength : data.pointerCurrentRaycast.distance;
							 | 
						||
| 
								 | 
							
								                StopSelect?.Invoke(transform.position + (transform.forward * targetLength), null);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private void Awake()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (lineRenderer == null)
							 | 
						||
| 
								 | 
							
								                gameObject.CanGetComponent(out lineRenderer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (inputModule == null)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (gameObject.CanGetComponent<AutoInputModule>(out var inputMod))
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    inputModule = inputMod;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (!(inputModule = AutoHandExtensions.CanFindObjectOfType<AutoInputModule>()))
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    EventSystem system = AutoHandExtensions.CanFindObjectOfType<EventSystem>();
							 | 
						||
| 
								 | 
							
								                    if(system == null) {
							 | 
						||
| 
								 | 
							
								                        system = new GameObject().AddComponent<EventSystem>();
							 | 
						||
| 
								 | 
							
								                        system.name = "UI Input Event System";
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    inputModule = system.gameObject.AddComponent<AutoInputModule>();
							 | 
						||
| 
								 | 
							
								                    inputModule.transform.parent = AutoHandExtensions.transformParent;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private void Update()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            UpdateLine();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private void UpdateLine()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            PointerEventData data = inputModule.GetData(pointerIndex);
							 | 
						||
| 
								 | 
							
								            float targetLength = data.pointerCurrentRaycast.distance == 0 ? raycastLength : data.pointerCurrentRaycast.distance;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (targetLength > 0)
							 | 
						||
| 
								 | 
							
								                _currTarget = data.pointerCurrentRaycast.gameObject;
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								                _currTarget = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (data.pointerCurrentRaycast.distance != 0 && !hover)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                lastHit = CreateRaycast(targetLength);
							 | 
						||
| 
								 | 
							
								                Vector3 endPosition = transform.position + (transform.forward * targetLength);
							 | 
						||
| 
								 | 
							
								                if (lastHit.collider) endPosition = lastHit.point;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (lastHit.collider != null)
							 | 
						||
| 
								 | 
							
								                    StartPoint?.Invoke(lastHit.point, lastHit.transform.gameObject);
							 | 
						||
| 
								 | 
							
								                else
							 | 
						||
| 
								 | 
							
								                    StartPoint?.Invoke(endPosition, null);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                // Show the ray if autoShowTarget is on when they enter the canvas
							 | 
						||
| 
								 | 
							
								                if (autoShowTarget) ShowRay(true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                hover = true;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else if (data.pointerCurrentRaycast.distance == 0 && hover)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                lastHit = CreateRaycast(targetLength);
							 | 
						||
| 
								 | 
							
								                Vector3 endPosition = transform.position + (transform.forward * targetLength);
							 | 
						||
| 
								 | 
							
								                if (lastHit.collider) endPosition = lastHit.point;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (lastHit.collider != null)
							 | 
						||
| 
								 | 
							
								                    StopPoint?.Invoke(lastHit.point, lastHit.transform.gameObject);
							 | 
						||
| 
								 | 
							
								                else
							 | 
						||
| 
								 | 
							
								                    StopPoint?.Invoke(endPosition, null);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                // Hide the ray when they leave the canvas
							 | 
						||
| 
								 | 
							
								                ShowRay(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                hover = false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if(hover) {
							 | 
						||
| 
								 | 
							
								                lastHit = CreateRaycast(targetLength);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                Vector3 endPosition = transform.position + (transform.forward * targetLength);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if(lastHit.collider) endPosition = lastHit.point;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                //Handle the hitmarker
							 | 
						||
| 
								 | 
							
								                hitPointMarker.transform.position = endPosition;
							 | 
						||
| 
								 | 
							
								                hitPointMarker.transform.forward = data.pointerCurrentRaycast.worldNormal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if(lastHit.collider) {
							 | 
						||
| 
								 | 
							
								                    hitPointMarker.transform.forward = lastHit.collider.transform.forward;
							 | 
						||
| 
								 | 
							
								                    hitPointMarker.transform.position = endPosition + hitPointMarker.transform.forward * 0.002f;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                //Handle the line renderer
							 | 
						||
| 
								 | 
							
								                for(int i = 0; i < lineSegements; i++) {
							 | 
						||
| 
								 | 
							
								                    lineRenderer.SetPosition(i, Vector3.Lerp(transform.position, endPosition, i/ lineSegements));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private RaycastHit CreateRaycast(float dist)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            RaycastHit hit;
							 | 
						||
| 
								 | 
							
								            Ray ray = new Ray(transform.position, transform.forward);
							 | 
						||
| 
								 | 
							
								            Physics.Raycast(ray, out hit, dist, UILayer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return hit;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private void ShowRay(bool show)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            hitPointMarker.SetActive(show);
							 | 
						||
| 
								 | 
							
								            lineRenderer.enabled = show;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |