Asset Browser: Selection rectangle works with scrolling

This commit is contained in:
Simon Lübeß
2025-07-06 15:15:21 +02:00
parent 1e614eb944
commit 3e9c9e8202
2 changed files with 44 additions and 47 deletions
@@ -276,7 +276,7 @@ namespace GlitchyEditor.EditWindows
//if (!_selectionRectStart.X.IsNaN) //if (!_selectionRectStart.X.IsNaN)
{ {
ImGui.TextUnformatted(_selectionRect.ToString(.. scope .())); ImGui.TextUnformatted(_rectangleSelection.ToString(.. scope .()));
} }
ImGui.End(); ImGui.End();
@@ -681,10 +681,7 @@ namespace GlitchyEditor.EditWindows
const float2 padding = .(24, 24); const float2 padding = .(24, 24);
//private Rectangle _selectionRect = .(float.NaN, -1); private ImGui.RectangleSelectionData _rectangleSelection;
private float2 _selectionRectStart = float.NaN;
private float2 _selectionRectEnd = float.NaN;
private float4 _selectionRect;
/// Renders the contents of _currentDirectory. Returns the node of the current directory, or null if the browser isn't in a directory. /// Renders the contents of _currentDirectory. Returns the node of the current directory, or null if the browser isn't in a directory.
private void DrawCurrentDirectory(TreeNode<AssetNode> currentDirectoryNode) private void DrawCurrentDirectory(TreeNode<AssetNode> currentDirectoryNode)
@@ -692,7 +689,6 @@ namespace GlitchyEditor.EditWindows
if (ImGui.IsWindowHovered()) if (ImGui.IsWindowHovered())
{ {
// TODO: Come up with a good hotkey system... // TODO: Come up with a good hotkey system...
var currentDirectoryNode;
if (Input.IsKeyPressed(.Alt)) if (Input.IsKeyPressed(.Alt))
{ {
if (Input.IsKeyPressing(.Up)) if (Input.IsKeyPressing(.Up))
@@ -722,16 +718,15 @@ namespace GlitchyEditor.EditWindows
} }
} }
List<TreeNode<AssetNode>> directoryEntries = null; List<TreeNode<AssetNode>> directoryEntries = scope List<TreeNode<AssetNode>>();
StringView searchFilter = StringView(&_filesFilter); StringView searchFilter = StringView(&_filesFilter);
if (_searchEverywhere && searchFilter.Length > 0) if (_searchEverywhere && searchFilter.Length > 0)
{ {
directoryEntries = scope:: List<TreeNode<AssetNode>>();
_manager.AssetHierarchy.[Friend]_assetRootNode.ForEach(scope (node) => _manager.AssetHierarchy.[Friend]_assetRootNode.ForEach(scope (node) =>
{ {
if (node->Name.Contains(searchFilter, true)) if (node->Name.Contains(searchFilter, ignoreCase: true))
{ {
directoryEntries.Add(node); directoryEntries.Add(node);
} }
@@ -745,18 +740,17 @@ namespace GlitchyEditor.EditWindows
return; return;
} }
directoryEntries = scope:: List<TreeNode<AssetNode>>(); currentDirectoryNode.Children.Where((entry) => entry->Name.Contains(searchFilter, true)).ToList(directoryEntries);
currentDirectoryNode.Children.CopyTo(directoryEntries);
} }
directoryEntries.Sort((entry1, entry2) => { directoryEntries.Sort((entry1, entry2) => {
// Try to sort so that directories are before files. // Sort so that directories are before files.
int score = entry2->IsDirectory <=> entry1->IsDirectory; int score = entry2->IsDirectory <=> entry1->IsDirectory;
if (score == 0) if (score == 0)
{ {
// If both are either directories or files sort alphabetically. // If both are either directories or files sort alphabetically.
score = StringView.Compare(entry1->Name, entry2->Name, true); score = StringView.Compare(entry1->Name, entry2->Name, ignoreCase: true);
} }
return score; return score;
@@ -771,9 +765,6 @@ namespace GlitchyEditor.EditWindows
for (var entry in directoryEntries) for (var entry in directoryEntries)
{ {
if (!entry->Name.Contains(searchFilter, true))
continue;
ImGui.PushID(entry->Path); ImGui.PushID(entry->Path);
DrawDirectoryEntry(entry); DrawDirectoryEntry(entry);
@@ -788,7 +779,7 @@ namespace GlitchyEditor.EditWindows
ImGui.PopID(); ImGui.PopID();
} }
ImGui.BeginRectangleSelection(ref _selectionRect, ImGui.IsMouseDown(.Left) || ImGui.IsMouseDown(.Right)); ImGui.BeginRectangleSelection(ref _rectangleSelection, ImGui.IsMouseDown(.Left) || ImGui.IsMouseDown(.Right));
if (_showNewFile) if (_showNewFile)
{ {
@@ -903,9 +894,9 @@ namespace GlitchyEditor.EditWindows
ImGui.ImageButton("FileImage", image, (.)IconSize); ImGui.ImageButton("FileImage", image, (.)IconSize);
if (ImGui.IsRectangleSelecting(ref _selectionRect)) if (ImGui.IsRectangleSelecting(ref _rectangleSelection))
{ {
if (ImGui.IsInRectangleSelection(ref _selectionRect)) if (ImGui.IsInRectangleSelection(ref _rectangleSelection))
{ {
SelectFile(entry->Path, false, .SingleFile, false); SelectFile(entry->Path, false, .SingleFile, false);
} }
@@ -1166,11 +1157,11 @@ namespace GlitchyEditor.EditWindows
List<TreeNode<AssetNode>> entries = new:ScopedAlloc! .(_selectedFiles.Count); List<TreeNode<AssetNode>> entries = new:ScopedAlloc! .(_selectedFiles.Count);
_selectedFiles.Select(scope (e) => { _selectedFiles.Select((e) => {
return _manager.AssetHierarchy.GetNodeFromPath(e); return _manager.AssetHierarchy.GetNodeFromPath(e);
}).Where(scope (e) => e case .Ok).Select(scope (e) => e.Get()).ToList(entries); }).Where((e) => e case .Ok).Select((e) => e.Get()).ToList(entries);
bool sameParent = entries.Select(scope (e) => e.Parent).Distinct().Count() == 1; bool sameParent = entries.Select((e) => e.Parent).Distinct().Count() == 1;
TreeNode<AssetNode> firstEntry = entries.First(); TreeNode<AssetNode> firstEntry = entries.First();
TreeNode<AssetNode> parent = sameParent ? entries.First().Parent : null; TreeNode<AssetNode> parent = sameParent ? entries.First().Parent : null;
+31 -25
View File
@@ -51,61 +51,70 @@ namespace ImGui
NoRender NoRender
} }
public static bool BeginRectangleSelection(ref float4 selectionRectangle, bool isMouseDown, RectangleSelectionFlags flags = .None) public struct RectangleSelectionData
{ {
/*let storage = ImGui.GetStateStorage(); public float4 SelectionRectangle;
ref float selectionRectX = ref *storage.GetFloatRef(ImGui.GetID("SelectionRect.X"), float.NaN);*/ public float2 StartPosition;
public bool IsSelecting;
}
public static bool BeginRectangleSelection(ref RectangleSelectionData selectionData, bool isMouseDown, RectangleSelectionFlags flags = .None)
{
float2 minRegion = (.)ImGui.GetWindowPos(); float2 minRegion = (.)ImGui.GetWindowPos();
float2 maxRegion = (.)ImGui.GetCursorPos() + minRegion + (float2)ImGui.GetContentRegionAvail(); float2 maxRegion = (.)ImGui.GetCursorPos() + minRegion + (float2)ImGui.GetContentRegionAvail();
ImGui.DrawRect((.)minRegion, (.)maxRegion, ImGui.Color(0,1f,0)); // ImGui.DrawRect((.)minRegion, (.)maxRegion, ImGui.Color(0,1f,0));
bool selectionValid() => !any(isnan(selectionRectangle));
if (isMouseDown) if (isMouseDown)
{ {
if (!selectionValid() && IsWindowHovered() && !IsAnyItemHovered()) if (!selectionData.IsSelecting && IsWindowHovered() && !IsAnyItemHovered())
{ {
selectionRectangle.XY = (float2)ImGui.GetMousePos(); selectionData.StartPosition = (float2)ImGui.GetMousePos() - (float2)ImGui.GetCursorScreenPos();
selectionData.IsSelecting = true;
} }
selectionRectangle.ZW = (.)ImGui.GetMousePos(); selectionData.SelectionRectangle.ZW = (float2)ImGui.GetMousePos();
} }
else else
{ {
selectionRectangle.XYZW = float.NaN; selectionData.IsSelecting = false;
return false; return false;
} }
selectionData.SelectionRectangle.XY = (float2)selectionData.StartPosition + (float2)ImGui.GetCursorScreenPos();
selectionRectangle.XY = clamp(selectionRectangle.XY, minRegion, maxRegion); selectionData.SelectionRectangle.ZW = clamp(selectionData.SelectionRectangle.ZW, minRegion, maxRegion);
selectionRectangle.ZW = clamp(selectionRectangle.ZW, minRegion, maxRegion);
if (!flags.HasFlag(.NoRender) && selectionValid())
if (!flags.HasFlag(.NoRender) && selectionData.IsSelecting)
{ {
let drawList = ImGui.GetForegroundDrawList(); let drawList = ImGui.GetForegroundDrawList();
drawList.AddRect((.)selectionRectangle.XY, (.)selectionRectangle.ZW, ImGui.GetColorU32(ImGui.Color(0, 130, 216, 255).Value));
drawList.AddRectFilled((.)selectionRectangle.XY, (.)selectionRectangle.ZW, ImGui.GetColorU32(ImGui.Color(0, 130, 216, 50).Value)); float2 clampedStartPoint = clamp(selectionData.SelectionRectangle.XY, minRegion, maxRegion);
drawList.AddRect((.)clampedStartPoint.XY, (.)selectionData.SelectionRectangle.ZW, ImGui.GetColorU32(ImGui.Color(0, 130, 216, 255).Value));
drawList.AddRectFilled((.)clampedStartPoint.XY, (.)selectionData.SelectionRectangle.ZW, ImGui.GetColorU32(ImGui.Color(0, 130, 216, 50).Value));
} }
return true; return true;
} }
/// Returns true if the user is currently doing a rectangle selection /// Returns true if the user is currently doing a rectangle selection
public static bool IsRectangleSelecting(ref float4 selectionRectangle) public static bool IsRectangleSelecting(ref RectangleSelectionData selectionData)
{ {
return !any(isnan(selectionRectangle)); return selectionData.IsSelecting;
} }
/// Returns true if the current item is intersecting the selection rectangle /// Returns true if the current item is intersecting the selection rectangle
public static bool IsInRectangleSelection(ref float4 selectionRectangle) public static bool IsInRectangleSelection(ref RectangleSelectionData selectionData)
{ {
if (any(isnan(selectionRectangle))) if (!selectionData.IsSelecting)
{ {
return false; return false;
} }
ImGui.DebugDrawItemRect(); // ImGui.DebugDrawItemRect();
float2 minRect = (.)ImGui.GetItemRectMin(); float2 minRect = (.)ImGui.GetItemRectMin();
float2 maxRect = (.)ImGui.GetItemRectMax(); float2 maxRect = (.)ImGui.GetItemRectMax();
@@ -116,11 +125,8 @@ namespace ImGui
Rectangle itemRectangle = .(topLeft, 0); Rectangle itemRectangle = .(topLeft, 0);
itemRectangle.BottomRight = bottomRight; itemRectangle.BottomRight = bottomRight;
let drawList = ImGui.GetForegroundDrawList(); float2 selectionTopLeft = min(selectionData.SelectionRectangle.XY, selectionData.SelectionRectangle.ZW);
drawList.AddRect((.)itemRectangle.TopLeft, (.)itemRectangle.BottomRight, ImGui.GetColorU32(ImGui.Color(0, 130, 216, 255).Value)); float2 selectionTottomRight = max(selectionData.SelectionRectangle.XY, selectionData.SelectionRectangle.ZW);
float2 selectionTopLeft = min(selectionRectangle.XY, selectionRectangle.ZW);
float2 selectionTottomRight = max(selectionRectangle.XY, selectionRectangle.ZW);
Rectangle rect = .(selectionTopLeft, 0); Rectangle rect = .(selectionTopLeft, 0);
rect.BottomRight = selectionTottomRight; rect.BottomRight = selectionTottomRight;