Control Rebind

 avatar
unknown
csharp
2 months ago
7.8 kB
1
No Index
using System.Linq;
using DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using Outline = UnityEngine.UI.Outline;

public class ControlRebinder : FistblitzButton, IPointerClickHandler
{
    public int bindingIndex
    {
        get
        {
            var device = panel.parent.controller.pi.devices[0];
            string deviceGroup;
            if (device is Gamepad)
                deviceGroup = "Gamepad";
            else if (device is Keyboard)
                deviceGroup = "Keyboard";
            else
                deviceGroup = "Unknown";
            var value = InputActionExtensions.GetBindingIndicesForDevice(PlayerInputAction,
                deviceGroup)[0];
            print(value);
            return value;
        }
    }

    private ControlPanel panel => transform.parent.parent.parent.GetComponent<ControlPanel>();

    private PlayerInput input => panel.parent.controller.pi;

    private InputAction PlayerInputAction =>
        input.actions.FindAction(actionToRebind.action.id);

    public UnityEvent BindCompleted;
    public UnityEvent CancelSequence;

    [SerializeField] private UnityEngine.UI.Outline outline;
    private Tween activeTween;

    private Tween ActiveTween
    {
        set
        {
            if (activeTween.IsActive()) activeTween.Kill();
            activeTween = value;
        }
    }

    [Header("Action to Rebind")] public InputActionReference actionToRebind;

    public bool SequenceActivated;

    private InputActionRebindingExtensions.RebindingOperation currentRebind;

    private string InputBindingName => PlayerInputAction.bindings[bindingIndex]
        .ToDisplayString(InputBinding.DisplayStringOptions.DontUseShortDisplayNames);

    public bool IsRebinding => currentRebind != null;

    public TextMeshProUGUI KeybindName;
    public TextMeshProUGUI KeybindValue;

    public Image isRebindingImage;

    protected override void Start()
    {
        base.Start();
        KeybindName.text = PlayerInputAction.name;
        KeybindValue.text = InputBindingName;
        outline.effectDistance = Vector2.zero;
    }

    public void RefreshButtons()
    {
        KeybindName.text = PlayerInputAction.name;
        KeybindValue.text = InputBindingName;
        outline.effectDistance = Vector2.zero;
        print("Refresh buttons called!");
    }

    private void Update()
    {
        isRebindingImage.color = IsRebinding ? Color.greenYellow : Color.white;
    }

    public void ResetBinding()
    {
        PlayerInputAction.RemoveBindingOverride(bindingIndex);
    }

    public void StartRebinding()
    {
        if (actionToRebind == null || actionToRebind.action == null)
        {
            Debug.LogWarning("No action assigned for rebinding.");
            return;
        }
        
        string devicePaths = "";
        foreach (var device in input.devices) {
            if (devicePaths != "") {
                devicePaths += ",";
            }
            devicePaths += device.path + "/*"; 
        }
        
        print(devicePaths);


        var action = PlayerInputAction;

        Debug.Log($"REBINDING [{action.name}] - Press a new key... (Press ESC to cancel)");

        KeybindValue.text = "Press a button....";

        if (action.enabled)
            action.Disable();
        
        currentRebind = action.PerformInteractiveRebinding(bindingIndex)
            .WithControlsExcluding("Mouse/position")
            .WithCancelingThrough("<Keyboard>/escape")
            .WithExpectedControlType("Button")
            // .OnMatchWaitForAnother(0.1f)
            // .OnPotentialMatch(operation => {
            //     var device = operation.selectedControl.device;
            //     if (!input.devices.Contains(device)) {
            //         // If another player presses a button, ignore it
            //         operation.RemoveCandidate(operation.selectedControl);
            //     }
            // })
            .WithControlsHavingToMatchPath(devicePaths)
            .OnComplete(op =>
            {
                action.Enable();
                currentRebind.Dispose();
                currentRebind = null;

                if (SequenceActivated)
                {
                    BindCompleted.Invoke();
                }

                KeybindName.text = PlayerInputAction.name;
                KeybindValue.text = InputBindingName;

                Debug.Log($"Rebind complete! New binding: {GetCurrentBinding()}");
                panel.isRebinding = false;
            })
            .OnCancel(op =>
            {
                action.Enable();
                currentRebind.Dispose();
                currentRebind = null;
                if (!SequenceActivated)
                {
                    action.ApplyBindingOverride("");
                }
                else
                {
                    CancelSequence.Invoke();
                }

                KeybindName.text = PlayerInputAction.name;
                KeybindValue.text = InputBindingName;

                panel.isRebinding = false;
                Debug.Log("Rebind cancelled.");
            });
        
        currentRebind.Start();
        panel.isRebinding = true;
    }

    private string GetCurrentBinding()
    {
        if (actionToRebind?.action == null)
            return "None";

        return InputControlPath.ToHumanReadableString(
            PlayerInputAction.bindings[bindingIndex].effectivePath,
            InputControlPath.HumanReadableStringOptions.OmitDevice);
    }

    public override void InitialiseButton()
    {
    }

    public override void DisableButton()
    {
    }

    public override void OnButtonPressed()
    {
        StartRebinding();
    }

    public override void ClickAnimation()
    {
    }

    public override void OnPointerEnter(PointerEventData eventData)
    {
        if (NotMyMarker(eventData)) return;
        base.OnPointerEnter(eventData);
        print("Hoevered over a rebinder");
        ActiveTween = DOTween.To(() => outline.effectDistance, x => outline.effectDistance = x, new Vector2(5, 5), 0.3f)
            .SetEase(Ease.OutCubic);
    }

    public override void OnPointerExit(PointerEventData eventData)
    {
        if (NotMyMarker(eventData)) return;
        base.OnPointerExit(eventData);
        print("Unhoevered over a rebinder");
        ActiveTween = DOTween.To(() => outline.effectDistance, x => outline.effectDistance = x, Vector2.zero, 0.3f)
            .SetEase(Ease.OutCubic);
    }
    
    public void OnPointerClick(PointerEventData eventData)
    {
        OnButtonPressed();
    }

    public override void OnSelect(BaseEventData eventData)
    {
        base.OnSelect(eventData);
        // ActiveTween = DOTween.To(() => outline.effectDistance, x => outline.effectDistance = x, new Vector2(5, 5), 0.3f)
        //     .SetEase(Ease.OutCubic);
    }

    public override void OnDeselect(BaseEventData eventData)
    {
        base.OnDeselect(eventData);
        // ActiveTween = DOTween.To(() => outline.effectDistance, x => outline.effectDistance = x, Vector2.zero, 0.3f)
        //     .SetEase(Ease.OutCubic);
    }

    public override void OnCancel(BaseEventData eventData)
    {
    }
    
    private bool NotMyMarker(BaseEventData eventData)
    {
        print(eventData.currentInputModule);
        return eventData.currentInputModule != panel.parent.Input;
    }

    
}
Editor is loading...
Leave a Comment