update
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Rive.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace Rive.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides input to a RiveCanvasRenderer and the RivePanel it displays.
|
||||
/// </summary>
|
||||
internal class CanvasPanelInputProvider : MonoBehaviour, IPanelInputProvider, ICanvasRaycastFilter, IPointerDownHandler, IPointerUpHandler, IPointerMoveHandler, IPointerExitHandler, IPointerEnterHandler
|
||||
{
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField] private RiveCanvasRenderer m_riveCanvasRenderer;
|
||||
|
||||
private List<IRiveWidget> m_RaycastResults = new List<IRiveWidget>();
|
||||
|
||||
|
||||
|
||||
private IRivePanel RivePanel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_riveCanvasRenderer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return m_riveCanvasRenderer.RivePanel;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<PanelPointerEvent> PointerPressed;
|
||||
public event Action<PanelPointerEvent> PointerReleased;
|
||||
public event Action<PanelPointerEvent> PointerMoved;
|
||||
public event Action<PanelPointerEvent> PointerExited;
|
||||
public event Action<PanelPointerEvent> PointerEntered;
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
FetchPanelRendererIfNeeded();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
FetchPanelRendererIfNeeded();
|
||||
|
||||
if (m_riveCanvasRenderer == null)
|
||||
{
|
||||
DebugLogger.Instance.LogWarning($"No {nameof(RiveCanvasRenderer)} component found on the GameObject - {gameObject.name}");
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchPanelRendererIfNeeded()
|
||||
{
|
||||
if (m_riveCanvasRenderer == null || !ReferenceEquals(m_riveCanvasRenderer.gameObject, this.gameObject))
|
||||
{
|
||||
m_riveCanvasRenderer = GetComponent<RiveCanvasRenderer>();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGetScreenPointToNormalizedLocalPointInFrame(RectTransform rectTransform, Vector2 screenPoint, Camera eventCamera, out Vector2 normalizedLocalPointInFrame)
|
||||
{
|
||||
normalizedLocalPointInFrame = Vector2.zero;
|
||||
|
||||
if (rectTransform == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector2 localPoint;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out localPoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
normalizedLocalPointInFrame = Rect.PointToNormalized(rectTransform.rect, localPoint);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// When used in a canvas, we don't want the panel raycast target to block raycasts if there are no widgets to hit so we filter out the raycasts in this case.
|
||||
// This allows the raycasts to pass through to regular canvas raycast targets outside of the panel.
|
||||
public bool IsRaycastLocationValid(Vector2 screenPosition, Camera eventCamera)
|
||||
{
|
||||
if (RivePanel == null || m_riveCanvasRenderer.PointerInputMode == PointerInputMode.DisablePointerInput)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_RaycastResults.Clear();
|
||||
Vector2 localNormalizedPointInPanel;
|
||||
if (!TryGetScreenPointToNormalizedLocalPointInFrame(m_riveCanvasRenderer.RectTransform, screenPosition, eventCamera, out localNormalizedPointInPanel))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PanelRaycaster.RaycastAll(RivePanel, localNormalizedPointInPanel, m_RaycastResults);
|
||||
|
||||
bool locationIsValid = m_RaycastResults.Count > 0;
|
||||
|
||||
|
||||
return locationIsValid;
|
||||
}
|
||||
|
||||
|
||||
private void ProcessPointerEvent(PointerEventData eventData, Action<PanelPointerEvent> pointerHandler)
|
||||
{
|
||||
if (pointerHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (RivePanel == null || m_riveCanvasRenderer.PointerInputMode == PointerInputMode.DisablePointerInput || !RivePanel.Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 canvasNormalizedPoint;
|
||||
if (!TryGetScreenPointToNormalizedLocalPointInFrame(m_riveCanvasRenderer.RectTransform, eventData.position, eventData.enterEventCamera, out canvasNormalizedPoint))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int pointerId = eventData.pointerId;
|
||||
pointerHandler(new PanelPointerEvent(canvasNormalizedPoint, pointerId));
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
ProcessPointerEvent(eventData, PointerPressed);
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
ProcessPointerEvent(eventData, PointerReleased);
|
||||
|
||||
}
|
||||
|
||||
public void OnPointerMove(PointerEventData eventData)
|
||||
{
|
||||
ProcessPointerEvent(eventData, PointerMoved);
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
ProcessPointerEvent(eventData, PointerExited);
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
ProcessPointerEvent(eventData, PointerEntered);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0f89e8c33fdd4e5f8ec4f5e3e33bf03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 350858
|
||||
packageName: Rive
|
||||
packageVersion: 0.4.2
|
||||
assetPath: Packages/app.rive.rive-unity/Runtime/Components/InputProviders/CanvasPanelInputProvider.cs
|
||||
uploadId: 896810
|
||||
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using Rive.Components;
|
||||
using Rive.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace Rive.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides input to a RiveTextureRenderer and the RivePanel it displays.
|
||||
/// </summary>
|
||||
internal class TexturePanelInputProvider : MonoBehaviour, IPanelInputProvider, IPointerDownHandler, IPointerUpHandler, IPointerMoveHandler, IPointerExitHandler, IPointerEnterHandler
|
||||
{
|
||||
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField] private RiveTextureRenderer m_rivePanelTextureRenderer;
|
||||
|
||||
private bool m_hasLoggedWrongColliderTypeError = false;
|
||||
private Vector2 m_lastNormalizedLocalPointInPanel = Vector2.zero;
|
||||
|
||||
public event Action<PanelPointerEvent> PointerPressed;
|
||||
public event Action<PanelPointerEvent> PointerReleased;
|
||||
public event Action<PanelPointerEvent> PointerMoved;
|
||||
public event Action<PanelPointerEvent> PointerExited;
|
||||
public event Action<PanelPointerEvent> PointerEntered;
|
||||
|
||||
private IRivePanel RivePanel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_rivePanelTextureRenderer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return m_rivePanelTextureRenderer.RivePanel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private bool IsSupportedCollider(Collider collider)
|
||||
{
|
||||
return collider is MeshCollider;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (m_rivePanelTextureRenderer == null)
|
||||
{
|
||||
m_rivePanelTextureRenderer = GetComponent<RiveTextureRenderer>();
|
||||
|
||||
if (m_rivePanelTextureRenderer == null)
|
||||
{
|
||||
DebugLogger.Instance.LogWarning($"No {nameof(RiveTextureRenderer)} component found on the GameObject - {gameObject.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the normalized local point in the frame from the RaycastResult.
|
||||
/// </summary>
|
||||
/// <param name="raycastResult"> The RaycastResult to get the normalized local point from. </param>
|
||||
/// <param name="normalizedLocalPointInFrame"> The normalized local point in the frame. </param>
|
||||
/// <returns> True if the normalized local point was successfully retrieved, false otherwise. </returns>
|
||||
private bool TryGetNormalizedLocalPointInPanel(RaycastResult raycastResult, out Vector2 normalizedLocalPointInFrame)
|
||||
{
|
||||
normalizedLocalPointInFrame = Vector2.zero;
|
||||
|
||||
|
||||
if (RivePanel == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (raycastResult.gameObject == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Camera camera = raycastResult.module != null ? raycastResult.module.eventCamera : null;
|
||||
if (camera == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Ray ray = camera.ScreenPointToRay(raycastResult.screenPosition);
|
||||
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Get the collider from the hit object.
|
||||
Collider collider = hit.collider;
|
||||
|
||||
if (collider == null)
|
||||
{
|
||||
DebugLogger.Instance.Log("Collider is null.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Vector2 pixelUV;
|
||||
|
||||
if (IsSupportedCollider(collider))
|
||||
{
|
||||
// For mesh colliders, we can use the texture coordinates directly
|
||||
pixelUV = hit.textureCoord;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWrongColliderErrorIfNeeded();
|
||||
return false;
|
||||
}
|
||||
|
||||
normalizedLocalPointInFrame = pixelUV;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LogWrongColliderErrorIfNeeded()
|
||||
{
|
||||
if (!m_hasLoggedWrongColliderTypeError)
|
||||
{
|
||||
DebugLogger.Instance.LogWarning($"Only MeshColliders are supported for pointer input on Rive Panels. Make sure the collider on the GameObject is a MeshCollider, or set the {nameof(PointerInputMode)} to {nameof(PointerInputMode.DisablePointerInput)} on the {nameof(RiveTextureRenderer)}.");
|
||||
m_hasLoggedWrongColliderTypeError = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessEvent(PointerEventData eventData, Action<PanelPointerEvent> pointerHandler)
|
||||
{
|
||||
if (pointerHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (RivePanel == null || m_rivePanelTextureRenderer.PointerInputMode == PointerInputMode.DisablePointerInput || !RivePanel.Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool pointIsInPanel = TryGetNormalizedLocalPointInPanel(eventData.pointerCurrentRaycast, out Vector2 normalizedLocalPointInPanel);
|
||||
|
||||
if (pointIsInPanel)
|
||||
{
|
||||
// Store the last known point in case we need to call the event with it later (like with OnPointerExit).
|
||||
m_lastNormalizedLocalPointInPanel = normalizedLocalPointInPanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This would be the case with OnPointerExit, because the raycast wouldn't have anything to hit, so we call the event with the last known point.
|
||||
normalizedLocalPointInPanel = m_lastNormalizedLocalPointInPanel;
|
||||
}
|
||||
|
||||
int pointerId = eventData.pointerId;
|
||||
pointerHandler?.Invoke(new PanelPointerEvent(normalizedLocalPointInPanel, pointerId));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void OnPointerMove(PointerEventData eventData)
|
||||
{
|
||||
ProcessEvent(eventData, PointerMoved);
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
ProcessEvent(eventData, PointerReleased);
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
ProcessEvent(eventData, PointerPressed);
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
ProcessEvent(eventData, PointerExited);
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
ProcessEvent(eventData, PointerEntered);
|
||||
}
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
if (m_rivePanelTextureRenderer == null)
|
||||
{
|
||||
m_rivePanelTextureRenderer = GetComponent<RiveTextureRenderer>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d5c455172690403b81ea6a542509e94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 350858
|
||||
packageName: Rive
|
||||
packageVersion: 0.4.2
|
||||
assetPath: Packages/app.rive.rive-unity/Runtime/Components/InputProviders/TexturePanelInputProvider.cs
|
||||
uploadId: 896810
|
||||
Reference in New Issue
Block a user