/* INFINITY CODE */ /* https://infinity-code.com */ /* Special thanks to Brian Chasalow and V for help in developing this script. */ using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class OnlineMapsRawImageTouchForwarder : MonoBehaviour { private static Vector2 zeroPosition = new Vector2(-10000, -10000); private static Vector3[] corners = new Vector3[4]; public RawImage image; public OnlineMaps map; public RenderTexture targetTexture; private OnlineMapsTileSetControl control; private Vector2 pointerPos = zeroPosition; private GameObject target; public Camera worldCamera { get { if (!image.canvas || image.canvas.renderMode == RenderMode.ScreenSpaceOverlay) return null; return image.canvas.worldCamera; } } public Vector2 ForwarderToMapSpace(Vector2 position) { Vector2 pos; if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform, position, worldCamera, out pos)) return pos; Vector2 sizeDelta = GetSizeDelta(image.rectTransform) / image.canvas.scaleFactor; pos += sizeDelta / 2; pos *= GetTargetSize() / sizeDelta; return pos; } private static Vector2 GetSizeDelta(RectTransform t) { t.GetWorldCorners(corners); return corners[2] - corners[0]; } private GameObject GetTargetGameObject(Vector2 position) { PointerEventData pe = new PointerEventData(EventSystem.current) { position = position }; List hits = new List(); EventSystem.current.RaycastAll(pe, hits); return hits.Any(h => h.gameObject == image.gameObject) ? image.gameObject : null; } public Vector2 GetTargetSize() { if (targetTexture) return new Vector2(targetTexture.width, targetTexture.height); return new Vector2(Screen.width, Screen.height); } private int GetTouchCountFromForwarder() { if (target != image.gameObject) return 0; #if UNITY_EDITOR return OnlineMapsInput.GetMouseButton(0) ? 1 : 0; #else if (OnlineMapsInput.touchSupported) { if (OnlineMapsInput.touchCount > 0) return OnlineMapsInput.touchCount; } return OnlineMapsInput.GetMouseButton(0) ? 1 : 0; #endif } public Vector2 MapToForwarderSpace(Vector2 position) { Vector2 sizeDelta = GetSizeDelta(image.rectTransform) * image.canvas.scaleFactor; position *= sizeDelta / GetTargetSize(); position -= sizeDelta / 2; Vector3 pos = (Vector3)position + image.transform.position; return RectTransformUtility.WorldToScreenPoint(worldCamera, pos); } protected void OnDisable() { control.OnUpdateBefore -= OnUpdateBefore; control.OnGetMultitouchInputPositions -= OnGetMultitouchInputPositions; control.OnGetInputPosition -= OnGetInputPosition; control.OnGetTouchCount -= OnGetTouchCount; OnlineMapsGUITooltipDrawer.OnDrawTooltip -= OnDrawTooltip; } private void OnDrawTooltip(GUIStyle style, string text, Vector2 position) { RectTransform t = image.rectTransform; Vector2 sizeDelta = GetSizeDelta(image.rectTransform); Vector2 p = position * sizeDelta / GetTargetSize() - t.sizeDelta / 2; Vector3 pos = (Vector3)p + corners[0]; p = RectTransformUtility.WorldToScreenPoint(worldCamera, pos); GUIContent tip = new GUIContent(text); Vector2 size = style.CalcSize(tip); Rect rect = new Rect( p.x - size.x / 2 - 5, Screen.height - p.y - size.y - 20, size.x + 10, size.y + 5 ); GUI.Label(rect, text, style); } private void OnEnable() { if (!map) map = OnlineMaps.instance; control = map?.control as OnlineMapsTileSetControl; if (!control) return; control.OnUpdateBefore += OnUpdateBefore; control.OnGetTouchCount += OnGetTouchCount; control.OnGetInputPosition += OnGetInputPosition; control.OnGetMultitouchInputPositions += OnGetMultitouchInputPositions; map.notInteractUnderGUI = false; control.checkScreenSizeForWheelZoom = false; OnlineMapsGUITooltipDrawer.OnDrawTooltip += OnDrawTooltip; } private Vector2 OnGetInputPosition() { if (target != image.gameObject) return zeroPosition; return ProcessTouch(pointerPos, out Vector2 pos) ? pos : zeroPosition; } private Vector2[] OnGetMultitouchInputPositions() { Vector2[] touches = OnlineMapsInput.touches.Select(t => t.position).ToArray(); for (int i = 0; i < touches.Length; i++) { ProcessTouch(touches[i], out Vector2 p, false); touches[i] = p; } return touches; } private int OnGetTouchCount() { return target == image.gameObject ? GetTouchCountFromForwarder() : 0; } private void OnUpdateBefore() { pointerPos = OnlineMapsInput.mousePosition; if (OnlineMapsInput.touchSupported && OnlineMapsInput.touchCount > 0) { pointerPos = zeroPosition; for (int i = 0; i < OnlineMapsInput.touchCount; i++) { Touch touch = OnlineMapsInput.touches[i]; pointerPos += touch.position; } pointerPos /= OnlineMapsInput.touchCount; } target = GetTargetGameObject(pointerPos); } private bool ProcessTouch(Vector2 inputTouch, out Vector2 localPosition, bool checkRect = true) { localPosition = zeroPosition; RectTransform t = image.rectTransform; if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform, inputTouch, worldCamera, out localPosition)) return false; if (checkRect && !t.rect.Contains(localPosition)) return false; Vector2 sizeDelta = GetSizeDelta(t) / image.canvas.scaleFactor; localPosition += sizeDelta / 2.0f; localPosition *= GetTargetSize() / sizeDelta; return true; } }