diff --git a/packages/org.gamecult.eve.unity-uitoolkit/Runtime/EveInputBindingMapElement.cs b/packages/org.gamecult.eve.unity-uitoolkit/Runtime/EveInputBindingMapElement.cs new file mode 100644 index 0000000..d460bf2 --- /dev/null +++ b/packages/org.gamecult.eve.unity-uitoolkit/Runtime/EveInputBindingMapElement.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using GameCult.Eve.Surface; +using UnityEngine; +using UnityEngine.UIElements; + +namespace GameCult.Eve.UnityUIToolkit +{ + public sealed class EveInputBindingMapElement : VisualElement + { + private readonly VisualElement _device = new VisualElement(); + private readonly Label _sequence = new Label(); + private readonly List _pendingSequence = new List(); + private EveInputDeviceLayout _layout = new EveInputDeviceLayout(); + private IReadOnlyList _bindings = Array.Empty(); + private string _draggedActionId = ""; + + public EveInputBindingMapElement() + { + style.position = Position.Relative; + style.flexGrow = 1; + _device.style.position = Position.Relative; + _device.style.minHeight = 360; + _device.style.flexGrow = 1; + _sequence.style.unityTextAlign = TextAnchor.MiddleCenter; + _sequence.style.minHeight = 32; + Add(_device); + Add(_sequence); + } + + public event Action? BindingRequested; + + public void SetState(EveInputDeviceLayout layout, IReadOnlyList bindings) + { + _layout = layout ?? new EveInputDeviceLayout(); + _bindings = bindings ?? Array.Empty(); + Render(); + } + + public void BeginActionDrag(string actionId) + { + _draggedActionId = actionId ?? ""; + } + + public void CancelActionDrag() + { + _draggedActionId = ""; + _pendingSequence.Clear(); + RenderSequence(); + } + + public void RecordDirectionalStep(string control) + { + if (!_layout.SupportsDirectionalStrings || string.IsNullOrWhiteSpace(_draggedActionId)) return; + if (!control.StartsWith("gamepad.dpad.", StringComparison.Ordinal)) return; + _pendingSequence.Add(control); + RenderSequence(); + } + + public void CommitDirectionalString() + { + if (string.IsNullOrWhiteSpace(_draggedActionId) || _pendingSequence.Count == 0) return; + BindingRequested?.Invoke(_draggedActionId, new EveInputGesture { Kind = "sequence", Controls = _pendingSequence.ToArray(), MaxStepIntervalMs = 650 }); + CancelActionDrag(); + } + + private void Render() + { + _device.Clear(); + foreach (var control in _layout.Controls) + { + var button = new Button(() => BindDirect(control.Control)); + button.text = BindingLabel(control.Control, control.Label); + button.style.position = Position.Absolute; + button.style.left = control.X * 54; + button.style.top = control.Y * 54; + button.style.width = control.Width * 50; + button.style.height = control.Height * 46; + button.tooltip = control.Control; + _device.Add(button); + } + RenderSequence(); + } + + private void BindDirect(string control) + { + if (string.IsNullOrWhiteSpace(_draggedActionId)) return; + if (_layout.SupportsDirectionalStrings && control.StartsWith("gamepad.dpad.", StringComparison.Ordinal)) + { + RecordDirectionalStep(control); + return; + } + BindingRequested?.Invoke(_draggedActionId, new EveInputGesture { Kind = "direct", Controls = new[] { control } }); + CancelActionDrag(); + } + + private string BindingLabel(string control, string fallback) + { + var actions = _bindings.Where(binding => binding.Gesture.Controls.Contains(control)).Select(binding => binding.ActionId).ToArray(); + return actions.Length == 0 ? fallback : fallback + "\n" + string.Join(" + ", actions); + } + + private void RenderSequence() + { + _sequence.text = _pendingSequence.Count == 0 ? "" : string.Join(" ", _pendingSequence.Select(DirectionGlyph)); + } + + private static string DirectionGlyph(string control) => control.EndsWith(".up") ? "UP" : control.EndsWith(".down") ? "DOWN" : control.EndsWith(".left") ? "LEFT" : "RIGHT"; + } +} diff --git a/packages/org.gamecult.eve.unity-uitoolkit/Runtime/EveInputBindingMapElement.cs.meta b/packages/org.gamecult.eve.unity-uitoolkit/Runtime/EveInputBindingMapElement.cs.meta new file mode 100644 index 0000000..7b66a00 --- /dev/null +++ b/packages/org.gamecult.eve.unity-uitoolkit/Runtime/EveInputBindingMapElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7832863f3465444db693d405c3389acf