diff --git a/CHANGELOG.md b/CHANGELOG.md index 270d405..1f86062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Improvements - Added InputHandler mouse and touch position querying that preserves the game's viewport - Added float version of GetRandomWeightedEntry - Allow LinkCode to specify a color to draw with +- Allow better control over the order and layout of a Keybind's combinations Fixes - **Fixed a formatting Code only knowing about the last Token that it is applied in** @@ -43,6 +44,7 @@ Improvements - Update elements less aggressively when changing a ui system's style - Automatically update all elements when changing a ui system's viewport - Allow setting a default color for clickable links in UiStyle +- Allow ElementHelper's KeybindButton to query a combination at a given index Fixes - Fixed paragraph links having incorrect hover locations when using special text alignments diff --git a/MLEM.Ui/Elements/ElementHelper.cs b/MLEM.Ui/Elements/ElementHelper.cs index 918acc8..c6dd1f6 100644 --- a/MLEM.Ui/Elements/ElementHelper.cs +++ b/MLEM.Ui/Elements/ElementHelper.cs @@ -117,7 +117,7 @@ namespace MLEM.Ui.Elements { /// /// Creates a that acts as a way to input a custom value for a . - /// Note that only the first of the given keybind is displayed and edited, all others are ignored. The exception is that, if is set, unbinding the keybind clears all combinations. + /// Note that only the at index of the given keybind is displayed and edited, all others are ignored. /// Inputting custom keybinds using this element supports -based modifiers and any -based keys. /// /// The button's anchor @@ -128,12 +128,10 @@ namespace MLEM.Ui.Elements { /// An optional generic input that allows the keybind value to be unbound, clearing all combinations /// A placeholder text that is displayed if the keybind is unbound /// An optional function to give each input a display name that is easier to read. If this is null, is used. + /// The index in the that the button should display. Note that, if the index is greater than the amount of combinations, combinations entered using this button will be stored at an earlier index. /// A keybind button with the given settings - public static Button KeybindButton(Anchor anchor, Vector2 size, Keybind keybind, InputHandler inputHandler, string activePlaceholder, GenericInput unbindKey = default, string unboundPlaceholder = "", Func inputName = null) { - string GetCurrentName() { - var combination = keybind.GetCombinations().FirstOrDefault(); - return combination?.ToString(" + ", inputName) ?? unboundPlaceholder; - } + public static Button KeybindButton(Anchor anchor, Vector2 size, Keybind keybind, InputHandler inputHandler, string activePlaceholder, GenericInput unbindKey = default, string unboundPlaceholder = "", Func inputName = null, int index = 0) { + string GetCurrentName() => keybind.TryGetCombination(index, out var combination) ? combination.ToString(" + ", inputName) : unboundPlaceholder; var button = new Button(anchor, size, GetCurrentName()); var active = false; @@ -148,18 +146,20 @@ namespace MLEM.Ui.Elements { activeNext = false; } else if (active) { if (unbindKey != default && inputHandler.IsPressed(unbindKey)) { - keybind.Clear(); + keybind.Remove((c, i) => i == index); button.Text.Text = unboundPlaceholder; active = false; } else if (inputHandler.InputsPressed.Length > 0) { var key = inputHandler.InputsPressed.FirstOrDefault(i => !i.IsModifier()); if (key != default) { var mods = inputHandler.InputsDown.Where(i => i.IsModifier()); - keybind.Remove((c, i) => i == 0).Add(key, mods.ToArray()); + keybind.Remove((c, i) => i == index).Insert(index, key, mods.ToArray()); button.Text.Text = GetCurrentName(); active = false; } } + } else { + button.Text.Text = GetCurrentName(); } }; return button; diff --git a/MLEM/Input/Keybind.cs b/MLEM/Input/Keybind.cs index ca8e28c..1ba8595 100644 --- a/MLEM/Input/Keybind.cs +++ b/MLEM/Input/Keybind.cs @@ -47,7 +47,28 @@ namespace MLEM.Input { /// public Keybind Add(GenericInput key, ModifierKey modifier) { - return this.Add(key, modifier.GetKeys().Select(m => (GenericInput) m).ToArray()); + foreach (var mod in modifier.GetKeys()) + this.Add(key, mod); + return this; + } + + /// + /// Inserts a new key combination into the given of this keybind's combinations that can optionally be pressed for the keybind to trigger. + /// + /// The index to insert this combination into. + /// The key to be pressed. + /// The modifier keys that have to be held down. + /// This keybind, for chaining. + public Keybind Insert(int index, GenericInput key, params GenericInput[] modifiers) { + this.combinations = this.combinations.Take(index).Append(new Combination(key, modifiers)).Concat(this.combinations.Skip(index)).ToArray(); + return this; + } + + /// + public Keybind Insert(int index, GenericInput key, ModifierKey modifier) { + foreach (var mod in modifier.GetKeys().Reverse()) + this.Insert(index, key, mod); + return this; } /// @@ -134,6 +155,22 @@ namespace MLEM.Input { yield return combination; } + /// + /// Tries to retrieve the combination at the given within this keybind. + /// + /// The index of the combination to retrieve. + /// The combination, or default if this method returns false. + /// Whether the combination could be successfully retrieved or the index was out of bounds of this keybind's combination collection. + public bool TryGetCombination(int index, out Combination combination) { + if (index >= 0 && index < this.combinations.Length) { + combination = this.combinations[index]; + return true; + } else { + combination = default; + return false; + } + } + /// /// Converts this keybind into an easily human-readable string. /// When using , this method is used with set to ", ". diff --git a/Sandbox/GameImpl.cs b/Sandbox/GameImpl.cs index bf73b71..6490d4a 100644 --- a/Sandbox/GameImpl.cs +++ b/Sandbox/GameImpl.cs @@ -304,6 +304,14 @@ namespace Sandbox { var newPanel = new Panel(Anchor.TopLeft, new Vector2(200, 100), new Vector2(10, 10)); newPanel.AddChild(new Button(Anchor.TopLeft, new Vector2(100, 20), "Text", "Tooltip text")); this.UiSystem.Add("Panel", newPanel); + + var keybind = new Keybind(MouseButton.Left, ModifierKey.Shift); + var keybindPanel = new Panel(Anchor.BottomRight, new Vector2(100, 100), new Vector2(5)); + for (var i = 0; i < 3; i++) { + var button = keybindPanel.AddChild(ElementHelper.KeybindButton(Anchor.AutoLeft, new Vector2(0.5F, 12), keybind, Input, "Press", Keys.Escape, index: i)); + button.Text.TextScale = 0.1F; + } + this.UiSystem.Add("Keybinds", keybindPanel); } protected override void DoUpdate(GameTime gameTime) {