diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs index 754e14d3d..8d78a88e5 100644 --- a/Source/Editor/Content/GUI/ContentView.cs +++ b/Source/Editor/Content/GUI/ContentView.cs @@ -193,6 +193,7 @@ namespace FlaxEditor.Content.GUI OnDelete?.Invoke(_selection); }), new InputActionsContainer.Binding(options => options.SelectAll, SelectAll), + new InputActionsContainer.Binding(options => options.DeselectAll, DeselectAll), new InputActionsContainer.Binding(options => options.Rename, () => { if (HasSelection && _selection[0].CanRename) @@ -397,10 +398,7 @@ namespace FlaxEditor.Content.GUI PerformLayout(); } - /// - /// Selects all the items. - /// - public void SelectAll() + private void BulkSelectUpdate(bool select = true) { // Lock layout var wasLayoutLocked = IsLayoutLocked; @@ -408,13 +406,30 @@ namespace FlaxEditor.Content.GUI // Select items _selection.Clear(); - _selection.AddRange(_items); + if (select) + _selection.AddRange(_items); // Unload and perform UI layout IsLayoutLocked = wasLayoutLocked; PerformLayout(); } + /// + /// Selects all the items. + /// + public void SelectAll() + { + BulkSelectUpdate(true); + } + + /// + /// Deselects all the items. + /// + public void DeselectAll() + { + BulkSelectUpdate(false); + } + /// /// Deselects the specified item. /// diff --git a/Source/Editor/GUI/CurveEditor.Contents.cs b/Source/Editor/GUI/CurveEditor.Contents.cs index 7e7fbbd32..bdb1c650b 100644 --- a/Source/Editor/GUI/CurveEditor.Contents.cs +++ b/Source/Editor/GUI/CurveEditor.Contents.cs @@ -484,6 +484,7 @@ namespace FlaxEditor.GUI cm.AddSeparator(); cm.AddButton("Edit all keyframes", () => _editor.EditAllKeyframes(this, location)); cm.AddButton("Select all keyframes", _editor.SelectAll); + cm.AddButton("Deselect all keyframes", _editor.DeselectAll); cm.AddButton("Copy all keyframes", () => { _editor.SelectAll(); diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs index 69671b1da..6e6f43230 100644 --- a/Source/Editor/GUI/CurveEditor.cs +++ b/Source/Editor/GUI/CurveEditor.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Linq; using FlaxEditor.CustomEditors; using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.Options; using FlaxEngine; using FlaxEngine.GUI; @@ -713,15 +714,28 @@ namespace FlaxEditor.GUI } } + private void BulkSelectUpdate(bool select = true) + { + for (int i = 0; i < _points.Count; i++) + { + _points[i].IsSelected = select; + } + } + /// /// Selects all keyframes. /// public void SelectAll() { - for (int i = 0; i < _points.Count; i++) - { - _points[i].IsSelected = true; - } + BulkSelectUpdate(true); + } + + /// + /// Deselects all keyframes. + /// + public void DeselectAll() + { + BulkSelectUpdate(false); } /// @@ -926,34 +940,35 @@ namespace FlaxEditor.GUI if (base.OnKeyDown(key)) return true; - switch (key) + InputOptions options = Editor.Instance.Options.Options.Input; + if (options.SelectAll.Process(this)) + { + SelectAll(); + UpdateTangents(); + return true; + } + else if (options.DeselectAll.Process(this)) + { + DeselectAll(); + UpdateTangents(); + return true; + } + else if (options.Delete.Process(this)) { - case KeyboardKeys.Delete: RemoveKeyframes(); return true; - case KeyboardKeys.A: - if (Root.GetKey(KeyboardKeys.Control)) - { - SelectAll(); - UpdateTangents(); - return true; - } - break; - case KeyboardKeys.C: - if (Root.GetKey(KeyboardKeys.Control)) - { - CopyKeyframes(); - return true; - } - break; - case KeyboardKeys.V: - if (Root.GetKey(KeyboardKeys.Control)) - { - KeyframesEditorUtils.Paste(this); - return true; - } - break; } + else if (options.Copy.Process(this)) + { + CopyKeyframes(); + return true; + } + else if (options.Paste.Process(this)) + { + KeyframesEditorUtils.Paste(this); + return true; + } + return false; } diff --git a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs index 3ede72503..ad84a75e0 100644 --- a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs +++ b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using FlaxEditor.CustomEditors; using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.Options; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; @@ -432,6 +433,7 @@ namespace FlaxEditor.GUI if (_editor.EnableKeyframesValueEdit) cm.AddButton("Edit all keyframes", () => _editor.EditAllKeyframes(this, location)); cm.AddButton("Select all keyframes", _editor.SelectAll).Enabled = _editor._points.Count > 0; + cm.AddButton("Deselect all keyframes", _editor.DeselectAll).Enabled = _editor._points.Count > 0; cm.AddButton("Copy all keyframes", () => { _editor.SelectAll(); @@ -1209,15 +1211,28 @@ namespace FlaxEditor.GUI } } + private void BulkSelectUpdate(bool select = true) + { + for (int i = 0; i < _points.Count; i++) + { + _points[i].IsSelected = select; + } + } + /// /// Selects all keyframes. /// public void SelectAll() { - for (int i = 0; i < _points.Count; i++) - { - _points[i].IsSelected = true; - } + BulkSelectUpdate(true); + } + + /// + /// Deselects all keyframes. + /// + public void DeselectAll() + { + BulkSelectUpdate(false); } /// @@ -1268,33 +1283,33 @@ namespace FlaxEditor.GUI if (base.OnKeyDown(key)) return true; - switch (key) + InputOptions options = Editor.Instance.Options.Options.Input; + if (options.SelectAll.Process(this)) + { + SelectAll(); + return true; + } + else if (options.DeselectAll.Process(this)) + { + DeselectAll(); + return true; + } + else if (options.Delete.Process(this)) { - case KeyboardKeys.Delete: RemoveKeyframes(); return true; - case KeyboardKeys.A: - if (Root.GetKey(KeyboardKeys.Control)) - { - SelectAll(); - return true; - } - break; - case KeyboardKeys.C: - if (Root.GetKey(KeyboardKeys.Control)) - { - CopyKeyframes(); - return true; - } - break; - case KeyboardKeys.V: - if (Root.GetKey(KeyboardKeys.Control)) - { - KeyframesEditorUtils.Paste(this); - return true; - } - break; } + else if (options.Copy.Process(this)) + { + CopyKeyframes(); + return true; + } + else if (options.Paste.Process(this)) + { + KeyframesEditorUtils.Paste(this); + return true; + } + return false; } diff --git a/Source/Editor/GUI/Tree/Tree.cs b/Source/Editor/GUI/Tree/Tree.cs index d01695abc..527053ab6 100644 --- a/Source/Editor/GUI/Tree/Tree.cs +++ b/Source/Editor/GUI/Tree/Tree.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using FlaxEditor.Options; using FlaxEngine; using FlaxEngine.Assertions; using FlaxEngine.GUI; @@ -315,10 +316,7 @@ namespace FlaxEditor.GUI.Tree } } - /// - /// Select all expanded nodes - /// - public void SelectAllExpanded() + private void BulkSelectUpdateExpanded(bool select = true) { if (_supportMultiSelect) { @@ -327,7 +325,8 @@ namespace FlaxEditor.GUI.Tree // Update selection Selection.Clear(); - WalkSelectExpandedTree(Selection, _children[0] as TreeNode); + if (select) + WalkSelectExpandedTree(Selection, _children[0] as TreeNode); // Check if changed if (Selection.Count != prev.Count || !Selection.SequenceEqual(prev)) @@ -338,6 +337,22 @@ namespace FlaxEditor.GUI.Tree } } + /// + /// Select all expanded nodes + /// + public void SelectAllExpanded() + { + BulkSelectUpdateExpanded(true); + } + + /// + /// Deselect all nodes + /// + public void DeselectAll() + { + BulkSelectUpdateExpanded(false); + } + /// public override void Update(float deltaTime) { @@ -472,14 +487,19 @@ namespace FlaxEditor.GUI.Tree // Check if can use multi selection if (_supportMultiSelect) { - bool isCtrlDown = Root.GetKey(KeyboardKeys.Control); + InputOptions options = Editor.Instance.Options.Options.Input; // Select all expanded nodes - if (key == KeyboardKeys.A && isCtrlDown) + if (options.SelectAll.Process(this)) { SelectAllExpanded(); return true; } + else if (options.DeselectAll.Process(this)) + { + DeselectAll(); + return true; + } } return base.OnKeyDown(key); diff --git a/Source/Editor/Modules/SceneEditingModule.cs b/Source/Editor/Modules/SceneEditingModule.cs index 831ebf3e0..faeca2520 100644 --- a/Source/Editor/Modules/SceneEditingModule.cs +++ b/Source/Editor/Modules/SceneEditingModule.cs @@ -60,13 +60,26 @@ namespace FlaxEditor.Modules { } + private void BulkScenesSelectUpdate(bool select = true) + { + // Blank list deselects all + Select(select ? Editor.Scene.Root.ChildNodes : new List()); + } + /// /// Selects all scenes. /// public void SelectAllScenes() { - // Select all scenes (linked to the root node) - Select(Editor.Scene.Root.ChildNodes); + BulkScenesSelectUpdate(true); + } + + /// + /// Deselects all scenes. + /// + public void DeselectAllScenes() + { + BulkScenesSelectUpdate(false); } /// diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index e1dc68fc2..6def96697 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -54,6 +54,7 @@ namespace FlaxEditor.Modules private ContextMenuButton _menuEditDelete; private ContextMenuButton _menuEditDuplicate; private ContextMenuButton _menuEditSelectAll; + private ContextMenuButton _menuEditDeselectAll; private ContextMenuButton _menuEditFind; private ContextMenuButton _menuSceneMoveActorToViewport; private ContextMenuButton _menuSceneAlignActorWithViewport; @@ -554,6 +555,7 @@ namespace FlaxEditor.Modules _menuEditDuplicate = cm.AddButton("Duplicate", inputOptions.Duplicate, Editor.SceneEditing.Duplicate); cm.AddSeparator(); _menuEditSelectAll = cm.AddButton("Select all", inputOptions.SelectAll, Editor.SceneEditing.SelectAllScenes); + _menuEditDeselectAll = cm.AddButton("Deselect all", inputOptions.DeselectAll, Editor.SceneEditing.DeselectAllScenes); _menuCreateParentForSelectedActors = cm.AddButton("Create parent for selected actors", Editor.SceneEditing.CreateParentForSelectedActors); _menuEditFind = cm.AddButton("Find", inputOptions.Search, Editor.Windows.SceneWin.Search); cm.AddSeparator(); @@ -673,6 +675,7 @@ namespace FlaxEditor.Modules _menuEditDelete.ShortKeys = inputOptions.Delete.ToString(); _menuEditDuplicate.ShortKeys = inputOptions.Duplicate.ToString(); _menuEditSelectAll.ShortKeys = inputOptions.SelectAll.ToString(); + _menuEditDeselectAll.ShortKeys = inputOptions.DeselectAll.ToString(); _menuEditFind.ShortKeys = inputOptions.Search.ToString(); _menuGamePlayGame.ShortKeys = inputOptions.Play.ToString(); _menuGamePlayCurrentScenes.ShortKeys = inputOptions.PlayCurrentScenes.ToString(); @@ -871,6 +874,7 @@ namespace FlaxEditor.Modules _menuEditDelete.Enabled = hasSthSelected; _menuEditDuplicate.Enabled = hasSthSelected; _menuEditSelectAll.Enabled = Level.IsAnySceneLoaded; + _menuEditDeselectAll.Enabled = hasSthSelected; control.PerformLayout(); } diff --git a/Source/Editor/Options/InputOptions.cs b/Source/Editor/Options/InputOptions.cs index cb79373b7..9bd556f20 100644 --- a/Source/Editor/Options/InputOptions.cs +++ b/Source/Editor/Options/InputOptions.cs @@ -56,6 +56,10 @@ namespace FlaxEditor.Options [EditorDisplay("Common"), EditorOrder(190)] public InputBinding SelectAll = new InputBinding(KeyboardKeys.A, KeyboardKeys.Control); + [DefaultValue(typeof(InputBinding), "Ctrl+Shift+A")] + [EditorDisplay("Common"), EditorOrder(195)] + public InputBinding DeselectAll = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift, KeyboardKeys.Control); + [DefaultValue(typeof(InputBinding), "F")] [EditorDisplay("Common"), EditorOrder(200)] public InputBinding FocusSelection = new InputBinding(KeyboardKeys.F); diff --git a/Source/Editor/Surface/VisjectSurface.cs b/Source/Editor/Surface/VisjectSurface.cs index e497cde23..78277dbe2 100644 --- a/Source/Editor/Surface/VisjectSurface.cs +++ b/Source/Editor/Surface/VisjectSurface.cs @@ -382,6 +382,7 @@ namespace FlaxEditor.Surface { new InputActionsContainer.Binding(options => options.Delete, Delete), new InputActionsContainer.Binding(options => options.SelectAll, SelectAll), + new InputActionsContainer.Binding(options => options.DeselectAll, DeselectAll), new InputActionsContainer.Binding(options => options.Copy, Copy), new InputActionsContainer.Binding(options => options.Paste, Paste), new InputActionsContainer.Binding(options => options.Cut, Cut), @@ -611,17 +612,14 @@ namespace FlaxEditor.Surface _context.MarkAsModified(graphEdited); } - /// - /// Selects all the nodes. - /// - public void SelectAll() + private void BulkSelectUpdate(bool select = true) { bool selectionChanged = false; for (int i = 0; i < _rootControl.Children.Count; i++) { - if (_rootControl.Children[i] is SurfaceControl control && !control.IsSelected) + if (_rootControl.Children[i] is SurfaceControl control && control.IsSelected != select) { - control.IsSelected = true; + control.IsSelected = select; selectionChanged = true; } } @@ -629,6 +627,22 @@ namespace FlaxEditor.Surface SelectionChanged?.Invoke(); } + /// + /// Selects all the nodes. + /// + public void SelectAll() + { + BulkSelectUpdate(true); + } + + /// + /// Deelects all the nodes. + /// + public void DeselectAll() + { + BulkSelectUpdate(false); + } + /// /// Clears the selection. /// diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index 7e2d9f628..b403c1489 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1305,6 +1305,7 @@ namespace FlaxEditor.Utilities inputActions.Add(options => options.Paste, Editor.Instance.SceneEditing.Paste); inputActions.Add(options => options.Duplicate, Editor.Instance.SceneEditing.Duplicate); inputActions.Add(options => options.SelectAll, Editor.Instance.SceneEditing.SelectAllScenes); + inputActions.Add(options => options.DeselectAll, Editor.Instance.SceneEditing.DeselectAllScenes); inputActions.Add(options => options.Delete, Editor.Instance.SceneEditing.Delete); inputActions.Add(options => options.Search, () => Editor.Instance.Windows.SceneWin.Search()); inputActions.Add(options => options.MoveActorToViewport, Editor.Instance.UI.MoveActorToViewport); diff --git a/Source/Editor/Windows/DebugLogWindow.cs b/Source/Editor/Windows/DebugLogWindow.cs index 53232e490..33946761a 100644 --- a/Source/Editor/Windows/DebugLogWindow.cs +++ b/Source/Editor/Windows/DebugLogWindow.cs @@ -170,6 +170,8 @@ namespace FlaxEditor.Windows /// public override bool OnKeyDown(KeyboardKeys key) { + InputOptions options = FlaxEditor.Editor.Instance.Options.Options.Input; + // Up if (key == KeyboardKeys.ArrowUp) { @@ -200,7 +202,7 @@ namespace FlaxEditor.Windows Open(); } // Ctrl+C - else if (key == KeyboardKeys.C && Root.GetKey(KeyboardKeys.Control)) + else if (options.Copy.Process(this)) { Copy(); return true; diff --git a/Source/Editor/Windows/Search/ContentSearchWindow.cs b/Source/Editor/Windows/Search/ContentSearchWindow.cs index 716c61b9e..0e3d1efdc 100644 --- a/Source/Editor/Windows/Search/ContentSearchWindow.cs +++ b/Source/Editor/Windows/Search/ContentSearchWindow.cs @@ -12,6 +12,7 @@ using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.Docking; using FlaxEditor.GUI.Input; using FlaxEditor.GUI.Tree; +using FlaxEditor.Options; using FlaxEditor.Scripting; using FlaxEditor.Surface; using FlaxEditor.Windows; @@ -142,6 +143,7 @@ namespace FlaxEngine.Windows.Search /// public override bool OnKeyDown(KeyboardKeys key) { + InputOptions options = FlaxEditor.Editor.Instance.Options.Options.Input; if (IsFocused) { if (key == KeyboardKeys.Return && Navigate != null) @@ -149,7 +151,7 @@ namespace FlaxEngine.Windows.Search Navigate.Invoke(this); return true; } - if (key == KeyboardKeys.C && Root.GetKey(KeyboardKeys.Control)) + if (options.Copy.Process(this)) { Clipboard.Text = Text; return true; diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 6f6daff5a..c22099011 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -1,6 +1,9 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. using System; +#if FLAX_EDITOR +using FlaxEditor.Options; +#endif using FlaxEngine.Assertions; using FlaxEngine.Utilities; @@ -1296,6 +1299,42 @@ namespace FlaxEngine.GUI bool ctrDown = window.GetKey(KeyboardKeys.Control); KeyDown?.Invoke(key); + // Handle controls that have bindings +#if FLAX_EDITOR + InputOptions options = FlaxEditor.Editor.Instance.Options.Options.Input; + if (options.Copy.Process(this)) + { + Copy(); + return true; + } + else if (options.Paste.Process(this)) + { + Paste(); + return true; + } + else if (options.Duplicate.Process(this)) + { + Duplicate(); + return true; + } + else if (options.Cut.Process(this)) + { + Cut(); + return true; + } + else if (options.SelectAll.Process(this)) + { + SelectAll(); + return true; + } + else if (options.DeselectAll.Process(this)) + { + Deselect(); + return true; + } +#endif + + // Handle controls without bindings switch (key) { case KeyboardKeys.ArrowRight: