560 lines
18 KiB
C#
560 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using BriarQueen.Framework.Coordinators.Events;
|
|
using BriarQueen.Framework.Events.Gameplay;
|
|
using BriarQueen.Framework.Events.Input;
|
|
using BriarQueen.Framework.Events.UI;
|
|
using BriarQueen.Framework.Managers.UI;
|
|
using BriarQueen.Framework.Services.Game;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.InputSystem.UI;
|
|
using VContainer;
|
|
|
|
namespace BriarQueen.Framework.Managers.Input
|
|
{
|
|
public enum DeviceInputType
|
|
{
|
|
KeyboardAndMouse,
|
|
XboxController,
|
|
PlaystationController,
|
|
SwitchProController
|
|
}
|
|
|
|
public class InputManager : MonoBehaviour, IDisposable, IManager
|
|
{
|
|
[Header("Input")]
|
|
[SerializeField]
|
|
private PlayerInput _playerInput;
|
|
|
|
[Header("Virtual Cursor")]
|
|
[SerializeField]
|
|
private float _controllerCursorSpeed = 1200f;
|
|
|
|
[SerializeField]
|
|
private bool _clampCursorToScreen = true;
|
|
|
|
private readonly Dictionary<string, InputAction> _cachedByName = new();
|
|
|
|
private InputAction _clickAction;
|
|
private InputAction _codexAction;
|
|
private bool _codexShown;
|
|
private bool _toolScreenShown;
|
|
|
|
private GameService _gameService;
|
|
private EventCoordinator _eventCoordinator;
|
|
private InputAction _hideHudAction;
|
|
private bool _hudHidden;
|
|
|
|
private bool _initialized;
|
|
private bool _isPaused;
|
|
private InputAction _pauseAction;
|
|
|
|
private InputAction _pointAction;
|
|
private InputAction _rightClickAction;
|
|
private InputAction _openToolsAction;
|
|
private InputAction _nextToolAction;
|
|
private InputAction _previousToolAction;
|
|
private InputAction _nextItemAction;
|
|
private InputAction _previousItemAction;
|
|
private InputAction _virtualMouseAction;
|
|
private InputAction _submitAction;
|
|
|
|
private UICursorService _uiCursorService;
|
|
|
|
private Vector2 _controllerCursorInput;
|
|
|
|
public Vector2 PointerPosition { get; private set; }
|
|
|
|
public DeviceInputType DeviceInputType { get; private set; }
|
|
|
|
public string ActiveActionMap => _playerInput != null && _playerInput.currentActionMap != null
|
|
? _playerInput.currentActionMap.name
|
|
: string.Empty;
|
|
|
|
public bool Initialized => _initialized;
|
|
|
|
public bool IsPaused => _isPaused;
|
|
|
|
public bool UsingControllerCursor => DeviceInputType != DeviceInputType.KeyboardAndMouse;
|
|
|
|
private void Awake()
|
|
{
|
|
PointerPosition = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!_initialized)
|
|
return;
|
|
|
|
UpdateControllerCursor();
|
|
|
|
if (_uiCursorService != null && UsingControllerCursor)
|
|
_uiCursorService.SetVirtualCursorPosition(PointerPosition);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!_initialized)
|
|
return;
|
|
|
|
if (_eventCoordinator != null)
|
|
{
|
|
_eventCoordinator.Unsubscribe<UIToggleHudEvent>(OnHudStateChanged);
|
|
_eventCoordinator.Unsubscribe<ToggleCodexEvent>(OnCodexStateChanged);
|
|
_eventCoordinator.Unsubscribe<ToggleToolScreenEvent>(OnToolScreenStateChanged);
|
|
}
|
|
|
|
UnbindCoreInputs();
|
|
_initialized = false;
|
|
}
|
|
|
|
[Inject]
|
|
public void Construct(
|
|
EventCoordinator eventCoordinator,
|
|
UICursorService uiCursorService,
|
|
GameService gameService)
|
|
{
|
|
_eventCoordinator = eventCoordinator;
|
|
_uiCursorService = uiCursorService;
|
|
_gameService = gameService;
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
Debug.Log("[InputManager] Initialize called");
|
|
|
|
if (_initialized)
|
|
{
|
|
Debug.Log("[InputManager] Already initialized");
|
|
return;
|
|
}
|
|
|
|
if (_eventCoordinator == null)
|
|
{
|
|
Debug.LogWarning("[InputManager] EventCoordinator is null");
|
|
return;
|
|
}
|
|
|
|
if (_playerInput == null)
|
|
{
|
|
Debug.LogWarning("[InputManager] PlayerInput is null");
|
|
return;
|
|
}
|
|
|
|
if (_playerInput.actions == null)
|
|
{
|
|
Debug.LogWarning("[InputManager] PlayerInput.actions is null");
|
|
return;
|
|
}
|
|
|
|
Debug.Log($"[InputManager] Current map before cache: {ActiveActionMap}");
|
|
|
|
CacheActions();
|
|
|
|
Debug.Log($"[InputManager] Point action: {_pointAction}");
|
|
Debug.Log($"[InputManager] Click action: {_clickAction}");
|
|
Debug.Log($"[InputManager] Virtual_Mouse action: {_virtualMouseAction}");
|
|
|
|
BindCoreInputs();
|
|
|
|
DeviceInputType = GetDeviceInputType(_playerInput);
|
|
ApplyCursorModeForCurrentScheme();
|
|
|
|
_initialized = true;
|
|
|
|
Debug.Log("[InputManager] Initialization complete");
|
|
}
|
|
|
|
private void CacheActions()
|
|
{
|
|
_cachedByName.Clear();
|
|
|
|
_pointAction = CacheAction("Point");
|
|
_virtualMouseAction = CacheAction("Virtual_Mouse");
|
|
_pauseAction = CacheAction("Pause");
|
|
_clickAction = CacheAction("Click");
|
|
_rightClickAction = CacheAction("Right_Click");
|
|
_hideHudAction = CacheAction("Hide_HUD");
|
|
_codexAction = CacheAction("Codex");
|
|
_openToolsAction = CacheAction("Show_Tools");
|
|
_nextToolAction = CacheAction("Next_Tool");
|
|
_previousToolAction = CacheAction("Previous_Tool");
|
|
_nextItemAction = CacheAction("Next_Item");
|
|
_previousItemAction = CacheAction("Previous_Item");
|
|
_submitAction = CacheAction("Submit");
|
|
}
|
|
|
|
private InputAction CacheAction(string actionName)
|
|
{
|
|
var action = GetAction(actionName);
|
|
|
|
if (action != null && !string.IsNullOrWhiteSpace(action.name))
|
|
_cachedByName[action.name] = action;
|
|
|
|
return action;
|
|
}
|
|
|
|
private void BindCoreInputs()
|
|
{
|
|
if (_pointAction != null)
|
|
{
|
|
Debug.Log("[InputManager] Binding Point");
|
|
|
|
_pointAction.performed += OnPoint;
|
|
_pointAction.canceled += OnPoint;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("[InputManager] Required action 'Point' not found.");
|
|
}
|
|
|
|
if (_virtualMouseAction != null)
|
|
{
|
|
_virtualMouseAction.performed += OnVirtualMouse;
|
|
_virtualMouseAction.canceled += OnVirtualMouse;
|
|
}
|
|
|
|
if (_pauseAction != null)
|
|
_pauseAction.performed += OnPause;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Pause' not found.");
|
|
|
|
if (_clickAction != null)
|
|
_clickAction.performed += OnClick;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Click' not found.");
|
|
|
|
if (_rightClickAction != null)
|
|
_rightClickAction.performed += OnRightClick;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Right_Click' not found.");
|
|
|
|
if (_hideHudAction != null)
|
|
_hideHudAction.performed += OnHideHUD;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Hide_HUD' not found.");
|
|
|
|
if (_codexAction != null)
|
|
_codexAction.performed += OnCodex;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Codex' not found.");
|
|
|
|
if (_openToolsAction != null)
|
|
_openToolsAction.performed += OnOpenTools;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Show_Tools' not found.");
|
|
|
|
if (_nextToolAction != null)
|
|
_nextToolAction.performed += OnNextToolClicked;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Next_Tool' not found.");
|
|
|
|
if (_previousToolAction != null)
|
|
_previousToolAction.performed += OnPreviousToolClicked;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Previous_Tool' not found.");
|
|
|
|
if (_nextItemAction != null)
|
|
_nextItemAction.performed += OnNextItemClicked;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Next_Item' not found.");
|
|
|
|
if (_previousItemAction != null)
|
|
_previousItemAction.performed += OnPreviousItemClicked;
|
|
else
|
|
Debug.LogWarning("[InputManager] Action 'Previous_Item' not found.");
|
|
|
|
if (_playerInput != null)
|
|
_playerInput.onControlsChanged += OnControlsChanged;
|
|
}
|
|
|
|
private void UnbindCoreInputs()
|
|
{
|
|
if (_pointAction != null)
|
|
{
|
|
_pointAction.performed -= OnPoint;
|
|
_pointAction.canceled -= OnPoint;
|
|
}
|
|
|
|
if (_virtualMouseAction != null)
|
|
{
|
|
_virtualMouseAction.performed -= OnVirtualMouse;
|
|
_virtualMouseAction.canceled -= OnVirtualMouse;
|
|
}
|
|
|
|
if (_pauseAction != null)
|
|
_pauseAction.performed -= OnPause;
|
|
|
|
if (_clickAction != null)
|
|
_clickAction.performed -= OnClick;
|
|
|
|
if (_rightClickAction != null)
|
|
_rightClickAction.performed -= OnRightClick;
|
|
|
|
if (_hideHudAction != null)
|
|
_hideHudAction.performed -= OnHideHUD;
|
|
|
|
if (_codexAction != null)
|
|
_codexAction.performed -= OnCodex;
|
|
|
|
if (_openToolsAction != null)
|
|
_openToolsAction.performed -= OnOpenTools;
|
|
|
|
if (_nextToolAction != null)
|
|
_nextToolAction.performed -= OnNextToolClicked;
|
|
|
|
if (_previousToolAction != null)
|
|
_previousToolAction.performed -= OnPreviousToolClicked;
|
|
|
|
if (_nextItemAction != null)
|
|
_nextItemAction.performed -= OnNextItemClicked;
|
|
|
|
if (_previousItemAction != null)
|
|
_previousItemAction.performed -= OnPreviousItemClicked;
|
|
|
|
if (_playerInput != null)
|
|
_playerInput.onControlsChanged -= OnControlsChanged;
|
|
}
|
|
|
|
private void UpdateControllerCursor()
|
|
{
|
|
if (!UsingControllerCursor)
|
|
return;
|
|
|
|
if (_controllerCursorInput.sqrMagnitude <= 0.0001f)
|
|
return;
|
|
|
|
PointerPosition += _controllerCursorInput * (_controllerCursorSpeed * Time.unscaledDeltaTime);
|
|
|
|
if (_clampCursorToScreen)
|
|
{
|
|
PointerPosition = new Vector2(
|
|
Mathf.Clamp(PointerPosition.x, 0f, Screen.width),
|
|
Mathf.Clamp(PointerPosition.y, 0f, Screen.height)
|
|
);
|
|
}
|
|
}
|
|
|
|
private void OnControlsChanged(PlayerInput playerInput)
|
|
{ Debug.Log($"Controls changed. Scheme: {playerInput.currentControlScheme}");
|
|
DeviceInputType = GetDeviceInputType(playerInput);
|
|
ApplyCursorModeForCurrentScheme();
|
|
}
|
|
|
|
private void ApplyCursorModeForCurrentScheme()
|
|
{
|
|
if (_uiCursorService == null)
|
|
return;
|
|
|
|
var useVirtualCursor = UsingControllerCursor;
|
|
_uiCursorService.SetUseVirtualCursor(useVirtualCursor);
|
|
|
|
if (useVirtualCursor)
|
|
_uiCursorService.SetVirtualCursorPosition(PointerPosition);
|
|
}
|
|
|
|
public void BindPauseForSkip(Action<InputAction.CallbackContext> callback)
|
|
{
|
|
if (_pauseAction == null || callback == null)
|
|
return;
|
|
|
|
_pauseAction.performed -= OnPause;
|
|
_pauseAction.performed += callback;
|
|
}
|
|
|
|
public void ResetPauseBind(Action<InputAction.CallbackContext> callback)
|
|
{
|
|
if (_pauseAction == null || callback == null)
|
|
return;
|
|
|
|
_pauseAction.performed -= callback;
|
|
_pauseAction.performed -= OnPause;
|
|
_pauseAction.performed += OnPause;
|
|
}
|
|
|
|
public void BindSubmitForStart(Action<InputAction.CallbackContext> callback)
|
|
{
|
|
if (_submitAction == null || callback == null)
|
|
return;
|
|
|
|
_submitAction.performed += callback;
|
|
}
|
|
|
|
public void ResetSubmitBind(Action<InputAction.CallbackContext> callback)
|
|
{
|
|
if (_submitAction == null || callback == null)
|
|
return;
|
|
|
|
_submitAction.performed -= callback;
|
|
}
|
|
|
|
public void BindAction(string actionName, Action<InputAction.CallbackContext> callback)
|
|
{
|
|
if (callback == null)
|
|
return;
|
|
|
|
var action = GetCachedAction(actionName);
|
|
if (action == null)
|
|
{
|
|
Debug.LogWarning($"[InputManager] Action '{actionName}' not found.");
|
|
return;
|
|
}
|
|
|
|
action.performed -= callback;
|
|
action.performed += callback;
|
|
}
|
|
|
|
public void UnbindAction(string actionName, Action<InputAction.CallbackContext> callback)
|
|
{
|
|
if (callback == null)
|
|
return;
|
|
|
|
var action = GetCachedAction(actionName);
|
|
if (action == null)
|
|
{
|
|
Debug.LogWarning($"[InputManager] Action '{actionName}' not found.");
|
|
return;
|
|
}
|
|
|
|
action.performed -= callback;
|
|
}
|
|
|
|
private InputAction GetCachedAction(string actionName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(actionName))
|
|
return null;
|
|
|
|
if (_cachedByName.TryGetValue(actionName, out var cached))
|
|
return cached;
|
|
|
|
var action = GetAction(actionName);
|
|
if (action != null)
|
|
_cachedByName[actionName] = action;
|
|
|
|
return action;
|
|
}
|
|
|
|
private static DeviceInputType GetDeviceInputType(PlayerInput input)
|
|
{
|
|
if (input == null)
|
|
return DeviceInputType.KeyboardAndMouse;
|
|
|
|
return input.currentControlScheme switch
|
|
{
|
|
"Keyboard&Mouse" => DeviceInputType.KeyboardAndMouse,
|
|
"Xbox" => DeviceInputType.XboxController,
|
|
"Playstation" => DeviceInputType.PlaystationController,
|
|
"Switch Pro" => DeviceInputType.SwitchProController,
|
|
_ => DeviceInputType.KeyboardAndMouse
|
|
};
|
|
}
|
|
|
|
private void OnHudStateChanged(UIToggleHudEvent evt)
|
|
{
|
|
_hudHidden = !evt.Show;
|
|
}
|
|
|
|
private void OnCodexStateChanged(ToggleCodexEvent evt)
|
|
{
|
|
_codexShown = evt.Shown;
|
|
}
|
|
|
|
private void OnToolScreenStateChanged(ToggleToolScreenEvent evt)
|
|
{
|
|
_toolScreenShown = evt.Shown;
|
|
}
|
|
|
|
private void OnHideHUD(InputAction.CallbackContext ctx)
|
|
{
|
|
_hudHidden = !_hudHidden;
|
|
_eventCoordinator?.PublishImmediate(new UIToggleHudEvent(_hudHidden));
|
|
}
|
|
|
|
private void OnPause(InputAction.CallbackContext ctx)
|
|
{
|
|
if(_gameService.IsMainMenuSceneLoaded)
|
|
return;
|
|
|
|
_isPaused = !_isPaused;
|
|
_eventCoordinator?.Publish(new PauseButtonClickedEvent());
|
|
}
|
|
|
|
private void OnCodex(InputAction.CallbackContext ctx)
|
|
{
|
|
if(_gameService.IsMainMenuSceneLoaded)
|
|
return;
|
|
_codexShown = !_codexShown;
|
|
_eventCoordinator?.Publish(new ToggleCodexEvent(_codexShown));
|
|
}
|
|
|
|
private void OnClick(InputAction.CallbackContext ctx)
|
|
{
|
|
_eventCoordinator?.PublishImmediate(new OnClickEvent(ctx));
|
|
}
|
|
|
|
private void OnRightClick(InputAction.CallbackContext ctx)
|
|
{
|
|
_eventCoordinator?.PublishImmediate(new OnRightClickEvent(ctx));
|
|
}
|
|
|
|
private void OnPoint(InputAction.CallbackContext ctx)
|
|
{
|
|
PointerPosition = ctx.ReadValue<Vector2>();
|
|
}
|
|
|
|
private void OnVirtualMouse(InputAction.CallbackContext ctx)
|
|
{
|
|
_controllerCursorInput = ctx.ReadValue<Vector2>();
|
|
}
|
|
|
|
private void OnOpenTools(InputAction.CallbackContext ctx)
|
|
{
|
|
if(_gameService.IsMainMenuSceneLoaded)
|
|
return;
|
|
_toolScreenShown = !_toolScreenShown;
|
|
_eventCoordinator?.Publish(new ToggleToolScreenEvent(_toolScreenShown));
|
|
}
|
|
|
|
private void OnNextToolClicked(InputAction.CallbackContext ctx)
|
|
{
|
|
_eventCoordinator?.Publish(new OnNextToolChangedEvent());
|
|
}
|
|
|
|
private void OnPreviousToolClicked(InputAction.CallbackContext ctx)
|
|
{
|
|
_eventCoordinator?.Publish(new OnPreviousToolChangedEvent());
|
|
}
|
|
|
|
private void OnNextItemClicked(InputAction.CallbackContext ctx)
|
|
{
|
|
_eventCoordinator?.Publish(new OnNextItemClickedEvent());
|
|
}
|
|
|
|
private void OnPreviousItemClicked(InputAction.CallbackContext ctx)
|
|
{
|
|
_eventCoordinator?.Publish(new OnPreviousItemClickedEvent());
|
|
}
|
|
|
|
public InputAction GetAction(string actionName)
|
|
{
|
|
if (_playerInput == null || _playerInput.actions == null || string.IsNullOrWhiteSpace(actionName))
|
|
return null;
|
|
|
|
try
|
|
{
|
|
return _playerInput.actions.FindAction(actionName, true);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
} |