From 603037e4d016968267ef23646f7cb5ccb8d8e0bc Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Sun, 31 Mar 2024 21:10:38 +0900 Subject: [PATCH 1/2] Add CreateInteractableComponent(MonoBehaviour) and make constructor to internal --- Runtime/InteractiveComponent.cs | 36 ++++++++++++++++++----- Runtime/InteractiveComponentCollector.cs | 2 +- Tests/Runtime/InteractiveComponentTest.cs | 2 +- Tests/Runtime/MonkeyTest.cs | 12 ++++---- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Runtime/InteractiveComponent.cs b/Runtime/InteractiveComponent.cs index 9d0364a..f46dc39 100644 --- a/Runtime/InteractiveComponent.cs +++ b/Runtime/InteractiveComponent.cs @@ -48,21 +48,42 @@ private readonly Func, PointerEventData, L private readonly PointerEventData _eventData = new PointerEventData(EventSystem.current); private readonly List _results = new List(); + internal InteractiveComponent(MonoBehaviour component, + Func getScreenPoint = null, + Func, PointerEventData, List, bool> isReachable = null) + { + this.component = component; + _getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; + _isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + } + /// - /// Constructor + /// Create InteractableComponent instance from MonoBehaviour. /// /// /// The function returns the screen position where raycast for the found GameObject. /// Default is DefaultScreenPointStrategy.GetScreenPoint. /// The function returns the GameObject is reachable from user or not. /// Default is DefaultReachableStrategy.IsReachable. - public InteractiveComponent(MonoBehaviour component, + /// The function returns the Component is interactable or not. + /// Default is DefaultComponentInteractableStrategy.IsInteractable. + /// Returns new InteractableComponent instance from MonoBehaviour. If MonoBehaviour is not interactable so, return null. + public static InteractiveComponent CreateInteractableComponent(MonoBehaviour component, Func getScreenPoint = null, - Func, PointerEventData, List, bool> isReachable = null) + Func, PointerEventData, List, bool> isReachable = null, + Func isComponentInteractable = null) { - this.component = component; - _getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; - _isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; + isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + isComponentInteractable = isComponentInteractable ?? DefaultComponentInteractableStrategy.IsInteractable; + + if (isComponentInteractable.Invoke(component)) + { + return new InteractiveComponent(component, getScreenPoint, isReachable); + } + + Debug.LogWarning($"Component `{component}` is not interactable."); + return null; } /// @@ -82,8 +103,8 @@ public static InteractiveComponent CreateInteractableComponent(GameObject gameOb Func isComponentInteractable = null) { getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; - isComponentInteractable = isComponentInteractable ?? DefaultComponentInteractableStrategy.IsInteractable; isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + isComponentInteractable = isComponentInteractable ?? DefaultComponentInteractableStrategy.IsInteractable; foreach (var component in gameObject.GetComponents()) { @@ -93,6 +114,7 @@ public static InteractiveComponent CreateInteractableComponent(GameObject gameOb } } + Debug.LogWarning($"GameObject `{gameObject}` has not interactable component."); return null; } diff --git a/Runtime/InteractiveComponentCollector.cs b/Runtime/InteractiveComponentCollector.cs index 0924e18..ee63c76 100644 --- a/Runtime/InteractiveComponentCollector.cs +++ b/Runtime/InteractiveComponentCollector.cs @@ -58,7 +58,7 @@ public IEnumerable FindInteractableComponents() { if (_isInteractable.Invoke(component)) { - yield return new InteractiveComponent(component, + yield return InteractiveComponent.CreateInteractableComponent(component, _getScreenPoint, _isReachable); } diff --git a/Tests/Runtime/InteractiveComponentTest.cs b/Tests/Runtime/InteractiveComponentTest.cs index 3c03c1d..c581a95 100644 --- a/Tests/Runtime/InteractiveComponentTest.cs +++ b/Tests/Runtime/InteractiveComponentTest.cs @@ -47,7 +47,7 @@ public void Fields() { var gameObject = GameObject.Find("UsingEventTrigger"); var component = gameObject.GetComponent(); - var sut = new InteractiveComponent(component); + var sut = InteractiveComponent.CreateInteractableComponent(component); Assert.That(sut.component, Is.EqualTo(component)); Assert.That(sut.gameObject, Is.EqualTo(gameObject)); diff --git a/Tests/Runtime/MonkeyTest.cs b/Tests/Runtime/MonkeyTest.cs index afba53b..6ccc4bd 100644 --- a/Tests/Runtime/MonkeyTest.cs +++ b/Tests/Runtime/MonkeyTest.cs @@ -206,13 +206,13 @@ public void Lottery_hitNotInteractiveComponent_returnNextLotteryComponent() { var components = new List() { - new InteractiveComponent( + InteractiveComponent.CreateInteractableComponent( GameObject.Find("UsingOnPointerClickHandler").GetComponent()), - new InteractiveComponent( + InteractiveComponent.CreateInteractableComponent( GameObject.Find("UsingPointerClickEventTrigger").GetComponent()), - new InteractiveComponent( + InteractiveComponent.CreateInteractableComponent( GameObject.Find("UsingOnPointerDownUpHandler").GetComponent()), - new InteractiveComponent( + InteractiveComponent.CreateInteractableComponent( GameObject.Find("UsingPointerDownUpEventTrigger").GetComponent()), }; components[0].gameObject.SetActive(false); @@ -231,7 +231,7 @@ public void Lottery_noInteractiveComponent_returnNull() { var components = new List() { - new InteractiveComponent( + InteractiveComponent.CreateInteractableComponent( GameObject.Find("UsingOnPointerClickHandler").GetComponent()), }; components[0].gameObject.SetActive(false); @@ -249,7 +249,7 @@ public void Lottery_withIgnoreAnnotation_returnNull() { var components = new List() { - new InteractiveComponent( + InteractiveComponent.CreateInteractableComponent( GameObject.Find("UsingMultipleEventTriggers").GetComponent()), }; components[0].gameObject.AddComponent(); From 7bfd08f76f59643eb35eac1946f2b2645801dd8c Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Sun, 31 Mar 2024 22:04:48 +0900 Subject: [PATCH 2/2] Obsolate CreateInteractableComponent(GameObject) --- Runtime/InteractiveComponent.cs | 1 + Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs | 13 ++++++++++--- Tests/Runtime/InteractiveComponentTest.cs | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Runtime/InteractiveComponent.cs b/Runtime/InteractiveComponent.cs index f46dc39..d30c3c3 100644 --- a/Runtime/InteractiveComponent.cs +++ b/Runtime/InteractiveComponent.cs @@ -97,6 +97,7 @@ public static InteractiveComponent CreateInteractableComponent(MonoBehaviour com /// The function returns the Component is interactable or not. /// Default is DefaultComponentInteractableStrategy.IsInteractable. /// Returns new InteractableComponent instance from GameObject. If GameObject is not interactable so, return null. + [Obsolete("Obsolete due to non-deterministic behavior when GameObject has multiple interactable components.")] public static InteractiveComponent CreateInteractableComponent(GameObject gameObject, Func getScreenPoint = null, Func, PointerEventData, List, bool> isReachable = null, diff --git a/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs b/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs index 3aba08a..8c463d3 100644 --- a/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs +++ b/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using NUnit.Framework; using TestHelper.Attributes; +using UnityEngine.UI; namespace TestHelper.Monkey.Samples.UGUIDemo { @@ -25,17 +26,23 @@ public async Task OpenSubScreens(string target) // When click Start button, then open Home screen. var startButton = await _finder.FindByNameAsync("StartButton", interactable: true); - InteractiveComponent.CreateInteractableComponent(startButton).Click(); + var startComponent = InteractiveComponent.CreateInteractableComponent(startButton.GetComponent