Files
rolld/game/Assets/Scripts/KeyBindingUI.cs
kerboul 7327f073d8 fix: remapper F1/F2/F3 -> backtick/Tab/T pour compatibilite WebGL navigateur
- DebugNetworkUI: F1 -> backtick (`)
- KeyBindingUI: F2 -> Tab
- ChatUI: F3 -> T (ouvrir seulement), Escape pour fermer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 20:53:07 +02:00

317 lines
9.4 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
/// <summary>
/// Runtime key rebinding UI. Toggle with F2.
/// Manages rebinding for InputSystem actions (movement, jump)
/// and custom camera orbit keys (ZQSD).
/// All overrides persist in PlayerPrefs.
/// </summary>
public class KeyBindingUI : MonoBehaviour
{
private bool _visible = false;
private string _rebindingAction = null;
/// <summary>True when the keybind config menu is open. Used to freeze camera + unlock cursor.</summary>
public static bool IsVisible { get; private set; }
private InputActionRebindingExtensions.RebindingOperation _rebindOp;
// Default camera keys (physical WASD positions = ZQSD on AZERTY)
private static readonly Dictionary<string, Key> _defaultCameraKeys = new()
{
{ "CamUp", Key.W },
{ "CamDown", Key.S },
{ "CamLeft", Key.A },
{ "CamRight", Key.D },
};
private static readonly string[] _cameraKeyNames = { "CamUp", "CamDown", "CamLeft", "CamRight" };
private static readonly string[] _cameraKeyLabels = { "Caméra haut", "Caméra bas", "Caméra gauche", "Caméra droite" };
private static Dictionary<string, Key> _currentCameraKeys;
private PlayerInput _playerInput;
void Awake()
{
LoadCameraKeys();
}
void Start()
{
_playerInput = FindFirstObjectByType<PlayerInput>();
LoadBindingOverrides();
}
void Update()
{
if (Keyboard.current != null && Keyboard.current[Key.Tab].wasPressedThisFrame)
{
_visible = !_visible;
IsVisible = _visible;
if (_visible)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else
{
CancelRebind();
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
}
void LateUpdate()
{
// Process camera key rebinding
if (_rebindingAction == null) return;
if (!_defaultCameraKeys.ContainsKey(_rebindingAction)) return;
var kb = Keyboard.current;
if (kb == null) return;
foreach (Key k in Enum.GetValues(typeof(Key)))
{
if (k == Key.None) continue;
try
{
if (kb[k].wasPressedThisFrame)
{
if (k == Key.Escape)
{
_rebindingAction = null;
return;
}
_currentCameraKeys[_rebindingAction] = k;
SaveCameraKeys();
_rebindingAction = null;
return;
}
}
catch { }
}
}
void OnGUI()
{
if (!_visible) return;
ImGuiSkin.EnsureReady();
// Overlay
ImGuiSkin.DrawOverlay();
float w = 480, h = 540;
ImGuiSkin.BeginWindow(w, h, "Configuration des touches");
// --- Movement ---
ImGuiSkin.DrawSectionHeader("DÉPLACEMENT");
GUILayout.Space(4);
DrawActionBinding("forward", "Avancer");
DrawActionBinding("backwards", "Reculer");
DrawActionBinding("left", "Gauche");
DrawActionBinding("right", "Droite");
DrawActionBinding("jump", "Sauter");
GUILayout.Space(10);
// --- Camera ---
ImGuiSkin.DrawSectionHeader("CAMÉRA (+ SOURIS)");
GUILayout.Space(4);
for (int i = 0; i < _cameraKeyNames.Length; i++)
DrawCameraKeyBinding(_cameraKeyNames[i], _cameraKeyLabels[i]);
GUILayout.Space(16);
// Buttons
GUILayout.BeginHorizontal();
if (GUILayout.Button("Réinitialiser tout", ImGuiSkin.Button, GUILayout.Height(32)))
ResetAllBindings();
if (GUILayout.Button("Fermer (Tab)", ImGuiSkin.Button, GUILayout.Height(32)))
{
_visible = false;
CancelRebind();
}
GUILayout.EndHorizontal();
GUILayout.Space(6);
if (_rebindingAction != null)
{
GUILayout.Label("Appuyez sur une touche pour assigner...", ImGuiSkin.Hint);
}
GUILayout.Label("Tab — Ouvrir / Fermer ce menu", ImGuiSkin.Footer);
ImGuiSkin.EndWindow();
}
// --- Drawing helpers ---
private void DrawActionBinding(string actionName, string label)
{
if (_playerInput == null) return;
var action = _playerInput.actions.FindAction(actionName);
if (action == null) return;
GUILayout.BeginHorizontal();
GUILayout.Label(label, ImGuiSkin.Label, GUILayout.Width(150));
string currentBinding = "---";
if (action.bindings.Count > 0)
currentBinding = InputControlPath.ToHumanReadableString(
action.bindings[0].effectivePath,
InputControlPath.HumanReadableStringOptions.OmitDevice);
bool isRebinding = _rebindingAction == actionName;
string btnText = isRebinding ? "[ ... ]" : currentBinding;
GUIStyle btnStyle = isRebinding ? ImGuiSkin.ButtonAccent : ImGuiSkin.ButtonSmall;
if (GUILayout.Button(btnText, btnStyle, GUILayout.Width(170), GUILayout.Height(26)))
{
if (!isRebinding) StartActionRebind(actionName);
else CancelRebind();
}
GUILayout.EndHorizontal();
}
private void DrawCameraKeyBinding(string keyName, string label)
{
GUILayout.BeginHorizontal();
GUILayout.Label(label, ImGuiSkin.Label, GUILayout.Width(150));
Key current = GetKey(keyName, _defaultCameraKeys[keyName]);
bool isRebinding = _rebindingAction == keyName;
string btnText = isRebinding ? "[ ... ]" : current.ToString();
GUIStyle btnStyle = isRebinding ? ImGuiSkin.ButtonAccent : ImGuiSkin.ButtonSmall;
if (GUILayout.Button(btnText, btnStyle, GUILayout.Width(170), GUILayout.Height(26)))
{
if (!isRebinding) StartCameraKeyRebind(keyName);
else CancelRebind();
}
GUILayout.EndHorizontal();
}
// --- Rebinding logic ---
private void StartActionRebind(string actionName)
{
CancelRebind();
var action = _playerInput?.actions.FindAction(actionName);
if (action == null) return;
_rebindingAction = actionName;
action.Disable();
_rebindOp = action.PerformInteractiveRebinding(0)
.WithControlsExcluding("Mouse")
.OnMatchWaitForAnother(0.1f)
.OnComplete(op =>
{
action.Enable();
SaveBindingOverrides();
_rebindingAction = null;
op.Dispose();
_rebindOp = null;
})
.OnCancel(op =>
{
action.Enable();
_rebindingAction = null;
op.Dispose();
_rebindOp = null;
})
.Start();
}
private void StartCameraKeyRebind(string keyName)
{
CancelRebind();
_rebindingAction = keyName;
}
private void CancelRebind()
{
if (_rebindOp != null)
{
_rebindOp.Cancel();
_rebindOp.Dispose();
_rebindOp = null;
}
_rebindingAction = null;
}
// --- Persistence ---
private void SaveBindingOverrides()
{
if (_playerInput == null) return;
string json = _playerInput.actions.SaveBindingOverridesAsJson();
PlayerPrefs.SetString("InputOverrides", json);
PlayerPrefs.Save();
}
private void LoadBindingOverrides()
{
if (_playerInput == null) return;
string json = PlayerPrefs.GetString("InputOverrides", "");
if (!string.IsNullOrEmpty(json))
_playerInput.actions.LoadBindingOverridesFromJson(json);
}
private static void LoadCameraKeys()
{
_currentCameraKeys = new Dictionary<string, Key>();
foreach (var kv in _defaultCameraKeys)
{
string saved = PlayerPrefs.GetString($"CamKey_{kv.Key}", "");
if (!string.IsNullOrEmpty(saved) && Enum.TryParse<Key>(saved, out Key parsed))
_currentCameraKeys[kv.Key] = parsed;
else
_currentCameraKeys[kv.Key] = kv.Value;
}
}
private static void SaveCameraKeys()
{
if (_currentCameraKeys == null) return;
foreach (var kv in _currentCameraKeys)
PlayerPrefs.SetString($"CamKey_{kv.Key}", kv.Value.ToString());
PlayerPrefs.Save();
}
/// <summary>
/// Get a camera key binding. Usable globally (static).
/// </summary>
public static Key GetKey(string name, Key fallback)
{
if (_currentCameraKeys == null) LoadCameraKeys();
return _currentCameraKeys != null && _currentCameraKeys.TryGetValue(name, out Key k) ? k : fallback;
}
private void ResetAllBindings()
{
// Reset InputSystem actions
if (_playerInput != null)
{
foreach (var action in _playerInput.actions)
action.RemoveAllBindingOverrides();
PlayerPrefs.DeleteKey("InputOverrides");
}
// Reset camera keys
_currentCameraKeys = new Dictionary<string, Key>(_defaultCameraKeys);
foreach (var kv in _defaultCameraKeys)
PlayerPrefs.DeleteKey($"CamKey_{kv.Key}");
PlayerPrefs.Save();
}
}