diff --git a/Assets/Scenes/Levels/Quarry.unity b/Assets/Scenes/Levels/Quarry.unity index 673cb870..9e8349f1 100644 --- a/Assets/Scenes/Levels/Quarry.unity +++ b/Assets/Scenes/Levels/Quarry.unity @@ -438175,6 +438175,50 @@ Transform: m_CorrespondingSourceObject: {fileID: 5145306031820616614, guid: fbbe1f4baf226904b96f839fe0c00181, type: 3} m_PrefabInstance: {fileID: 1352048898} m_PrefabAsset: {fileID: 0} +--- !u!1 &1360662869 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1360662870} + - component: {fileID: 1360662871} + m_Layer: 0 + m_Name: TestObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1360662870 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1360662869} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.45709, y: -0.24522, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1360662871 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1360662869} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d086a8fb5e4cfc047a52b859f91fb867, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1001 &1363194738 PrefabInstance: m_ObjectHideFlags: 0 @@ -445420,3 +445464,4 @@ SceneRoots: - {fileID: 122256018} - {fileID: 1101333109} - {fileID: 4912039252317080710} + - {fileID: 1360662870} diff --git a/Assets/Scripts/Input/InputManager.cs b/Assets/Scripts/Input/InputManager.cs index bf8081d9..e244a232 100644 --- a/Assets/Scripts/Input/InputManager.cs +++ b/Assets/Scripts/Input/InputManager.cs @@ -1,175 +1,234 @@ -using UnityEngine; +using System; +using UnityEngine; using UnityEngine.InputSystem; +using UnityEngine.SceneManagement; -/// -/// Handles input events and dispatches them to the appropriate ITouchInputConsumer. -/// Supports tap and hold/drag logic, with interactable delegation and debug logging. -/// -public class InputManager : MonoBehaviour +namespace Input { - private static InputManager _instance; - private static bool _isQuitting = false; - - public static InputManager Instance + public enum InputMode { - get + Game, + UI, + GameAndUI, + InputDisabled + } + + /// + /// Handles input events and dispatches them to the appropriate ITouchInputConsumer. + /// Supports tap and hold/drag logic, with interactable delegation and debug logging. + /// + public class InputManager : MonoBehaviour + { + private const string UiActions = "UI"; + private const string GameActions = "PlayerTouch"; + + private static InputManager _instance; + private static bool _isQuitting = false; + + public static InputManager Instance { - if (_instance == null && Application.isPlaying && !_isQuitting) + get { - _instance = FindAnyObjectByType(); - if (_instance == null) + if (_instance == null && Application.isPlaying && !_isQuitting) { - var go = new GameObject("InputManager"); - _instance = go.AddComponent(); - // DontDestroyOnLoad(go); + _instance = FindAnyObjectByType(); + if (_instance == null) + { + var go = new GameObject("InputManager"); + _instance = go.AddComponent(); + // DontDestroyOnLoad(go); + } } + return _instance; } - return _instance; } - } - private PlayerInput playerInput; - private InputAction tapMoveAction; - private InputAction holdMoveAction; - private InputAction positionAction; - private ITouchInputConsumer defaultConsumer; - private bool isHoldActive; + private PlayerInput playerInput; + private InputAction tapMoveAction; + private InputAction holdMoveAction; + private InputAction positionAction; + private ITouchInputConsumer defaultConsumer; + private bool isHoldActive; - void Awake() - { - _instance = this; - // DontDestroyOnLoad(gameObject); - playerInput = GetComponent(); - if (playerInput == null) + void Awake() { - Debug.LogError("[InputManager] InputManager requires a PlayerInput component attached to the same GameObject."); - return; + _instance = this; + // DontDestroyOnLoad(gameObject); + playerInput = GetComponent(); + if (playerInput == null) + { + Debug.LogError("[InputManager] InputManager requires a PlayerInput component attached to the same GameObject."); + return; + } + tapMoveAction = playerInput.actions.FindAction("TapMove", false); + holdMoveAction = playerInput.actions.FindAction("HoldMove", false); + positionAction = playerInput.actions.FindAction("TouchPosition", false); } - tapMoveAction = playerInput.actions.FindAction("TapMove", false); - holdMoveAction = playerInput.actions.FindAction("HoldMove", false); - positionAction = playerInput.actions.FindAction("TouchPosition", false); - } - void OnEnable() - { - if (tapMoveAction != null) - tapMoveAction.performed += OnTapMovePerformed; - if (holdMoveAction != null) + private void Start() { - holdMoveAction.performed += OnHoldMoveStarted; - holdMoveAction.canceled += OnHoldMoveCanceled; + SceneManagerService.Instance.SceneLoadCompleted += SwitchInputOnSceneLoaded; + SwitchInputOnSceneLoaded(SceneManager.GetActiveScene().name); } - } - void OnDisable() - { - if (tapMoveAction != null) - tapMoveAction.performed -= OnTapMovePerformed; - if (holdMoveAction != null) + private void SwitchInputOnSceneLoaded(string sceneName) { - holdMoveAction.performed -= OnHoldMoveStarted; - holdMoveAction.canceled -= OnHoldMoveCanceled; + if (sceneName.ToLower().Contains("mainmenu")) + { + Debug.Log("[InputManager] SwitchInputOnSceneLoaded - Setting InputMode to UI for MainMenu"); + SetInputMode(InputMode.UI); + } + else + { + Debug.Log("[InputManager] SwitchInputOnSceneLoaded - Setting InputMode to PlayerTouch"); + SetInputMode(InputMode.Game); + } } - } - void OnApplicationQuit() - { - _isQuitting = true; - } - - /// - /// Sets the default ITouchInputConsumer to receive input events. - /// - public void SetDefaultConsumer(ITouchInputConsumer consumer) - { - defaultConsumer = consumer; - } - - /// - /// Handles tap input, delegates to interactable if present, otherwise to default consumer. - /// - private void OnTapMovePerformed(InputAction.CallbackContext ctx) - { - Vector2 screenPos = positionAction.ReadValue(); - Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); - Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); - Debug.Log($"[InputManager] TapMove performed at {worldPos2D}"); - if (!TryDelegateToInteractable(worldPos2D)) + public void SetInputMode(InputMode inputMode) { - Debug.Log("[InputManager] No interactable found, forwarding tap to default consumer"); - defaultConsumer?.OnTap(worldPos2D); + switch (inputMode) + { + case InputMode.UI: + playerInput.actions.FindActionMap(UiActions).Enable(); + playerInput.actions.FindActionMap(GameActions).Disable(); + break; + case InputMode.Game: + playerInput.actions.FindActionMap(UiActions).Disable(); + playerInput.actions.FindActionMap(GameActions).Enable(); + break; + case InputMode.GameAndUI: + playerInput.actions.FindActionMap(UiActions).Enable(); + playerInput.actions.FindActionMap(GameActions).Enable(); + break; + case InputMode.InputDisabled: + playerInput.actions.FindActionMap(UiActions).Disable(); + playerInput.actions.FindActionMap(GameActions).Disable(); + break; + } } - else + + void OnEnable() { - Debug.Log("[InputManager] Tap delegated to interactable"); + if (tapMoveAction != null) + tapMoveAction.performed += OnTapMovePerformed; + if (holdMoveAction != null) + { + holdMoveAction.performed += OnHoldMoveStarted; + holdMoveAction.canceled += OnHoldMoveCanceled; + } } - } - /// - /// Handles the start of a hold input. - /// - private void OnHoldMoveStarted(InputAction.CallbackContext ctx) - { - isHoldActive = true; - Vector2 screenPos = positionAction.ReadValue(); - Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); - Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); - Debug.Log($"[InputManager] HoldMove started at {worldPos2D}"); - defaultConsumer?.OnHoldStart(worldPos2D); - } + void OnDisable() + { + if (tapMoveAction != null) + tapMoveAction.performed -= OnTapMovePerformed; + if (holdMoveAction != null) + { + holdMoveAction.performed -= OnHoldMoveStarted; + holdMoveAction.canceled -= OnHoldMoveCanceled; + } + } - /// - /// Handles the end of a hold input. - /// - private void OnHoldMoveCanceled(InputAction.CallbackContext ctx) - { - if (!isHoldActive) return; - isHoldActive = false; - Vector2 screenPos = positionAction.ReadValue(); - Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); - Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); - Debug.Log($"[InputManager] HoldMove canceled at {worldPos2D}"); - defaultConsumer?.OnHoldEnd(worldPos2D); - } + void OnApplicationQuit() + { + _isQuitting = true; + } - /// - /// Continuously updates hold move input while active. - /// - void Update() - { - if (isHoldActive && holdMoveAction != null && holdMoveAction.phase == InputActionPhase.Performed) + /// + /// Sets the default ITouchInputConsumer to receive input events. + /// + public void SetDefaultConsumer(ITouchInputConsumer consumer) + { + defaultConsumer = consumer; + } + + /// + /// Handles tap input, delegates to interactable if present, otherwise to default consumer. + /// + private void OnTapMovePerformed(InputAction.CallbackContext ctx) { Vector2 screenPos = positionAction.ReadValue(); Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); - // Debug.Log($"[InputManager] HoldMove update at {worldPos2D}"); - defaultConsumer?.OnHoldMove(worldPos2D); - } - } - - /// - /// Attempts to delegate a tap to an interactable at the given world position. - /// Traces on the "Interactable" channel and logs detailed info. - /// - private bool TryDelegateToInteractable(Vector2 worldPos) - { - LayerMask mask = GameManager.Instance != null ? GameManager.Instance.InteractableLayerMask : -1; - Collider2D hit = Physics2D.OverlapPoint(worldPos, mask); - if (hit != null) - { - var consumer = hit.GetComponent(); - if (consumer != null) + Debug.Log($"[InputManager] TapMove performed at {worldPos2D}"); + if (!TryDelegateToInteractable(worldPos2D)) { - Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})"); - consumer.OnTap(worldPos); - return true; + Debug.Log("[InputManager] No interactable found, forwarding tap to default consumer"); + defaultConsumer?.OnTap(worldPos2D); + } + else + { + Debug.Log("[InputManager] Tap delegated to interactable"); } - Debug.unityLogger.Log("Interactable", $"[InputManager] Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found."); } - else + + /// + /// Handles the start of a hold input. + /// + private void OnHoldMoveStarted(InputAction.CallbackContext ctx) { - Debug.unityLogger.Log("Interactable", $"[InputManager] No Collider2D found at {worldPos} for interactable delegation."); + isHoldActive = true; + Vector2 screenPos = positionAction.ReadValue(); + Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); + Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); + Debug.Log($"[InputManager] HoldMove started at {worldPos2D}"); + defaultConsumer?.OnHoldStart(worldPos2D); + } + + /// + /// Handles the end of a hold input. + /// + private void OnHoldMoveCanceled(InputAction.CallbackContext ctx) + { + if (!isHoldActive) return; + isHoldActive = false; + Vector2 screenPos = positionAction.ReadValue(); + Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); + Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); + Debug.Log($"[InputManager] HoldMove canceled at {worldPos2D}"); + defaultConsumer?.OnHoldEnd(worldPos2D); + } + + /// + /// Continuously updates hold move input while active. + /// + void Update() + { + if (isHoldActive && holdMoveAction != null && holdMoveAction.phase == InputActionPhase.Performed) + { + Vector2 screenPos = positionAction.ReadValue(); + Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); + Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); + // Debug.Log($"[InputManager] HoldMove update at {worldPos2D}"); + defaultConsumer?.OnHoldMove(worldPos2D); + } + } + + /// + /// Attempts to delegate a tap to an interactable at the given world position. + /// Traces on the "Interactable" channel and logs detailed info. + /// + private bool TryDelegateToInteractable(Vector2 worldPos) + { + LayerMask mask = GameManager.Instance != null ? GameManager.Instance.InteractableLayerMask : -1; + Collider2D hit = Physics2D.OverlapPoint(worldPos, mask); + if (hit != null) + { + var consumer = hit.GetComponent(); + if (consumer != null) + { + Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})"); + consumer.OnTap(worldPos); + return true; + } + Debug.unityLogger.Log("Interactable", $"[InputManager] Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found."); + } + else + { + Debug.unityLogger.Log("Interactable", $"[InputManager] No Collider2D found at {worldPos} for interactable delegation."); + } + return false; } - return false; } } diff --git a/Assets/Scripts/LevelS/LevelSwitch.cs b/Assets/Scripts/LevelS/LevelSwitch.cs index cbc29ff6..36d39fc5 100644 --- a/Assets/Scripts/LevelS/LevelSwitch.cs +++ b/Assets/Scripts/LevelS/LevelSwitch.cs @@ -96,6 +96,9 @@ public class LevelSwitch : MonoBehaviour // Setup menu with data and callbacks menu.Setup(switchData, OnMenuConfirm, OnMenuCancel); _isActive = false; // Prevent re-triggering until menu is closed + + // Switch input mode to UI only + InputManager.Instance.SetInputMode(InputMode.UI); } private async void OnMenuConfirm() diff --git a/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs b/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs index 9c3fa3cf..5a974a54 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs @@ -1,5 +1,6 @@ using UnityEngine; using AppleHills.Core.Settings; +using Input; namespace Minigames.DivingForPictures { diff --git a/Assets/Scripts/Test.meta b/Assets/Scripts/Test.meta new file mode 100644 index 00000000..f10bb29a --- /dev/null +++ b/Assets/Scripts/Test.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23fdb60880dd05846a6e0d3681a02242 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/DivingMinigameSettings.asset b/Assets/Settings/DivingMinigameSettings.asset index 766926f6..58d56dd8 100644 --- a/Assets/Settings/DivingMinigameSettings.asset +++ b/Assets/Settings/DivingMinigameSettings.asset @@ -31,7 +31,7 @@ MonoBehaviour: surfacingSpawnDelay: 5 initialTileCount: 3 tileSpawnBuffer: 1 - moveSpeed: 2 + moveSpeed: 1 speedUpFactor: 0 speedUpInterval: 10 maxMoveSpeed: 12