Merge branch 'shift-select-nodes' of https://github.com/Tryibion/FlaxEngine into Tryibion-shift-select-nodes

# Conflicts:
#	Source/Editor/GUI/Tree/Tree.cs
This commit is contained in:
Wojtek Figat
2025-08-19 18:45:33 +02:00

View File

@@ -41,6 +41,7 @@ namespace FlaxEditor.GUI.Tree
private Margin _margin; private Margin _margin;
private bool _autoSize = true; private bool _autoSize = true;
private bool _deferLayoutUpdate = false; private bool _deferLayoutUpdate = false;
private TreeNode _lastSelectedNode;
/// <summary> /// <summary>
/// The TreeNode that is being dragged over. This could have a value when not dragging. /// The TreeNode that is being dragged over. This could have a value when not dragging.
@@ -67,7 +68,7 @@ namespace FlaxEditor.GUI.Tree
/// Gets the first selected node or null. /// Gets the first selected node or null.
/// </summary> /// </summary>
public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null; public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null;
/// <summary> /// <summary>
/// Allow nodes to Draw the root tree line. /// Allow nodes to Draw the root tree line.
/// </summary> /// </summary>
@@ -392,20 +393,27 @@ namespace FlaxEditor.GUI.Tree
{ {
if (_deferLayoutUpdate) if (_deferLayoutUpdate)
FlushPendingPerformLayout(); FlushPendingPerformLayout();
var window = Root;
bool shiftDown = window.GetKey(KeyboardKeys.Shift);
bool keyUpArrow = window.GetKey(KeyboardKeys.ArrowUp);
bool keyDownArrow = window.GetKey(KeyboardKeys.ArrowDown);
var node = SelectedNode; // Use last selection for last selected node if sift is down
if (shiftDown)
_lastSelectedNode ??= Selection[^1];
var node = _lastSelectedNode ?? SelectedNode;
if (Selection.Count == 0)
_lastSelectedNode = null;
// Check if has focus and if any node is focused and it isn't a root // Check if has focus and if any node is focused and it isn't a root
if (ContainsFocus && node != null && node.AutoFocus) if (ContainsFocus && node != null && node.AutoFocus)
{ {
var window = Root;
if (window.GetKeyDown(KeyboardKeys.ArrowUp) || window.GetKeyDown(KeyboardKeys.ArrowDown)) if (window.GetKeyDown(KeyboardKeys.ArrowUp) || window.GetKeyDown(KeyboardKeys.ArrowDown))
_keyUpdateTime = KeyUpdateTimeout; _keyUpdateTime = KeyUpdateTimeout;
if (_keyUpdateTime >= KeyUpdateTimeout && window is WindowRootControl windowRoot && windowRoot.Window.IsFocused) if (_keyUpdateTime >= KeyUpdateTimeout && window is WindowRootControl windowRoot && windowRoot.Window.IsFocused)
{ {
bool keyUpArrow = window.GetKey(KeyboardKeys.ArrowUp);
bool keyDownArrow = window.GetKey(KeyboardKeys.ArrowDown);
// Check if arrow flags are different // Check if arrow flags are different
if (keyDownArrow != keyUpArrow) if (keyDownArrow != keyUpArrow)
{ {
@@ -415,24 +423,38 @@ namespace FlaxEditor.GUI.Tree
Assert.AreNotEqual(-1, myIndex); Assert.AreNotEqual(-1, myIndex);
// Up // Up
TreeNode toSelect = null; List<TreeNode> toSelect = new List<TreeNode>();
if (shiftDown && _supportMultiSelect)
{
toSelect.AddRange(Selection);
}
if (keyUpArrow) if (keyUpArrow)
{ {
if (myIndex == 0) if (myIndex == 0)
{ {
// Select parent // Select parent
toSelect = parentNode; if (toSelect.Contains(parentNode))
toSelect.Remove(node);
else
toSelect.Add(parentNode);
_lastSelectedNode = parentNode;
} }
else else
{ {
// Select previous parent child // Select previous parent child
toSelect = nodeParent.GetChild(myIndex - 1) as TreeNode; var select = nodeParent.GetChild(myIndex - 1) as TreeNode;
// Select last child if is valid and expanded and has any children // Select last child if is valid and expanded and has any children
if (toSelect != null && toSelect.IsExpanded && toSelect.HasAnyVisibleChild) if (select != null && select.IsExpanded && select.HasAnyVisibleChild)
{ {
toSelect = toSelect.GetChild(toSelect.ChildrenCount - 1) as TreeNode; select = select.GetChild(select.ChildrenCount - 1) as TreeNode;
} }
if (toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
} }
} }
// Down // Down
@@ -441,32 +463,48 @@ namespace FlaxEditor.GUI.Tree
if (node.IsExpanded && node.HasAnyVisibleChild) if (node.IsExpanded && node.HasAnyVisibleChild)
{ {
// Select the first child // Select the first child
toSelect = node.GetChild(0) as TreeNode; var select = node.GetChild(0) as TreeNode;
if (toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
} }
else if (myIndex == nodeParent.ChildrenCount - 1) else if (myIndex == nodeParent.ChildrenCount - 1)
{ {
// Select next node after parent // Select next node after parent
while (parentNode != null && toSelect == null) TreeNode select = null;
while (parentNode != null && select == null)
{ {
int parentIndex = parentNode.IndexInParent; int parentIndex = parentNode.IndexInParent;
if (parentIndex != -1 && parentIndex < parentNode.Parent.ChildrenCount - 1) if (parentIndex != -1 && parentIndex < parentNode.Parent.ChildrenCount - 1)
{ {
toSelect = parentNode.Parent.GetChild(parentIndex + 1) as TreeNode; select = parentNode.Parent.GetChild(parentIndex + 1) as TreeNode;
} }
parentNode = parentNode.Parent as TreeNode; parentNode = parentNode.Parent as TreeNode;
} }
if (toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
} }
else else
{ {
// Select next parent child // Select next parent child
toSelect = nodeParent.GetChild(myIndex + 1) as TreeNode; var select = nodeParent.GetChild(myIndex + 1) as TreeNode;
if (toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
} }
} }
if (toSelect != null && toSelect.AutoFocus) if (toSelect.Count > 0)
{ {
// Select // Select
Select(toSelect); Select(toSelect);
toSelect.Focus(); _lastSelectedNode?.Focus();
} }
// Reset time // Reset time