mirror of
https://github.com/ConjureETS/Unity_Utils.git
synced 2026-03-23 20:40:58 +00:00
205 lines
7.4 KiB
C#
205 lines
7.4 KiB
C#
using System;
|
|
using JetBrains.Annotations;
|
|
using JohnsonUtils.Utilities;
|
|
using JohnsonUtils.Utilities.Icons;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
namespace JohnsonUtils.Canvases
|
|
{
|
|
public class RebindActionUI : MonoBehaviour
|
|
{
|
|
public event Action<string, string> UpdateBindingUIEvent;
|
|
|
|
[SerializeField] private TextUIComponent actionLabel;
|
|
[SerializeField] private RebindReferences mainBindingReferences;
|
|
[SerializeField] private RebindReferences altBindingReferences;
|
|
|
|
private TextUIComponent _rebindOverlay;
|
|
private InputAction _action;
|
|
private InputActionRebindingExtensions.RebindingOperation _rebindOperation;
|
|
|
|
[PublicAPI]
|
|
public void ResetToDefault()
|
|
{
|
|
_action.actionMap.Disable();
|
|
_action.RemoveBindingOverride(mainBindingReferences.Index);
|
|
_action.RemoveBindingOverride(altBindingReferences.Index);
|
|
UpdateBindingDisplay();
|
|
_action.actionMap.Enable();
|
|
}
|
|
|
|
private void StartInteractiveRebind(int index)
|
|
{
|
|
_action.actionMap.Disable();
|
|
PerformInteractiveRebind(index);
|
|
_action.actionMap.Enable();
|
|
}
|
|
|
|
private void PerformInteractiveRebind(int bindingIndex)
|
|
{
|
|
_rebindOperation?.Cancel(); // Will null out rebindOperation.
|
|
|
|
void CleanUp(InputActionRebindingExtensions.RebindingOperation rebindingOperation)
|
|
{
|
|
if (_rebindOverlay != null)
|
|
{
|
|
_rebindOverlay.SetActive(false);
|
|
}
|
|
|
|
UpdateBindingDisplay();
|
|
_rebindOperation?.Dispose();
|
|
_rebindOperation = null;
|
|
}
|
|
|
|
// Configure the rebind.
|
|
_rebindOperation = _action.PerformInteractiveRebinding(bindingIndex)
|
|
.OnCancel(CleanUp)
|
|
.OnComplete(CleanUp);
|
|
|
|
// If it's a part binding, show the name of the part in the UI.
|
|
string partName = string.Empty;
|
|
if (_action.bindings[bindingIndex].isPartOfComposite)
|
|
partName = $"Binding '{_action.bindings[bindingIndex].name}'. ";
|
|
|
|
// Bring up rebind overlay, if we have one.
|
|
if (_rebindOverlay != null)
|
|
{
|
|
_rebindOverlay.Show();
|
|
string text = !string.IsNullOrEmpty(_rebindOperation.expectedControlType)
|
|
? $"{partName}Waiting for {_rebindOperation.expectedControlType} input..."
|
|
: $"{partName}Waiting for input...";
|
|
_rebindOverlay.Text =text;
|
|
}
|
|
|
|
// If we have no rebind overlay and no callback but we have a binding text label,
|
|
// temporarily set the binding text label to "<Waiting>".
|
|
if (_rebindOverlay == null && mainBindingReferences.Text != null)
|
|
mainBindingReferences.Text.Text = "<Waiting...>";
|
|
|
|
_rebindOperation.Start();
|
|
}
|
|
|
|
protected void OnEnable()
|
|
{
|
|
mainBindingReferences.Button.OnClick += () => StartInteractiveRebind(mainBindingReferences.Index);
|
|
altBindingReferences.Button.OnClick += () => StartInteractiveRebind(altBindingReferences.Index);
|
|
}
|
|
|
|
protected void OnDisable()
|
|
{
|
|
_rebindOperation?.Dispose();
|
|
_rebindOperation = null;
|
|
}
|
|
|
|
private void UpdateActionLabel()
|
|
{
|
|
if (actionLabel == null) return;
|
|
|
|
string actionLabelText = _action.bindings[mainBindingReferences.Index].isPartOfComposite
|
|
? _action.bindings[mainBindingReferences.Index].name.Capitalize()
|
|
: _action.name;
|
|
|
|
if (actionLabelText.Equals("Dash")) actionLabelText = "Tackle";
|
|
actionLabel.Text = actionLabelText;
|
|
}
|
|
|
|
public void UpdateBindingDisplay(bool shouldCallEvent = true)
|
|
{
|
|
string mainDisplayString = string.Empty;
|
|
string altDisplayString = string.Empty;
|
|
string deviceLayoutName = string.Empty;
|
|
string mainControlPath = string.Empty;
|
|
string altControlPath = string.Empty;
|
|
|
|
if (_action != null)
|
|
{
|
|
if (mainBindingReferences.Index != -1)
|
|
mainDisplayString = _action.GetBindingDisplayString(mainBindingReferences.Index,
|
|
out deviceLayoutName,
|
|
out mainControlPath);
|
|
if (altBindingReferences.Index != -1)
|
|
altDisplayString = _action.GetBindingDisplayString(altBindingReferences.Index, out _,
|
|
out altControlPath);
|
|
}
|
|
|
|
UpdateDuplicateText(mainBindingReferences, mainDisplayString);
|
|
UpdateDuplicateText(altBindingReferences, altDisplayString);
|
|
|
|
Sprite mainIcon = BindingsIconsUtil.GetSprite(deviceLayoutName, mainControlPath);
|
|
Sprite altIcon = BindingsIconsUtil.GetSprite(deviceLayoutName, altControlPath);
|
|
|
|
DisplayIcon(mainBindingReferences, mainIcon);
|
|
DisplayIcon(altBindingReferences, altIcon);
|
|
|
|
if (shouldCallEvent)
|
|
{
|
|
UpdateBindingUIEvent?.Invoke(deviceLayoutName, mainControlPath);
|
|
}
|
|
}
|
|
|
|
private void DisplayIcon(RebindReferences reference, Sprite mainIcon)
|
|
{
|
|
if (mainIcon != null)
|
|
{
|
|
reference.Text.Hide();
|
|
reference.Image.Sprite = mainIcon;
|
|
reference.Image.Show();
|
|
}
|
|
else
|
|
{
|
|
reference.Text.Show();
|
|
reference.Image.Hide();
|
|
}
|
|
}
|
|
|
|
private void UpdateDuplicateText(RebindReferences reference, string mainDisplayString)
|
|
{
|
|
if (reference.Text == null) return;
|
|
reference.Text.Text = mainDisplayString == "Delta" ? "Mouse" : mainDisplayString;
|
|
bool mainDuplicate = CheckDuplicateBindings(reference.Index);
|
|
reference.Button.Color = mainDuplicate ? Color.red : Color.white;
|
|
}
|
|
|
|
private bool CheckDuplicateBindings(int bindingIndex)
|
|
{
|
|
if (_action == null) return false;
|
|
|
|
InputBinding newBinding = _action.bindings[bindingIndex];
|
|
|
|
if (newBinding.effectivePath.IsNullOrEmpty()) return false;
|
|
|
|
foreach (InputBinding binding in _action.actionMap.bindings)
|
|
{
|
|
if (binding.action == newBinding.action) continue;
|
|
|
|
if (binding.effectivePath == newBinding.effectivePath) return true;
|
|
}
|
|
|
|
if (!_action.bindings[0].isComposite) return false;
|
|
|
|
for (int i = 1; i < _action.bindings.Count; i++)
|
|
{
|
|
if (i == bindingIndex) continue;
|
|
if (_action.bindings[i].effectivePath == newBinding.effectivePath)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void Initialize(int bindingIndex, InputAction inputAction, TextUIComponent overlay,
|
|
Action<string, string> onUpdateBindingUIEvent)
|
|
{
|
|
mainBindingReferences.Index = bindingIndex;
|
|
altBindingReferences.Index = bindingIndex + 1;
|
|
_action = inputAction;
|
|
_rebindOverlay = overlay;
|
|
UpdateBindingUIEvent += onUpdateBindingUIEvent;
|
|
UpdateActionLabel();
|
|
UpdateBindingDisplay();
|
|
}
|
|
}
|
|
} |