update
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace Rive.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// The hit test behavior of a RiveWidget in relation to other elements.
|
||||
/// </summary>
|
||||
public enum HitTestBehavior
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The bounds of the RiveWidget will consume all hits, even if there is no listener (hit area) at the target point. Content behind the RiveWidget will not receive hits.
|
||||
/// </summary>
|
||||
Opaque = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The RiveWidget will only consume hits where there is a listener (hit area) at the target point. Content behind the RiveWidget will only receive hits if no listener was hit.
|
||||
/// </summary>
|
||||
Translucent = 1,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All hits will pass through the RiveWidget, regardless of whether a Rive listener was hit. Rive listeners will still receive hits.
|
||||
/// </summary>
|
||||
[Obsolete("Transparent hit testing is deprecated, please use Translucent instead.")]
|
||||
Transparent = 2,
|
||||
|
||||
/// <summary>
|
||||
/// No hit testing will be performed on the RiveWidget.
|
||||
/// </summary>
|
||||
None = 3
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70f512ba226594a9da0ac89681b3070a
|
||||
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/Public/HitTesting/HitTestBehavior.cs
|
||||
uploadId: 896810
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Rive.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for providing input events to a RivePanel.
|
||||
/// </summary>
|
||||
public interface IPanelInputProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a pointer is pressed. The Vector2 parameter represents the normalized local point in the panel,
|
||||
/// where coordinates are in the range [0,1] with (0,0) at bottom-left and (1,1) at top-right.
|
||||
/// </summary>
|
||||
event Action<PanelPointerEvent> PointerPressed;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a pointer is released. The Vector2 parameter represents the normalized local point in the panel,
|
||||
/// where coordinates are in the range [0,1] with (0,0) at bottom-left and (1,1) at top-right.
|
||||
/// </summary>
|
||||
event Action<PanelPointerEvent> PointerReleased;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a pointer is moved. The Vector2 parameter represents the normalized local point in the panel,
|
||||
/// where coordinates are in the range [0,1] with (0,0) at bottom-left and (1,1) at top-right.
|
||||
/// </summary>
|
||||
event Action<PanelPointerEvent> PointerMoved;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a pointer exits the panel. The Vector2 parameter represents the normalized local point in the panel,
|
||||
/// where coordinates are in the range [0,1] with (0,0) at bottom-left and (1,1) at top-right.
|
||||
/// </summary>
|
||||
event Action<PanelPointerEvent> PointerExited;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a pointer enters the panel. The Vector2 parameter represents the normalized local point in the panel,
|
||||
/// where coordinates are in the range [0,1] with (0,0) at bottom-left and (1,1) at top-right.
|
||||
/// </summary>
|
||||
event Action<PanelPointerEvent> PointerEntered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7db5fdfddda6b4de1afcb3f3f7437ea1
|
||||
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/Public/HitTesting/IPanelInputProvider.cs
|
||||
uploadId: 896810
|
||||
@@ -0,0 +1,27 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Rive.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Pointer data delivered by input providers and propagated through the panel/widget pipeline.
|
||||
/// </summary>
|
||||
public readonly struct PanelPointerEvent
|
||||
{
|
||||
public readonly Vector2 Position;
|
||||
public readonly int PointerId;
|
||||
/// <summary>
|
||||
/// Creates a new pointer event for panel input propagation.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// The normalized point in panel space [0,1] where (0,0) is bottom-left and (1,1) is top-right.
|
||||
/// </param>
|
||||
/// <param name="pointerId">The unique id for the active pointer/touch.</param>
|
||||
public PanelPointerEvent(Vector2 position, int pointerId)
|
||||
{
|
||||
Position = position;
|
||||
PointerId = pointerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfb74b0293d1b4c07922c10574a0abd4
|
||||
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/Public/HitTesting/PanelPointerEvent.cs
|
||||
uploadId: 896810
|
||||
@@ -0,0 +1,140 @@
|
||||
using System.Collections.Generic;
|
||||
using Rive.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Rive.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class for performing hit testing (raycasting) on RivePanels to detect which widgets are under a given point.
|
||||
/// This is used to handle input events and determine which widgets should receive pointer interactions.
|
||||
/// </summary>
|
||||
public class PanelRaycaster
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates the raycastResults list with the widgets in a RivePanel that are hit by the given normalized local point in the panel.
|
||||
/// </summary>
|
||||
/// <param name="rivePanel"> The RivePanel to check for hit widgets. </param>
|
||||
/// <param name="normalizedPointInPanel"> The normalized local point in the panel to check for hit widgets. The coordinates are in the range [0,1] where (0,0) is the bottom-left corner and (1,1) is the top-right corner. </param>
|
||||
/// <param name="eventCamera"> The camera used by the event system or canvas </param>
|
||||
/// <param name="raycastResults"> The list to populate with hit widgets. </param>
|
||||
public static void RaycastAll(IRivePanel rivePanel, Vector2 normalizedPointInPanel, List<IRiveWidget> raycastResults)
|
||||
{
|
||||
RectTransform panelRectTransform = rivePanel.WidgetContainer;
|
||||
if (panelRectTransform == null)
|
||||
{
|
||||
DebugLogger.Instance.LogError("Panel RectTransform is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i = rivePanel.Widgets.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var widget = rivePanel.Widgets[i];
|
||||
if (widget == null || !widget.Enabled || widget.RenderObject == null || widget.HitTestBehavior == HitTestBehavior.None)
|
||||
continue;
|
||||
|
||||
Vector2 normalizedWidgetPoint;
|
||||
bool isWithinWidgetBounds = TryGetNormalizedPointInWidget(rivePanel, normalizedPointInPanel, widget, out normalizedWidgetPoint);
|
||||
|
||||
if (ProcessHitTestBehavior(widget, normalizedWidgetPoint, raycastResults, isWithinWidgetBounds))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Processes the hit test behavior of a widget and adds it to the raycastResults list if it should be hit.
|
||||
/// </summary>
|
||||
/// <param name="widget"> The widget to process. </param>
|
||||
/// <param name="normalizedPointInWidgetRect"> The normalized point in the widget's rect to check for a hit. The coordinates are in the range [0,1] where (0,0) is the bottom-left corner and (1,1) is the top-right corner. </param>
|
||||
/// <param name="raycastResults"> The list to populate with hit widgets. </param>
|
||||
/// <returns> True if should should block other widgets from being hit, false otherwise. </returns>
|
||||
private static bool ProcessHitTestBehavior(IRiveWidget widget, Vector2 normalizedPointInWidgetRect, List<IRiveWidget> raycastResults, bool isWithinWidgetBounds)
|
||||
{
|
||||
switch (widget.HitTestBehavior)
|
||||
{
|
||||
case HitTestBehavior.Opaque:
|
||||
|
||||
raycastResults.Add(widget);
|
||||
// Block other widgets from being hit if the pointer is within the widget
|
||||
return isWithinWidgetBounds;
|
||||
case HitTestBehavior.Translucent:
|
||||
bool foundHit = widget.HitTest(normalizedPointInWidgetRect);
|
||||
|
||||
if (foundHit)
|
||||
{
|
||||
raycastResults.Add(widget);
|
||||
return isWithinWidgetBounds;
|
||||
}
|
||||
break;
|
||||
#pragma warning disable CS0618 // Transparent hit testing is deprecated but kept for backward compatibility
|
||||
case HitTestBehavior.Transparent:
|
||||
raycastResults.Add(widget);
|
||||
// Continue checking other widgets
|
||||
return false;
|
||||
#pragma warning restore CS0618
|
||||
case HitTestBehavior.None:
|
||||
// Do not add to raycastResults
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the normalized local point in the widget from the normalized local point in the panel.
|
||||
/// </summary>
|
||||
/// <param name="rivePanel"> The RivePanel that contains the widget. </param>
|
||||
/// <param name="normalizedPointInPanel"> The normalized local point in the panel. The coordinates are in the range [0,1] where (0,0) is the bottom-left corner and (1,1) is the top-right corner.</param>
|
||||
/// <param name="widget"> The widget to get the normalized local point in. </param>
|
||||
/// <param name="normalizedWidgetPoint"> The normalized point in the widget's rect. </param>
|
||||
/// <returns> True if the normalized local point is within the widget's bounds, false otherwise. </returns>
|
||||
public static bool TryGetNormalizedPointInWidget(IRivePanel rivePanel, Vector2 normalizedPointInPanel, IRiveWidget widget, out Vector2 normalizedWidgetPoint)
|
||||
{
|
||||
normalizedWidgetPoint = Vector2.zero;
|
||||
|
||||
RectTransform panelRectTransform = rivePanel.WidgetContainer;
|
||||
if (panelRectTransform == null)
|
||||
{
|
||||
DebugLogger.Instance.LogError("Panel RectTransform is null.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var panelRect = panelRectTransform.rect;
|
||||
if (panelRect.width <= 0f || panelRect.height <= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need to turn the normalized point (0..1) into a local point on the panel.
|
||||
// Unity’s RectTransform coordinates are based on the pivot, not always the center.
|
||||
// So when the pivot changes, the rect’s xMin/yMin shift too. If we ignore that, input gets offset.
|
||||
// Using xMin/yMin + (normalized * size) lets us rebuild the original local point again, so everything stays lined up.
|
||||
Vector2 panelLocalPoint = new Vector2(
|
||||
panelRect.xMin + (normalizedPointInPanel.x * panelRect.width),
|
||||
panelRect.yMin + (normalizedPointInPanel.y * panelRect.height)
|
||||
);
|
||||
|
||||
Vector3 worldPoint = panelRectTransform.TransformPoint(panelLocalPoint);
|
||||
|
||||
Vector3 widgetLocalPoint = widget.RectTransform.InverseTransformPoint(worldPoint);
|
||||
|
||||
normalizedWidgetPoint = new Vector2(
|
||||
(widgetLocalPoint.x - widget.RectTransform.rect.xMin) / widget.RectTransform.rect.width,
|
||||
(widgetLocalPoint.y - widget.RectTransform.rect.yMin) / widget.RectTransform.rect.height
|
||||
);
|
||||
|
||||
if (widget.RectTransform.rect.Contains(widgetLocalPoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc94d7864e5db458e990e4d9fdd933d3
|
||||
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/Public/HitTesting/PanelRaycaster.cs
|
||||
uploadId: 896810
|
||||
Reference in New Issue
Block a user