#nullable enable using ImGuiNET; using T3.Core.Settings; using T3.Editor.Gui.Input; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; using T3.SystemUi; namespace T3.Editor.Gui.Interaction.Keyboard; /// /// User interface switching and adjusting KeyBindings... /// internal static class KeyMapEditor { private static KeyMap CurrentKeyMap => KeyMapSwitching.CurrentKeymap; private static KeyMap _currentKeyBindingWithoutChanges = KeyMapSwitching.CurrentKeymap.Clone(); public static void DrawEditor() { FormInputs.SetIndent(100); // Draw Keymap list var userSelection = UserSettings.Config.KeyBindingName; if (FormInputs.AddDropdown(ref userSelection, KeyMapSwitching.KeyMaps.Select(t => t.Name), "Key Map", $""" You can clone key map bindings and create your personal layouts. They wil be saved to {FileLocations.SettingsDirectory}. """)) { if (KeyMapSwitching.TrySetKeyMap(userSelection)) { UserSettings.Config.KeyBindingName = userSelection; UserSettings.Save(); _currentKeyBindingWithoutChanges = CurrentKeyMap.Clone(); } else { Log.Warning($"Failed to find keymap {userSelection}"); } } FormInputs.AddVerticalSpace(); FormInputs.AddStringInput("Name", ref KeyMapSwitching.CurrentKeymap.Name); FormInputs.AddStringInput("Author", ref KeyMapSwitching.CurrentKeymap.Author); _somethingChanged |= KeyMapSwitching.CurrentKeymap.Name != _currentKeyBindingWithoutChanges.Name; _somethingChanged |= KeyMapSwitching.CurrentKeymap.Author != _currentKeyBindingWithoutChanges.Author; FormInputs.AddVerticalSpace(); //FormInputs.SetIndentToParameters(); FormInputs.ApplyIndent(); if (!CurrentKeyMap.ReadOnly) { //ImGui.SameLine(0,1); if (CustomComponents.DisablableButton("Save", _somethingChanged)) { // TODO: and check if saving worked //KeyBindingHandling.SaveKeyBinding(_currentKeyBinding); KeyMapSwitching.SaveKeyMap(CurrentKeyMap); _currentKeyBindingWithoutChanges = CurrentKeyMap.Clone(); UserSettings.Config.KeyBindingName = KeyMapSwitching.CurrentKeymap.Name; _somethingChanged = false; } } ImGui.SameLine(); if (CustomComponents.DisablableButton("Clone", !_somethingChanged)) { KeyMapSwitching.CloneCurrentKeymap(); UserSettings.Config.KeyBindingName = CurrentKeyMap.Name; UserSettings.Save(); _somethingChanged = true; } if (!CurrentKeyMap.ReadOnly) { ImGui.SameLine(); if (ImGui.Button("Delete")) { KeyMapSwitching.DeleteKeyMap(CurrentKeyMap); } } FormInputs.AddVerticalSpace(); ImGui.Separator(); FormInputs.AddVerticalSpace(); DrawKeyMapTable(); } private static void DrawKeyMapTable() { var needUpdate = false; // Draw the table of shortcuts (same as before) if (ImGui.BeginTable("Shortcuts", 2, ImGuiTableFlags.BordersInnerH | ImGuiTableFlags.ScrollY)) { ImGui.TableSetupColumn("Action", ImGuiTableColumnFlags.WidthStretch, 0.65f); ImGui.TableSetupColumn("Shortcut", ImGuiTableColumnFlags.WidthStretch, 0.35f); foreach (var action in Enum.GetValues()) { if (action == UserActions.__Count) continue; ImGui.TableNextRow(); if (_selectedAction == action) { ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, ImGui.GetColorU32(ImGuiCol.Header)); } ImGui.TableSetColumnIndex(0); var actionName = CustomComponents.HumanReadablePascalCase(Enum.GetName(action)); if (ImGui.Selectable(actionName, _selectedAction == action, ImGuiSelectableFlags.SpanAllColumns | ImGuiSelectableFlags.AllowOverlap)) { _selectedAction = action; CurrentKeyMap.TryGetBinding(action, out var keyBinding); _selectedCombo = keyBinding.KeyCombination; ImGui.OpenPopup(actionName); } ImGui.TableSetColumnIndex(1); if (CurrentKeyMap.TryGetBinding(action, out var binding)) { var shortcuts = action.ListShortcuts(); if (_somethingChanged) { _currentKeyBindingWithoutChanges.TryGetBinding(action, out var originalBinding); var changed = !binding.KeyCombination.Matches(ref originalBinding.KeyCombination); if (changed) { if (string.IsNullOrEmpty(shortcuts)) { ImGui.PushStyleColor(ImGuiCol.Text, UiColors.StatusAttention.Rgba); ImGui.TextUnformatted("Removed " + _currentKeyBindingWithoutChanges.ShortCutsLabelsForActions[(int)action]); ImGui.PopStyleColor(); } else { ImGui.PushStyleColor(ImGuiCol.Text, UiColors.Text.Rgba); ImGui.TextUnformatted(shortcuts); ImGui.PopStyleColor(); } } else if (!string.IsNullOrEmpty(shortcuts)) { ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); ImGui.TextUnformatted(shortcuts); ImGui.PopStyleColor(); } } else { // Fallback to save allocations. ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); ImGui.TextUnformatted(shortcuts); ImGui.PopStyleColor(); } } needUpdate |= DrawEditPopUp(action, actionName); } ImGui.EndTable(); } if (needUpdate) { _somethingChanged = true; CurrentKeyMap.UpdateShortcutLabels(); } } private static KeyCombination _selectedCombo; private static bool DrawEditPopUp(UserActions action, string actionName) { if (!ImGui.BeginPopup(actionName)) return false; var needsUpdate = false; if (DrawToggle("Ctrl", _selectedCombo.Ctrl)) _selectedCombo.Ctrl = !_selectedCombo.Ctrl; ImGui.SameLine(0, 4); if (DrawToggle("Alt", _selectedCombo.Alt)) _selectedCombo.Alt = !_selectedCombo.Alt; ImGui.SameLine(0, 4); if (DrawToggle("Shift", _selectedCombo.Shift)) _selectedCombo.Shift = !_selectedCombo.Shift; ImGui.SameLine(0, 10); if (ImGui.IsKeyPressed(ImGuiKey.Escape)) { ImGui.CloseCurrentPopup(); } var pressedKey = KeyHandler.GetPressedKey(); if (pressedKey != Key.Undefined) { _selectedCombo.Key = pressedKey; } var k = _selectedCombo.Key; ImGui.SetNextItemWidth(100); if (FormInputs.DrawEnumDropdown(ref k, "key")) _selectedCombo.Key = k; FormInputs.AddVerticalSpace(5); var hasConflictingBinding = CurrentKeyMap.TryGetConflictingBinding(_selectedAction, _selectedCombo, out var conflictingBinding); if (hasConflictingBinding) { CustomComponents.StylizedText($"Already used for {conflictingBinding.Action}", Fonts.FontSmall, UiColors.StatusAttention); } FormInputs.AddVerticalSpace(); // Action buttons var isAssignValid = _selectedCombo.Key != Key.Undefined && !CurrentKeyMap.DoesBindingMatchCombo(_selectedAction, _selectedCombo); if (CustomComponents.DisablableButton("Assign", isAssignValid)) { CurrentKeyMap.AddBinding(_selectedAction, _selectedCombo); ImGui.CloseCurrentPopup(); if (hasConflictingBinding) { CurrentKeyMap.RemoveBinding(conflictingBinding.Action); } needsUpdate = true; } ImGui.SameLine(); var isRemoveValid = _selectedCombo.Key != Key.Undefined && _selectedAction != UserActions.None; if (CustomComponents.DisablableButton("Remove", isRemoveValid)) { CurrentKeyMap.RemoveBinding(_selectedAction); _selectedAction = UserActions.None; ImGui.CloseCurrentPopup(); needsUpdate = true; } ImGui.SameLine(); if (ImGui.Button("Cancel")) { ImGui.CloseCurrentPopup(); } FormInputs.AddVerticalSpace(); ImGui.EndPopup(); return needsUpdate; } private static bool DrawToggle(string label, bool enabled) { return CustomComponents.ToggleButton(ref enabled, label, new Vector2(40, 0)); } private static bool _somethingChanged; public static readonly object Dummy = new(); private static UserActions _selectedAction = UserActions.None; }