272 lines
11 KiB
C#
272 lines
11 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.SceneManagement;
|
|
using OctoRef = OctoCore.OctoCore;
|
|
|
|
namespace Unheimlich.Navigation.Debuging
|
|
{
|
|
/// <summary>
|
|
/// Listens for debug input combos and drives DebugNavigation.
|
|
///
|
|
/// — Gamepad : L3+R3 simultaneously → unlock/lock. L2/R2 → prev/next scene.
|
|
/// — Keyboard : backquote (² AZERTY / ~ QWERTY) → unlock/lock. A/E → prev/next.
|
|
///
|
|
/// Device display: switches based on last active input, not physical connection.
|
|
/// </summary>
|
|
public class DebugMenuUnlocker : MonoBehaviour
|
|
{
|
|
[Header("Data")]
|
|
[SerializeField] private DebugNavigation _debugNavigation;
|
|
|
|
[Header("Unlock Events")]
|
|
public UnityEvent OnDebugMenuUnlockedGamepad;
|
|
public UnityEvent OnDebugMenuUnlockedKeyboard;
|
|
public UnityEvent OnDebugMenuLocked;
|
|
|
|
[Header("Navigation Events")]
|
|
public UnityEvent OnPreviousScene;
|
|
public UnityEvent OnNextScene;
|
|
|
|
[Header("Device Switch Events")]
|
|
[Tooltip("Fired when gamepad input is detected and last input was keyboard/mouse.")]
|
|
public UnityEvent OnSwitchedToGamepad;
|
|
|
|
[Tooltip("Fired when keyboard/mouse input is detected and last input was gamepad.")]
|
|
public UnityEvent OnSwitchedToKeyboard;
|
|
|
|
// ── State ────────────────────────────────────────────────────────────
|
|
|
|
private bool _isUnlocked = false;
|
|
private bool _lastWasGamepad = false;
|
|
|
|
// Input Actions
|
|
private InputAction _keyboardUnlockAction;
|
|
private InputAction _gamepadUnlockAction;
|
|
private InputAction _gamepadPreviousAction;
|
|
private InputAction _gamepadNextAction;
|
|
private InputAction _keyboardPreviousAction;
|
|
private InputAction _keyboardNextAction;
|
|
private InputAction _anyGamepadAction;
|
|
private InputAction _anyKeyboardAction;
|
|
|
|
// ── Unity lifecycle ──────────────────────────────────────────────────
|
|
|
|
private void Awake() => BuildInputActions();
|
|
private void OnEnable() => EnableActions();
|
|
private void Start()
|
|
{
|
|
DebugManager.instance.enableRuntimeUI = false;
|
|
|
|
StartCoroutine(InitWhenReady());
|
|
SceneManager.sceneLoaded += OnUnitySceneLoaded;
|
|
}
|
|
private void OnDisable()
|
|
{
|
|
DisableActions();
|
|
UnsubscribeFromSceneEvents();
|
|
SceneManager.sceneLoaded -= OnUnitySceneLoaded;
|
|
}
|
|
private void OnDestroy() => DisposeActions();
|
|
|
|
// ── Build ────────────────────────────────────────────────────────────
|
|
|
|
private void BuildInputActions()
|
|
{
|
|
// Keyboard unlock : backquote (² AZERTY / ~ QWERTY)
|
|
_keyboardUnlockAction = new InputAction("DebugUnlockKeyboard", InputActionType.Button);
|
|
_keyboardUnlockAction.AddBinding("<Keyboard>/backquote");
|
|
_keyboardUnlockAction.performed += _ => ToggleDebugMenu(false);
|
|
|
|
// Gamepad unlock : L3 + R3 simultaneously
|
|
_gamepadUnlockAction = new InputAction("DebugUnlockGamepad", InputActionType.Button);
|
|
_gamepadUnlockAction.AddCompositeBinding("ButtonWithOneModifier")
|
|
.With("Modifier", "<Gamepad>/leftStickPress")
|
|
.With("Button", "<Gamepad>/rightStickPress");
|
|
_gamepadUnlockAction.performed += _ => ToggleDebugMenu(true);
|
|
|
|
// Gamepad navigation : L2 / R2
|
|
_gamepadPreviousAction = new InputAction("DebugPrevGamepad", InputActionType.Button);
|
|
_gamepadPreviousAction.AddBinding("<Gamepad>/leftTrigger")
|
|
.WithProcessor("AxisDeadzone(min=0.5,max=1)");
|
|
_gamepadPreviousAction.performed += _ => TryPrevious();
|
|
|
|
_gamepadNextAction = new InputAction("DebugNextGamepad", InputActionType.Button);
|
|
_gamepadNextAction.AddBinding("<Gamepad>/rightTrigger")
|
|
.WithProcessor("AxisDeadzone(min=0.5,max=1)");
|
|
_gamepadNextAction.performed += _ => TryNext();
|
|
|
|
// Keyboard navigation : A / E
|
|
_keyboardPreviousAction = new InputAction("DebugPrevKeyboard", InputActionType.Button);
|
|
_keyboardPreviousAction.AddBinding("<Keyboard>/q");
|
|
_keyboardPreviousAction.performed += _ => TryPrevious();
|
|
|
|
_keyboardNextAction = new InputAction("DebugNextKeyboard", InputActionType.Button);
|
|
_keyboardNextAction.AddBinding("<Keyboard>/e");
|
|
_keyboardNextAction.performed += _ => TryNext();
|
|
|
|
// Device detection
|
|
_anyGamepadAction = new InputAction("AnyGamepad", InputActionType.PassThrough);
|
|
_anyGamepadAction.AddBinding("<Gamepad>/leftStick");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/rightStick");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/buttonSouth");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/buttonNorth");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/buttonEast");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/buttonWest");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/leftShoulder");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/rightShoulder");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/leftTrigger");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/rightTrigger");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/start");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/select");
|
|
_anyGamepadAction.AddBinding("<Gamepad>/dpad");
|
|
_anyGamepadAction.performed += _ => OnAnyGamepadInput();
|
|
|
|
_anyKeyboardAction = new InputAction("AnyKeyboard", InputActionType.PassThrough);
|
|
_anyKeyboardAction.AddBinding("<Keyboard>/anyKey");
|
|
_anyKeyboardAction.AddBinding("<Mouse>/delta");
|
|
_anyKeyboardAction.AddBinding("<Mouse>/leftButton");
|
|
_anyKeyboardAction.AddBinding("<Mouse>/rightButton");
|
|
_anyKeyboardAction.performed += _ => OnAnyKeyboardInput();
|
|
}
|
|
|
|
private void EnableActions()
|
|
{
|
|
_keyboardUnlockAction?.Enable();
|
|
_gamepadUnlockAction?.Enable();
|
|
_gamepadPreviousAction?.Enable();
|
|
_gamepadNextAction?.Enable();
|
|
_keyboardPreviousAction?.Enable();
|
|
_keyboardNextAction?.Enable();
|
|
_anyGamepadAction?.Enable();
|
|
_anyKeyboardAction?.Enable();
|
|
}
|
|
|
|
private void DisableActions()
|
|
{
|
|
_keyboardUnlockAction?.Disable();
|
|
_gamepadUnlockAction?.Disable();
|
|
_gamepadPreviousAction?.Disable();
|
|
_gamepadNextAction?.Disable();
|
|
_keyboardPreviousAction?.Disable();
|
|
_keyboardNextAction?.Disable();
|
|
_anyGamepadAction?.Disable();
|
|
_anyKeyboardAction?.Disable();
|
|
}
|
|
|
|
private void DisposeActions()
|
|
{
|
|
_keyboardUnlockAction?.Dispose();
|
|
_gamepadUnlockAction?.Dispose();
|
|
_gamepadPreviousAction?.Dispose();
|
|
_gamepadNextAction?.Dispose();
|
|
_keyboardPreviousAction?.Dispose();
|
|
_keyboardNextAction?.Dispose();
|
|
_anyGamepadAction?.Dispose();
|
|
_anyKeyboardAction?.Dispose();
|
|
}
|
|
|
|
// ── Init ─────────────────────────────────────────────────────────────
|
|
|
|
private IEnumerator InitWhenReady()
|
|
{
|
|
yield return new WaitUntil(() => OctoRef.Instance != null);
|
|
yield return new WaitUntil(() => OctoRef.Instance.Navigation.CurrentScene != null);
|
|
|
|
SyncDebugNavigation();
|
|
SubscribeToSceneEvents();
|
|
}
|
|
|
|
// ── Scene events ─────────────────────────────────────────────────────
|
|
|
|
private void SubscribeToSceneEvents()
|
|
{
|
|
if (OctoRef.Instance == null) return;
|
|
OctoRef.Instance.Navigation.OnSceneLoadCompleted += OnSceneLoadCompleted;
|
|
}
|
|
|
|
private void UnsubscribeFromSceneEvents()
|
|
{
|
|
if (OctoRef.Instance == null) return;
|
|
OctoRef.Instance.Navigation.OnSceneLoadCompleted -= OnSceneLoadCompleted;
|
|
}
|
|
|
|
private void OnUnitySceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
UnsubscribeFromSceneEvents();
|
|
SubscribeToSceneEvents();
|
|
}
|
|
|
|
private void OnSceneLoadCompleted(OctoCore.Navigation.Data.OctoSceneData sceneData)
|
|
{
|
|
_debugNavigation?.SyncWithCurrentScene(sceneData);
|
|
}
|
|
|
|
// ── Device switch ────────────────────────────────────────────────────
|
|
|
|
private void OnAnyGamepadInput()
|
|
{
|
|
if (_lastWasGamepad) return;
|
|
_lastWasGamepad = true;
|
|
OnSwitchedToGamepad?.Invoke();
|
|
}
|
|
|
|
private void OnAnyKeyboardInput()
|
|
{
|
|
if (!_lastWasGamepad) return;
|
|
_lastWasGamepad = false;
|
|
OnSwitchedToKeyboard?.Invoke();
|
|
}
|
|
|
|
// ── Logic ────────────────────────────────────────────────────────────
|
|
|
|
private void SyncDebugNavigation()
|
|
{
|
|
if (_debugNavigation == null || OctoRef.Instance == null) return;
|
|
_debugNavigation.SyncWithCurrentScene(OctoRef.Instance.Navigation.CurrentScene);
|
|
}
|
|
|
|
private void ToggleDebugMenu(bool isGamepad)
|
|
{
|
|
_isUnlocked = !_isUnlocked;
|
|
|
|
if (_isUnlocked)
|
|
{
|
|
SyncDebugNavigation();
|
|
if (isGamepad) OnDebugMenuUnlockedGamepad?.Invoke();
|
|
else OnDebugMenuUnlockedKeyboard?.Invoke();
|
|
Debug.Log($"[DebugMenuUnlocker] Unlocked ({(isGamepad ? "Gamepad" : "Keyboard")}).");
|
|
}
|
|
else
|
|
{
|
|
OnDebugMenuLocked?.Invoke();
|
|
Debug.Log("[DebugMenuUnlocker] Locked.");
|
|
}
|
|
}
|
|
|
|
private void TryPrevious()
|
|
{
|
|
if (!_isUnlocked || _debugNavigation == null) return;
|
|
OnPreviousScene?.Invoke();
|
|
_debugNavigation.Previous();
|
|
}
|
|
|
|
private void TryNext()
|
|
{
|
|
if (!_isUnlocked || _debugNavigation == null) return;
|
|
OnNextScene?.Invoke();
|
|
_debugNavigation.Next();
|
|
}
|
|
|
|
/// <summary>Called directly by Debug Menu UI buttons (0-based index).</summary>
|
|
public void LoadSceneByIndex(int index)
|
|
{
|
|
if (_debugNavigation == null) return;
|
|
_debugNavigation.LoadByIndex(index);
|
|
}
|
|
|
|
public bool IsUnlocked => _isUnlocked;
|
|
}
|
|
} |