diff --git a/Assets/Tests/Editor/MouseUiCoordinateConverterTests.cs b/Assets/Tests/Editor/MouseUiCoordinateConverterTests.cs
new file mode 100644
index 0000000000..6969c1abb9
--- /dev/null
+++ b/Assets/Tests/Editor/MouseUiCoordinateConverterTests.cs
@@ -0,0 +1,45 @@
+using NUnit.Framework;
+using UnityEditor;
+using UnityEngine;
+
+using io.github.hatayama.UnityCliLoop.FirstPartyTools;
+
+namespace io.github.hatayama.UnityCliLoop.Tests.Editor
+{
+ ///
+ /// Characterizes coordinate conversion shared by mouse UI action executors.
+ ///
+ [TestFixture]
+ public sealed class MouseUiCoordinateConverterTests
+ {
+ ///
+ /// Verifies top-left input coordinates are flipped against the current Game view height.
+ ///
+ [Test]
+ public void InputToScreen_WithTopLeftCoordinates_FlipsYAgainstCurrentGameViewHeight()
+ {
+ Vector2 inputPosition = new(12.5f, 37.25f);
+ float gameViewHeight = Handles.GetMainGameViewSize().y;
+
+ Vector2 screenPosition = MouseUiCoordinateConverter.InputToScreen(inputPosition);
+
+ Assert.That(
+ screenPosition,
+ Is.EqualTo(new Vector2(inputPosition.x, gameViewHeight - inputPosition.y)));
+ }
+
+ ///
+ /// Verifies converting input coordinates to screen space and back preserves the position.
+ ///
+ [Test]
+ public void ScreenToInput_AfterInputToScreen_RestoresPosition()
+ {
+ Vector2 inputPosition = new(42.5f, 64.25f);
+
+ Vector2 screenPosition = MouseUiCoordinateConverter.InputToScreen(inputPosition);
+ Vector2 restoredPosition = MouseUiCoordinateConverter.ScreenToInput(screenPosition);
+
+ Assert.That(restoredPosition, Is.EqualTo(inputPosition));
+ }
+ }
+}
diff --git a/Assets/Tests/Editor/MouseUiCoordinateConverterTests.cs.meta b/Assets/Tests/Editor/MouseUiCoordinateConverterTests.cs.meta
new file mode 100644
index 0000000000..13acb98485
--- /dev/null
+++ b/Assets/Tests/Editor/MouseUiCoordinateConverterTests.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 87ef2e81957a4e62a25589f09ed27b6b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Tests/Editor/StaticFacadeStateGuardTests.cs b/Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
index 433f950558..4526b8987e 100644
--- a/Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
+++ b/Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
@@ -328,10 +328,11 @@ public void ExecuteDynamicCodeUseCase_WhenAwaitingWorkflow_DoesNotCaptureEditorS
}
[Test]
- public void SimulateMouseUiUseCase_WhenReturningAfterTimeout_UsesCapturedUnityObjectState()
+ public void MouseUiPressActionExecutor_WhenReturningAfterTimeout_UsesCapturedUnityObjectState()
{
// Tests that timeout result branches use plain captured bools instead of UnityEngine.Object null checks.
- string source = ReadSourceFile("Packages/src/Editor/FirstPartyTools/SimulateMouseUi/SimulateMouseUiUseCase.cs");
+ string source = ReadSourceFile(
+ "Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs");
Assert.That(source, Does.Contain("bool hitTarget = resolvedTargets.Target != null;"));
Assert.That(source, Does.Contain("bool shouldReleasePointer = resolvedTargets.RawTarget != null && resolvedTargets.Target != null;"));
diff --git a/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiCoordinateConverter.cs b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiCoordinateConverter.cs
new file mode 100644
index 0000000000..ea8fe05ebf
--- /dev/null
+++ b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiCoordinateConverter.cs
@@ -0,0 +1,27 @@
+#nullable enable
+using UnityEditor;
+using UnityEngine;
+
+namespace io.github.hatayama.UnityCliLoop.FirstPartyTools
+{
+ ///
+ /// Converts between top-left mouse input coordinates and Unity screen coordinates.
+ ///
+ internal static class MouseUiCoordinateConverter
+ {
+ // Input coordinates use top-left origin; Unity Screen space uses bottom-left origin.
+ // Handles.GetMainGameViewSize() returns the Game view's target resolution (e.g. 1920x1080),
+ // which matches the Canvas layout space — unlike Screen.height which returns the window pixel size.
+ internal static Vector2 InputToScreen(Vector2 inputPos)
+ {
+ float targetHeight = Handles.GetMainGameViewSize().y;
+ return new Vector2(inputPos.x, targetHeight - inputPos.y);
+ }
+
+ internal static Vector2 ScreenToInput(Vector2 screenPos)
+ {
+ float targetHeight = Handles.GetMainGameViewSize().y;
+ return new Vector2(screenPos.x, targetHeight - screenPos.y);
+ }
+ }
+}
diff --git a/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiCoordinateConverter.cs.meta b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiCoordinateConverter.cs.meta
new file mode 100644
index 0000000000..44713341fe
--- /dev/null
+++ b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiCoordinateConverter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: acada63040774a569f5945fc464b30f1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs
new file mode 100644
index 0000000000..5cb3b556c3
--- /dev/null
+++ b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs
@@ -0,0 +1,218 @@
+#nullable enable
+using System.Threading;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.EventSystems;
+
+using io.github.hatayama.UnityCliLoop.Runtime;
+using io.github.hatayama.UnityCliLoop.ToolContracts;
+
+namespace io.github.hatayama.UnityCliLoop.FirstPartyTools
+{
+ ///
+ /// Executes click and long-press mouse UI actions.
+ ///
+ internal static class MouseUiPressActionExecutor
+ {
+ internal static async Task ExecuteClick(
+ MouseUiSimulationCommand parameters,
+ EventSystem eventSystem,
+ MouseUiMainThreadCleanupScheduler cleanupScheduler,
+ CancellationToken ct)
+ {
+ Vector2 inputPos = new(parameters.X, parameters.Y);
+ Vector2 screenPos = MouseUiCoordinateConverter.InputToScreen(inputPos);
+ PointerEventData pointerData = MouseUiPointerTargetResolver.CreatePointerPressData(eventSystem, screenPos, parameters.Button);
+ ResolvedPointerTargets resolvedTargets =
+ MouseUiPointerTargetResolver.ResolvePressablePointerTargets(parameters, eventSystem, inputPos, screenPos, pointerData, MouseAction.Click);
+ if (resolvedTargets.FailureResponse != null)
+ {
+ return resolvedTargets.FailureResponse;
+ }
+
+ if (parameters.BypassRaycast && resolvedTargets.Target == null)
+ {
+ return new SimulateMouseUiResponse
+ {
+ Success = false,
+ Message = $"TargetPath '{parameters.TargetPath}' has no pointer click or pointer down handler.",
+ Action = MouseAction.Click.ToString(),
+ PositionX = inputPos.x,
+ PositionY = inputPos.y
+ };
+ }
+
+ string? targetName = resolvedTargets.Target?.name;
+ bool hitTarget = resolvedTargets.Target != null;
+ SimulateMouseUiOverlayState.Update(
+ MouseAction.Click, inputPos, null,
+ targetName, Handles.GetMainGameViewSize());
+
+ bool expandCompleted = await MouseUiOverlayAnimator.PlayExpandAnimation(ct).ConfigureAwait(false);
+ if (!expandCompleted)
+ {
+ cleanupScheduler.QueueOverlayClear();
+ return MouseUiSimulationResponseFactory.CreateFrameTimeoutResult(MouseAction.Click, inputPos, null, targetName);
+ }
+ await MainThreadSwitcher.SwitchToMainThread(ct);
+
+ // Fire click events after expand animation so the user sees where the click lands
+ ExecutePointerClickEvents(resolvedTargets, pointerData);
+
+ bool dissipateCompleted = await MouseUiOverlayAnimator.PlayDissipateAnimation(ct).ConfigureAwait(false);
+ if (!dissipateCompleted)
+ {
+ cleanupScheduler.QueueOverlayClear();
+ return MouseUiSimulationResponseFactory.CreateClickResult(parameters, inputPos, targetName, hitTarget);
+ }
+ await MainThreadSwitcher.SwitchToMainThread(ct);
+
+ return MouseUiSimulationResponseFactory.CreateClickResult(parameters, inputPos, targetName, hitTarget);
+ }
+
+ internal static async Task ExecuteLongPress(
+ MouseUiSimulationCommand parameters,
+ EventSystem eventSystem,
+ MouseUiMainThreadCleanupScheduler cleanupScheduler,
+ CancellationToken ct)
+ {
+ if (parameters.Duration <= 0f || float.IsNaN(parameters.Duration) || float.IsInfinity(parameters.Duration))
+ {
+ return new SimulateMouseUiResponse
+ {
+ Success = false,
+ Message = $"Duration must be positive, got: {parameters.Duration}",
+ Action = MouseAction.LongPress.ToString()
+ };
+ }
+
+ Vector2 inputPos = new(parameters.X, parameters.Y);
+ Vector2 screenPos = MouseUiCoordinateConverter.InputToScreen(inputPos);
+ PointerEventData pointerData = MouseUiPointerTargetResolver.CreatePointerPressData(eventSystem, screenPos, parameters.Button);
+ ResolvedPointerTargets resolvedTargets =
+ MouseUiPointerTargetResolver.ResolvePressablePointerTargets(parameters, eventSystem, inputPos, screenPos, pointerData, MouseAction.LongPress);
+ if (resolvedTargets.FailureResponse != null)
+ {
+ return resolvedTargets.FailureResponse;
+ }
+
+ if (parameters.BypassRaycast && resolvedTargets.Target == null)
+ {
+ return new SimulateMouseUiResponse
+ {
+ Success = false,
+ Message = $"TargetPath '{parameters.TargetPath}' has no pointer down or pointer click handler.",
+ Action = MouseAction.LongPress.ToString(),
+ PositionX = inputPos.x,
+ PositionY = inputPos.y
+ };
+ }
+
+ string? targetName = resolvedTargets.Target?.name;
+ bool hitTarget = resolvedTargets.Target != null;
+ bool shouldReleasePointer = resolvedTargets.RawTarget != null && resolvedTargets.Target != null;
+ SimulateMouseUiOverlayState.Update(
+ MouseAction.LongPress, inputPos, null,
+ targetName, Handles.GetMainGameViewSize());
+
+ bool expandCompleted = await MouseUiOverlayAnimator.PlayExpandAnimation(ct).ConfigureAwait(false);
+ if (!expandCompleted)
+ {
+ cleanupScheduler.QueueOverlayClear();
+ return MouseUiSimulationResponseFactory.CreateFrameTimeoutResult(MouseAction.LongPress, inputPos, null, targetName);
+ }
+ await MainThreadSwitcher.SwitchToMainThread(ct);
+
+ ExecuteLongPressPointerDown(resolvedTargets, pointerData);
+
+ try
+ {
+ // Hold for Duration seconds, updating elapsed time each frame for overlay display
+ float startTime = Time.realtimeSinceStartup;
+ float elapsed = 0f;
+ while (elapsed < parameters.Duration)
+ {
+ SimulateMouseUiOverlayState.UpdateLongPressElapsed(elapsed);
+ bool frameReady = await MouseUiEditorFrameWaiter.WaitForEditorFrameAndSwitchToMainThreadAsync(ct).ConfigureAwait(false);
+ if (!frameReady)
+ {
+ cleanupScheduler.QueueOverlayClear();
+ return MouseUiSimulationResponseFactory.CreateFrameTimeoutResult(MouseAction.LongPress, inputPos, null, targetName);
+ }
+ await MainThreadSwitcher.SwitchToMainThread(ct);
+ elapsed = Time.realtimeSinceStartup - startTime;
+ }
+ SimulateMouseUiOverlayState.UpdateLongPressElapsed(parameters.Duration);
+ }
+ finally
+ {
+ // Ensure pointerUp fires even if the hold loop is cancelled
+ if (shouldReleasePointer)
+ {
+ cleanupScheduler.ExecuteCleanupOnMainThread(
+ () => ExecuteEvents.Execute(resolvedTargets.Target!, pointerData, ExecuteEvents.pointerUpHandler));
+ }
+ }
+
+ bool dissipateCompleted = await MouseUiOverlayAnimator.PlayDissipateAnimation(ct).ConfigureAwait(false);
+ if (!dissipateCompleted)
+ {
+ cleanupScheduler.QueueOverlayClear();
+ return MouseUiSimulationResponseFactory.CreateLongPressResult(parameters, inputPos, targetName, hitTarget);
+ }
+ await MainThreadSwitcher.SwitchToMainThread(ct);
+
+ return MouseUiSimulationResponseFactory.CreateLongPressResult(parameters, inputPos, targetName, hitTarget);
+ }
+
+ private static void ExecutePointerClickEvents(
+ ResolvedPointerTargets resolvedTargets,
+ PointerEventData pointerData)
+ {
+ if (resolvedTargets.RawTarget == null)
+ {
+ return;
+ }
+
+ if (resolvedTargets.PressTarget != null)
+ {
+ ExecuteEvents.ExecuteHierarchy(
+ resolvedTargets.RawTarget,
+ pointerData,
+ ExecuteEvents.pointerDownHandler);
+ }
+
+ if (resolvedTargets.Target != null)
+ {
+ ExecuteEvents.Execute(
+ resolvedTargets.Target,
+ pointerData,
+ ExecuteEvents.pointerUpHandler);
+ }
+
+ if (resolvedTargets.ClickTarget != null)
+ {
+ ExecuteEvents.Execute(
+ resolvedTargets.ClickTarget,
+ pointerData,
+ ExecuteEvents.pointerClickHandler);
+ }
+ }
+
+ private static void ExecuteLongPressPointerDown(
+ ResolvedPointerTargets resolvedTargets,
+ PointerEventData pointerData)
+ {
+ if (resolvedTargets.RawTarget == null || resolvedTargets.Target == null)
+ {
+ return;
+ }
+
+ ExecuteEvents.ExecuteHierarchy(
+ resolvedTargets.RawTarget,
+ pointerData,
+ ExecuteEvents.pointerDownHandler);
+ }
+ }
+}
diff --git a/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs.meta b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs.meta
new file mode 100644
index 0000000000..dac5c0e384
--- /dev/null
+++ b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/MouseUiPressActionExecutor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8b0a30f1d03b457c870578e67fd99f1b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/SimulateMouseUiUseCase.cs b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/SimulateMouseUiUseCase.cs
index cc65111861..4f30a03383 100644
--- a/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/SimulateMouseUiUseCase.cs
+++ b/Packages/src/Editor/FirstPartyTools/SimulateMouseUi/SimulateMouseUiUseCase.cs
@@ -85,7 +85,11 @@ private async Task ExecuteMouseAction(
switch (parameters.Action)
{
case MouseAction.Click:
- return await ExecuteClick(parameters, eventSystem, ct).ConfigureAwait(false);
+ return await MouseUiPressActionExecutor.ExecuteClick(
+ parameters,
+ eventSystem,
+ _mainThreadCleanupScheduler,
+ ct).ConfigureAwait(false);
case MouseAction.Drag:
return await ExecuteDragOneShot(parameters, eventSystem, ct).ConfigureAwait(false);
@@ -100,7 +104,11 @@ private async Task ExecuteMouseAction(
return await ExecuteDragEnd(parameters, ct).ConfigureAwait(false);
case MouseAction.LongPress:
- return await ExecuteLongPress(parameters, eventSystem, ct).ConfigureAwait(false);
+ return await MouseUiPressActionExecutor.ExecuteLongPress(
+ parameters,
+ eventSystem,
+ _mainThreadCleanupScheduler,
+ ct).ConfigureAwait(false);
default:
// Unreachable when TryFromSchema succeeds; kept as a defensive Success=false response
@@ -111,215 +119,6 @@ private async Task ExecuteMouseAction(
}
}
- // Input coordinates use top-left origin; Unity Screen space uses bottom-left origin.
- // Handles.GetMainGameViewSize() returns the Game view's target resolution (e.g. 1920x1080),
- // which matches the Canvas layout space — unlike Screen.height which returns the window pixel size.
- private static Vector2 InputToScreen(Vector2 inputPos)
- {
- float targetHeight = Handles.GetMainGameViewSize().y;
- return new Vector2(inputPos.x, targetHeight - inputPos.y);
- }
-
- private static Vector2 ScreenToInput(Vector2 screenPos)
- {
- float targetHeight = Handles.GetMainGameViewSize().y;
- return new Vector2(screenPos.x, targetHeight - screenPos.y);
- }
-
- private async Task ExecuteClick(
- MouseUiSimulationCommand parameters, EventSystem eventSystem, CancellationToken ct)
- {
- Vector2 inputPos = new(parameters.X, parameters.Y);
- Vector2 screenPos = InputToScreen(inputPos);
- PointerEventData pointerData = MouseUiPointerTargetResolver.CreatePointerPressData(eventSystem, screenPos, parameters.Button);
- ResolvedPointerTargets resolvedTargets =
- MouseUiPointerTargetResolver.ResolvePressablePointerTargets(parameters, eventSystem, inputPos, screenPos, pointerData, MouseAction.Click);
- if (resolvedTargets.FailureResponse != null)
- {
- return resolvedTargets.FailureResponse;
- }
-
- if (parameters.BypassRaycast && resolvedTargets.Target == null)
- {
- return new SimulateMouseUiResponse
- {
- Success = false,
- Message = $"TargetPath '{parameters.TargetPath}' has no pointer click or pointer down handler.",
- Action = MouseAction.Click.ToString(),
- PositionX = inputPos.x,
- PositionY = inputPos.y
- };
- }
-
- string? targetName = resolvedTargets.Target?.name;
- bool hitTarget = resolvedTargets.Target != null;
- SimulateMouseUiOverlayState.Update(
- MouseAction.Click, inputPos, null,
- targetName, Handles.GetMainGameViewSize());
-
- bool expandCompleted = await MouseUiOverlayAnimator.PlayExpandAnimation(ct).ConfigureAwait(false);
- if (!expandCompleted)
- {
- _mainThreadCleanupScheduler.QueueOverlayClear();
- return MouseUiSimulationResponseFactory.CreateFrameTimeoutResult(MouseAction.Click, inputPos, null, targetName);
- }
- await MainThreadSwitcher.SwitchToMainThread(ct);
-
- // Fire click events after expand animation so the user sees where the click lands
- ExecutePointerClickEvents(resolvedTargets, pointerData);
-
- bool dissipateCompleted = await MouseUiOverlayAnimator.PlayDissipateAnimation(ct).ConfigureAwait(false);
- if (!dissipateCompleted)
- {
- _mainThreadCleanupScheduler.QueueOverlayClear();
- return MouseUiSimulationResponseFactory.CreateClickResult(parameters, inputPos, targetName, hitTarget);
- }
- await MainThreadSwitcher.SwitchToMainThread(ct);
-
- return MouseUiSimulationResponseFactory.CreateClickResult(parameters, inputPos, targetName, hitTarget);
- }
-
- private async Task ExecuteLongPress(
- MouseUiSimulationCommand parameters, EventSystem eventSystem, CancellationToken ct)
- {
- if (parameters.Duration <= 0f || float.IsNaN(parameters.Duration) || float.IsInfinity(parameters.Duration))
- {
- return new SimulateMouseUiResponse
- {
- Success = false,
- Message = $"Duration must be positive, got: {parameters.Duration}",
- Action = MouseAction.LongPress.ToString()
- };
- }
-
- Vector2 inputPos = new(parameters.X, parameters.Y);
- Vector2 screenPos = InputToScreen(inputPos);
- PointerEventData pointerData = MouseUiPointerTargetResolver.CreatePointerPressData(eventSystem, screenPos, parameters.Button);
- ResolvedPointerTargets resolvedTargets =
- MouseUiPointerTargetResolver.ResolvePressablePointerTargets(parameters, eventSystem, inputPos, screenPos, pointerData, MouseAction.LongPress);
- if (resolvedTargets.FailureResponse != null)
- {
- return resolvedTargets.FailureResponse;
- }
-
- if (parameters.BypassRaycast && resolvedTargets.Target == null)
- {
- return new SimulateMouseUiResponse
- {
- Success = false,
- Message = $"TargetPath '{parameters.TargetPath}' has no pointer down or pointer click handler.",
- Action = MouseAction.LongPress.ToString(),
- PositionX = inputPos.x,
- PositionY = inputPos.y
- };
- }
-
- string? targetName = resolvedTargets.Target?.name;
- bool hitTarget = resolvedTargets.Target != null;
- bool shouldReleasePointer = resolvedTargets.RawTarget != null && resolvedTargets.Target != null;
- SimulateMouseUiOverlayState.Update(
- MouseAction.LongPress, inputPos, null,
- targetName, Handles.GetMainGameViewSize());
-
- bool expandCompleted = await MouseUiOverlayAnimator.PlayExpandAnimation(ct).ConfigureAwait(false);
- if (!expandCompleted)
- {
- _mainThreadCleanupScheduler.QueueOverlayClear();
- return MouseUiSimulationResponseFactory.CreateFrameTimeoutResult(MouseAction.LongPress, inputPos, null, targetName);
- }
- await MainThreadSwitcher.SwitchToMainThread(ct);
-
- ExecuteLongPressPointerDown(resolvedTargets, pointerData);
-
- try
- {
- // Hold for Duration seconds, updating elapsed time each frame for overlay display
- float startTime = Time.realtimeSinceStartup;
- float elapsed = 0f;
- while (elapsed < parameters.Duration)
- {
- SimulateMouseUiOverlayState.UpdateLongPressElapsed(elapsed);
- bool frameReady = await MouseUiEditorFrameWaiter.WaitForEditorFrameAndSwitchToMainThreadAsync(ct).ConfigureAwait(false);
- if (!frameReady)
- {
- _mainThreadCleanupScheduler.QueueOverlayClear();
- return MouseUiSimulationResponseFactory.CreateFrameTimeoutResult(MouseAction.LongPress, inputPos, null, targetName);
- }
- await MainThreadSwitcher.SwitchToMainThread(ct);
- elapsed = Time.realtimeSinceStartup - startTime;
- }
- SimulateMouseUiOverlayState.UpdateLongPressElapsed(parameters.Duration);
- }
- finally
- {
- // Ensure pointerUp fires even if the hold loop is cancelled
- if (shouldReleasePointer)
- {
- _mainThreadCleanupScheduler.ExecuteCleanupOnMainThread(
- () => ExecuteEvents.Execute(resolvedTargets.Target!, pointerData, ExecuteEvents.pointerUpHandler));
- }
- }
-
- bool dissipateCompleted = await MouseUiOverlayAnimator.PlayDissipateAnimation(ct).ConfigureAwait(false);
- if (!dissipateCompleted)
- {
- _mainThreadCleanupScheduler.QueueOverlayClear();
- return MouseUiSimulationResponseFactory.CreateLongPressResult(parameters, inputPos, targetName, hitTarget);
- }
- await MainThreadSwitcher.SwitchToMainThread(ct);
-
- return MouseUiSimulationResponseFactory.CreateLongPressResult(parameters, inputPos, targetName, hitTarget);
- }
-
- private static void ExecutePointerClickEvents(
- ResolvedPointerTargets resolvedTargets,
- PointerEventData pointerData)
- {
- if (resolvedTargets.RawTarget == null)
- {
- return;
- }
-
- if (resolvedTargets.PressTarget != null)
- {
- ExecuteEvents.ExecuteHierarchy(
- resolvedTargets.RawTarget,
- pointerData,
- ExecuteEvents.pointerDownHandler);
- }
-
- if (resolvedTargets.Target != null)
- {
- ExecuteEvents.Execute(
- resolvedTargets.Target,
- pointerData,
- ExecuteEvents.pointerUpHandler);
- }
-
- if (resolvedTargets.ClickTarget != null)
- {
- ExecuteEvents.Execute(
- resolvedTargets.ClickTarget,
- pointerData,
- ExecuteEvents.pointerClickHandler);
- }
- }
-
- private static void ExecuteLongPressPointerDown(
- ResolvedPointerTargets resolvedTargets,
- PointerEventData pointerData)
- {
- if (resolvedTargets.RawTarget == null || resolvedTargets.Target == null)
- {
- return;
- }
-
- ExecuteEvents.ExecuteHierarchy(
- resolvedTargets.RawTarget,
- pointerData,
- ExecuteEvents.pointerDownHandler);
- }
-
private PointerEventData InitiateDrag(
EventSystem eventSystem,
Vector2 screenPos,
@@ -354,8 +153,8 @@ private async Task ExecuteDragOneShot(
{
Vector2 inputStart = new(parameters.FromX, parameters.FromY);
Vector2 inputEnd = new(parameters.X, parameters.Y);
- Vector2 screenStart = InputToScreen(inputStart);
- Vector2 screenEnd = InputToScreen(inputEnd);
+ Vector2 screenStart = MouseUiCoordinateConverter.InputToScreen(inputStart);
+ Vector2 screenEnd = MouseUiCoordinateConverter.InputToScreen(inputEnd);
RaycastResult? hit = parameters.BypassRaycast ? null : UiRaycastHelper.RaycastUI(screenStart, eventSystem);
RaycastResult startRaycast = new();
GameObject? rawTarget = null;
@@ -547,7 +346,7 @@ private async Task InterpolateDragPosition(
pointerData.delta = endPos - previousPosition;
ExecuteEvents.Execute(target, pointerData, ExecuteEvents.dragHandler);
- SimulateMouseUiOverlayState.UpdatePosition(ScreenToInput(endPos));
+ SimulateMouseUiOverlayState.UpdatePosition(MouseUiCoordinateConverter.ScreenToInput(endPos));
return true;
}
@@ -573,7 +372,7 @@ private async Task InterpolateDragPosition(
ExecuteEvents.Execute(target, pointerData, ExecuteEvents.dragHandler);
- SimulateMouseUiOverlayState.UpdatePosition(ScreenToInput(currentPosition));
+ SimulateMouseUiOverlayState.UpdatePosition(MouseUiCoordinateConverter.ScreenToInput(currentPosition));
}
while (t < 1.0f);
@@ -596,7 +395,7 @@ private async Task ExecuteDragStart(
}
Vector2 inputPos = new(parameters.X, parameters.Y);
- Vector2 screenPos = InputToScreen(inputPos);
+ Vector2 screenPos = MouseUiCoordinateConverter.InputToScreen(inputPos);
RaycastResult? hit = parameters.BypassRaycast ? null : UiRaycastHelper.RaycastUI(screenPos, eventSystem);
RaycastResult startRaycast = new();
GameObject? rawTarget = null;
@@ -730,14 +529,14 @@ private async Task ExecuteDragMove(
}
Vector2 inputEnd = new(parameters.X, parameters.Y);
- Vector2 screenEnd = InputToScreen(inputEnd);
+ Vector2 screenEnd = MouseUiCoordinateConverter.InputToScreen(inputEnd);
PointerEventData pointerData = MouseDragState.PointerData!;
GameObject target = MouseDragState.Target!;
string targetName = target.name;
SimulateMouseUiOverlayState.Update(
MouseAction.DragMove,
- ScreenToInput(pointerData.position),
+ MouseUiCoordinateConverter.ScreenToInput(pointerData.position),
SimulateMouseUiOverlayState.DragStartPosition,
targetName, Handles.GetMainGameViewSize());
@@ -790,7 +589,7 @@ private async Task ExecuteDragEnd(
}
Vector2 inputEnd = new(parameters.X, parameters.Y);
- Vector2 screenEnd = InputToScreen(inputEnd);
+ Vector2 screenEnd = MouseUiCoordinateConverter.InputToScreen(inputEnd);
PointerEventData pointerData = MouseDragState.PointerData!;
GameObject target = MouseDragState.Target!;
string targetName = target.name;
@@ -808,7 +607,7 @@ private async Task ExecuteDragEnd(
SimulateMouseUiOverlayState.Update(
MouseAction.DragEnd,
- ScreenToInput(pointerData.position),
+ MouseUiCoordinateConverter.ScreenToInput(pointerData.position),
SimulateMouseUiOverlayState.DragStartPosition,
targetName, Handles.GetMainGameViewSize());