mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Basic rectangle selection in content browser
This commit is contained in:
@@ -59,9 +59,77 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
public const String s_WindowTitle = "Content Browser";
|
public const String s_WindowTitle = "Content Browser";
|
||||||
|
|
||||||
private append String _currentDirectory = .();
|
class History
|
||||||
|
{
|
||||||
|
AssetHierarchy _hierarchy;
|
||||||
|
|
||||||
//private append String _selectedFile = .();
|
public AssetHierarchy AssetHierarchy
|
||||||
|
{
|
||||||
|
get => _hierarchy;
|
||||||
|
set => _hierarchy = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private append List<String> _history = .() ~ ClearAndDeleteItems!(_);
|
||||||
|
private int _currentIndex = -1;
|
||||||
|
|
||||||
|
public StringView CurrentDirectoryPath => _currentIndex >= 0 ? _history[_currentIndex] : "";
|
||||||
|
|
||||||
|
public void Navigate(StringView nextPath)
|
||||||
|
{
|
||||||
|
_currentIndex++;
|
||||||
|
_history.Insert(_currentIndex, new String(nextPath));
|
||||||
|
|
||||||
|
TrimHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TrimHistory()
|
||||||
|
{
|
||||||
|
while (_history.Count > (_currentIndex + 1))
|
||||||
|
{
|
||||||
|
delete _history.PopBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Replace(StringView nextPath)
|
||||||
|
{
|
||||||
|
if (_currentIndex == -1)
|
||||||
|
{
|
||||||
|
_currentIndex = 0;
|
||||||
|
_history.AddFront(new String(nextPath));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_history[_currentIndex].Set(nextPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrimHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Back()
|
||||||
|
{
|
||||||
|
if (_currentIndex > 0)
|
||||||
|
{
|
||||||
|
_currentIndex--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Forward()
|
||||||
|
{
|
||||||
|
if ((_currentIndex + 1) < _history.Count)
|
||||||
|
{
|
||||||
|
_currentIndex++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private append History _directoryHistory = .();
|
||||||
|
|
||||||
|
public StringView CurrentDirectory => _directoryHistory.CurrentDirectoryPath;
|
||||||
|
|
||||||
private append List<String> _selectedFiles = .() ~ ClearAndDeleteItems!(_);
|
private append List<String> _selectedFiles = .() ~ ClearAndDeleteItems!(_);
|
||||||
|
|
||||||
@@ -136,21 +204,48 @@ namespace GlitchyEditor.EditWindows
|
|||||||
protected override void InternalShow()
|
protected override void InternalShow()
|
||||||
{
|
{
|
||||||
_manager.Update();
|
_manager.Update();
|
||||||
|
|
||||||
|
// Show History
|
||||||
|
if (ImGui.Begin("Debug History"))
|
||||||
|
{
|
||||||
|
for (String path in _directoryHistory.[Friend]_history)
|
||||||
|
{
|
||||||
|
if (_directoryHistory.CurrentDirectoryPath === StringView(path))
|
||||||
|
{
|
||||||
|
ImGui.Text("==>");
|
||||||
|
ImGui.SameLine();
|
||||||
|
}
|
||||||
|
ImGui.Text(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (!_selectionRectStart.X.IsNaN)
|
||||||
|
{
|
||||||
|
ImGui.TextUnformatted(_selectionRect.ToString(.. scope .()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we are in an existing directory.
|
// Make sure we are in an existing directory.
|
||||||
if (!_manager.AssetHierarchy.FileExists(_currentDirectory))
|
if (!_manager.AssetHierarchy.FileExists(CurrentDirectory))
|
||||||
{
|
{
|
||||||
_currentDirectory.Set(_manager.AssetDirectory);
|
_directoryHistory.Replace(_manager.AssetDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let originalWindowPadding = ImGui.GetStyle().WindowPadding;
|
||||||
|
ImGui.PushStyleVar(.WindowPadding, float2(0,0));
|
||||||
|
defer ImGui.PopStyleVar();
|
||||||
|
|
||||||
|
if(!ImGui.Begin(s_WindowTitle, &_open, .None))
|
||||||
|
{
|
||||||
|
ImGui.End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + originalWindowPadding.y);
|
||||||
|
|
||||||
// Update selection modifies
|
// Update selection modifies
|
||||||
{
|
{
|
||||||
if(!ImGui.Begin(s_WindowTitle, &_open, .None))
|
|
||||||
{
|
|
||||||
ImGui.End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_addToSelection = Input.IsKeyPressed(.Control);
|
_addToSelection = Input.IsKeyPressed(.Control);
|
||||||
|
|
||||||
if (Input.IsKeyPressed(.Shift))
|
if (Input.IsKeyPressed(.Shift))
|
||||||
@@ -163,7 +258,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove paths that no longer exist.
|
// Remove paths from selection that no longer exist.
|
||||||
for (String path in _selectedFiles)
|
for (String path in _selectedFiles)
|
||||||
{
|
{
|
||||||
Result<TreeNode<AssetNode>> node = _manager.AssetHierarchy.GetNodeFromPath(path);
|
Result<TreeNode<AssetNode>> node = _manager.AssetHierarchy.GetNodeFromPath(path);
|
||||||
@@ -223,9 +318,12 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
if (ImGui.BeginChild("Files"))
|
if (ImGui.BeginChild("Files"))
|
||||||
{
|
{
|
||||||
TreeNode<AssetNode> currentDirectoryNode = TrySilent!(_manager.AssetHierarchy.GetNodeFromPath(_currentDirectory));
|
Result<TreeNode<AssetNode>> currentDirectoryNode = _manager.AssetHierarchy.GetNodeFromPath(_directoryHistory.CurrentDirectoryPath);
|
||||||
|
|
||||||
DrawCurrentDirectory(currentDirectoryNode);
|
if (currentDirectoryNode case .Ok(TreeNode<AssetNode> currentDirectory))
|
||||||
|
{
|
||||||
|
DrawCurrentDirectory(currentDirectoryNode);
|
||||||
|
}
|
||||||
|
|
||||||
// Context menu when clicking on the background.
|
// Context menu when clicking on the background.
|
||||||
if (ImGui.BeginPopupContextWindow())
|
if (ImGui.BeginPopupContextWindow())
|
||||||
@@ -235,8 +333,16 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
|
|
||||||
FileDropTarget(currentDirectoryNode, .External);
|
if (ImGui.IsItemClicked(.Left | .Right))
|
||||||
|
{
|
||||||
|
_selectedFiles.ClearAndDeleteItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentDirectoryNode case .Ok(TreeNode<AssetNode> currentDirectory))
|
||||||
|
{
|
||||||
|
FileDropTarget(currentDirectory, .External);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndTable();
|
ImGui.EndTable();
|
||||||
@@ -258,14 +364,14 @@ namespace GlitchyEditor.EditWindows
|
|||||||
Range
|
Range
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectFile(StringView fullFilePath, bool clearOldSelection, SelectionMode mode)
|
private void SelectFile(StringView fullFilePath, bool clearOldSelection, SelectionMode mode, bool toggle = true)
|
||||||
{
|
{
|
||||||
if (clearOldSelection)
|
if (clearOldSelection)
|
||||||
{
|
{
|
||||||
_selectedFiles.ClearAndDeleteItems();
|
_selectedFiles.ClearAndDeleteItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == .SingleFile)
|
if (mode == .SingleFile && toggle)
|
||||||
{
|
{
|
||||||
if (IsFileSelected(fullFilePath))
|
if (IsFileSelected(fullFilePath))
|
||||||
{
|
{
|
||||||
@@ -277,6 +383,13 @@ namespace GlitchyEditor.EditWindows
|
|||||||
_selectedFiles.Add(new String(fullFilePath));
|
_selectedFiles.Add(new String(fullFilePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mode == .SingleFile && !toggle)
|
||||||
|
{
|
||||||
|
if (!IsFileSelected(fullFilePath))
|
||||||
|
{
|
||||||
|
_selectedFiles.Add(new String(fullFilePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (mode == .Range)
|
else if (mode == .Range)
|
||||||
{
|
{
|
||||||
if (IsFileSelected(fullFilePath))
|
if (IsFileSelected(fullFilePath))
|
||||||
@@ -295,6 +408,12 @@ namespace GlitchyEditor.EditWindows
|
|||||||
OnFileSelected(this, fullFilePath);
|
OnFileSelected(this, fullFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DeselectFile(StringView fullFilePath)
|
||||||
|
{
|
||||||
|
String oldPath = TrySilent!(_selectedFiles.GetAndRemoveAlt(fullFilePath));
|
||||||
|
delete oldPath;
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawSearchBar()
|
private void DrawSearchBar()
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted("Search:");
|
ImGui.TextUnformatted("Search:");
|
||||||
@@ -309,7 +428,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
if (ImGui.MenuItem("Open in file browser..."))
|
if (ImGui.MenuItem("Open in file browser..."))
|
||||||
{
|
{
|
||||||
if (Path.OpenFolder(_currentDirectory) case .Err)
|
if (Path.OpenFolder(CurrentDirectory) case .Err)
|
||||||
Log.EngineLogger.Error("Failed to open directory in file browser.");
|
Log.EngineLogger.Error("Failed to open directory in file browser.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,14 +438,14 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
if (ImGui.MenuItem("Full path"))
|
if (ImGui.MenuItem("Full path"))
|
||||||
{
|
{
|
||||||
ImGui.SetClipboardText(_currentDirectory);
|
ImGui.SetClipboardText(CurrentDirectory.ToScopeCStr!());
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.AttachTooltip("Copies the full file path of the current folder.");
|
ImGui.AttachTooltip("Copies the full file path of the current folder.");
|
||||||
|
|
||||||
if (ImGui.MenuItem("Asset identifier"))
|
if (ImGui.MenuItem("Asset identifier"))
|
||||||
{
|
{
|
||||||
Result<TreeNode<AssetNode>> assetNode = _manager.AssetHierarchy.GetNodeFromPath(_currentDirectory);
|
Result<TreeNode<AssetNode>> assetNode = _manager.AssetHierarchy.GetNodeFromPath(CurrentDirectory);
|
||||||
|
|
||||||
if (assetNode case .Ok(let treeNode))
|
if (assetNode case .Ok(let treeNode))
|
||||||
{
|
{
|
||||||
@@ -404,14 +523,14 @@ namespace GlitchyEditor.EditWindows
|
|||||||
/// Creates a new asset with the given creator
|
/// Creates a new asset with the given creator
|
||||||
private void CreateAsset()
|
private void CreateAsset()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(_currentDirectory))
|
if (!Directory.Exists(CurrentDirectory))
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Directory {_currentDirectory} doesn't exist.");
|
Log.EngineLogger.Error($"Directory {CurrentDirectory} doesn't exist.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String currentFile = scope String();
|
String currentFile = scope String();
|
||||||
Path.Combine(currentFile, _currentDirectory, StringView(&_newFileName));
|
Path.Combine(currentFile, CurrentDirectory, StringView(&_newFileName));
|
||||||
|
|
||||||
// Add file extension, if necessary
|
// Add file extension, if necessary
|
||||||
if (!currentFile.EndsWith(_newFileCreator.FileExtension))
|
if (!currentFile.EndsWith(_newFileCreator.FileExtension))
|
||||||
@@ -459,7 +578,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
if(tree.Children.Where(scope (node) => node->IsDirectory).Count() == 0)
|
if(tree.Children.Where(scope (node) => node->IsDirectory).Count() == 0)
|
||||||
flags |= .Leaf;
|
flags |= .Leaf;
|
||||||
|
|
||||||
if (tree->Path == _currentDirectory)
|
if (tree->Path == CurrentDirectory)
|
||||||
flags |= .Selected;
|
flags |= .Selected;
|
||||||
|
|
||||||
// TODO: this kinda works, but the user should be able to close the directory
|
// TODO: this kinda works, but the user should be able to close the directory
|
||||||
@@ -475,7 +594,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
if (!ImGui.IsItemToggledOpen() && ImGui.IsItemClicked(.Left))
|
if (!ImGui.IsItemToggledOpen() && ImGui.IsItemClicked(.Left))
|
||||||
{
|
{
|
||||||
_currentDirectory.Set(tree->Path);
|
_directoryHistory.Navigate(tree->Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isOpen)
|
if(isOpen)
|
||||||
@@ -493,21 +612,40 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
const float2 padding = .(24, 24);
|
const float2 padding = .(24, 24);
|
||||||
|
|
||||||
|
//private Rectangle _selectionRect = .(float.NaN, -1);
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
var currentDirectoryNode;
|
var currentDirectoryNode;
|
||||||
if (Input.IsKeyPressed(.Alt) && Input.IsKeyPressing(.Up))
|
if (Input.IsKeyPressed(.Alt))
|
||||||
{
|
{
|
||||||
if (currentDirectoryNode.Parent != _manager.AssetHierarchy.RootNode)
|
if (Input.IsKeyPressing(.Up))
|
||||||
{
|
{
|
||||||
_currentDirectory.Set(currentDirectoryNode.Parent->Path);
|
if (currentDirectoryNode.Parent != _manager.AssetHierarchy.RootNode)
|
||||||
|
{
|
||||||
|
_directoryHistory.Navigate(currentDirectoryNode.Parent->Path);
|
||||||
|
|
||||||
|
_selectedFiles.ClearAndDeleteItems();
|
||||||
|
currentDirectoryNode = currentDirectoryNode.Parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_selectedFiles.ClearAndDeleteItems();
|
if (Input.IsKeyPressing(.Left))
|
||||||
currentDirectoryNode = currentDirectoryNode.Parent;
|
{
|
||||||
|
_directoryHistory.Back();
|
||||||
|
}
|
||||||
|
if (Input .IsKeyPressing(.Right))
|
||||||
|
{
|
||||||
|
_directoryHistory.Forward();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.BeginRectangleSelection(ref _selectionRect, ImGui.IsMouseDown(.Left) || ImGui.IsMouseDown(.Right));
|
||||||
|
|
||||||
List<TreeNode<AssetNode>> directoryEntries = null;
|
List<TreeNode<AssetNode>> directoryEntries = null;
|
||||||
|
|
||||||
ImGui.Style* style = ImGui.GetStyle();
|
ImGui.Style* style = ImGui.GetStyle();
|
||||||
@@ -661,7 +799,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
EditorLayer.SetDropEffect(.Copy);
|
EditorLayer.SetDropEffect(.Copy);
|
||||||
|
|
||||||
if (dropTarget->Path == _currentDirectory)
|
if (dropTarget->Path == CurrentDirectory)
|
||||||
{
|
{
|
||||||
ImGui.SetTooltip($"Copy here ({dropTarget->Name})");
|
ImGui.SetTooltip($"Copy here ({dropTarget->Name})");
|
||||||
}
|
}
|
||||||
@@ -712,6 +850,18 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
ImGui.ImageButton("FileImage", image, (.)IconSize);
|
ImGui.ImageButton("FileImage", image, (.)IconSize);
|
||||||
|
|
||||||
|
if (ImGui.IsRectangleSelecting(ref _selectionRect))
|
||||||
|
{
|
||||||
|
if (ImGui.IsInRectangleSelection(ref _selectionRect))
|
||||||
|
{
|
||||||
|
SelectFile(entry->Path, false, .SingleFile, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeselectFile(entry->Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.PopStyleColor();
|
ImGui.PopStyleColor();
|
||||||
|
|
||||||
if (ImGui.BeginDragDropSource())
|
if (ImGui.BeginDragDropSource())
|
||||||
@@ -816,7 +966,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
|
|
||||||
ImGui.AttachTooltip(entry->Name);
|
ImGui.AttachTooltip(entry->Name);
|
||||||
@@ -1027,7 +1177,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
if (entry->IsDirectory)
|
if (entry->IsDirectory)
|
||||||
{
|
{
|
||||||
_currentDirectory.Set(entry->Path);
|
_directoryHistory.Navigate(entry->Path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,6 +38,95 @@ namespace ImGui
|
|||||||
public static explicit operator float4(Vec4 v) => .(v.x, v.y, v.z, v.w);
|
public static explicit operator float4(Vec4 v) => .(v.x, v.y, v.z, v.w);
|
||||||
public static explicit operator Vec4(float4 v) => .(v.X, v.Y, v.Z, v.W);
|
public static explicit operator Vec4(float4 v) => .(v.X, v.Y, v.Z, v.W);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Color
|
||||||
|
{
|
||||||
|
public static explicit operator ColorRGBA(Color c) => .(c.Value.x, c.Value.y, c.Value.z, c.Value.w);
|
||||||
|
public static explicit operator Color(ColorRGBA c) => .(c.R, c.G, c.B, c.A);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RectangleSelectionFlags
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
NoRender
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool BeginRectangleSelection(ref float4 selectionRectangle, bool isMouseDown, RectangleSelectionFlags flags = .None)
|
||||||
|
{
|
||||||
|
/*let storage = ImGui.GetStateStorage();
|
||||||
|
ref float selectionRectX = ref *storage.GetFloatRef(ImGui.GetID("SelectionRect.X"), float.NaN);*/
|
||||||
|
|
||||||
|
float2 minRegion = (.)ImGui.GetCursorPos() + (.)ImGui.GetWindowPos();
|
||||||
|
float2 maxRegion = minRegion + (float2)ImGui.GetContentRegionAvail();
|
||||||
|
|
||||||
|
ImGui.DrawRect((.)minRegion, (.)maxRegion, ImGui.Color(0,1f,0));
|
||||||
|
|
||||||
|
bool selectionValid() => !any(isnan(selectionRectangle));
|
||||||
|
|
||||||
|
if (isMouseDown)
|
||||||
|
{
|
||||||
|
if (!selectionValid() && IsWindowHovered())
|
||||||
|
{
|
||||||
|
selectionRectangle.XY = (float2)ImGui.GetMousePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectionRectangle.ZW = (.)ImGui.GetMousePos();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectionRectangle.XYZW = float.NaN;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectionRectangle.XY = clamp(selectionRectangle.XY, minRegion, maxRegion);
|
||||||
|
selectionRectangle.ZW = clamp(selectionRectangle.ZW, minRegion, maxRegion);
|
||||||
|
|
||||||
|
if (!flags.HasFlag(.NoRender) && selectionValid())
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the user is currently doing a rectangle selection
|
||||||
|
public static bool IsRectangleSelecting(ref float4 selectionRectangle)
|
||||||
|
{
|
||||||
|
return !any(isnan(selectionRectangle));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the current item is intersecting the selection rectangle
|
||||||
|
public static bool IsInRectangleSelection(ref float4 selectionRectangle)
|
||||||
|
{
|
||||||
|
if (any(isnan(selectionRectangle)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.DebugDrawItemRect();
|
||||||
|
|
||||||
|
float2 minRect = (.)ImGui.GetItemRectMin();
|
||||||
|
float2 maxRect = (.)ImGui.GetItemRectMax();
|
||||||
|
|
||||||
|
float2 topLeft = min(minRect, maxRect);
|
||||||
|
float2 bottomRight = max(minRect, maxRect);
|
||||||
|
|
||||||
|
Rectangle itemRectangle = .(topLeft, 0);
|
||||||
|
itemRectangle.BottomRight = bottomRight;
|
||||||
|
|
||||||
|
let drawList = ImGui.GetForegroundDrawList();
|
||||||
|
drawList.AddRect((.)itemRectangle.TopLeft, (.)itemRectangle.BottomRight, ImGui.GetColorU32(ImGui.Color(0, 130, 216, 255).Value));
|
||||||
|
|
||||||
|
float2 selectionTopLeft = min(selectionRectangle.XY, selectionRectangle.ZW);
|
||||||
|
float2 selectionTottomRight = max(selectionRectangle.XY, selectionRectangle.ZW);
|
||||||
|
|
||||||
|
Rectangle rect = .(selectionTopLeft, 0);
|
||||||
|
rect.BottomRight = selectionTottomRight;
|
||||||
|
|
||||||
|
return rect.Intersects(itemRectangle);
|
||||||
|
}
|
||||||
|
|
||||||
public static Payload<T>? AcceptDragDropPayload<T>(char8* type, DragDropFlags flags = .None) where T : struct
|
public static Payload<T>? AcceptDragDropPayload<T>(char8* type, DragDropFlags flags = .None) where T : struct
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using Bon;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Math;
|
||||||
|
|
||||||
|
enum IntersectionMode
|
||||||
|
{
|
||||||
|
Disjoint,
|
||||||
|
Intersects,
|
||||||
|
Contains
|
||||||
|
}
|
||||||
|
|
||||||
|
[BonTarget, CRepr]
|
||||||
|
struct Rectangle
|
||||||
|
{
|
||||||
|
private float2 _topLeft;
|
||||||
|
private float2 _size;
|
||||||
|
|
||||||
|
public float2 TopLeft
|
||||||
|
{
|
||||||
|
get => _topLeft;
|
||||||
|
set mut => _topLeft = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 Size
|
||||||
|
{
|
||||||
|
get => _size;
|
||||||
|
set mut => _size = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 BottomRight
|
||||||
|
{
|
||||||
|
get => _topLeft + _size;
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
_size = value - _topLeft;
|
||||||
|
|
||||||
|
if (_size.X < 0)
|
||||||
|
{
|
||||||
|
_size.X = -_size.X;
|
||||||
|
_topLeft.X = value.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_size.Y < 0)
|
||||||
|
{
|
||||||
|
_size.Y = -_size.Y;
|
||||||
|
_topLeft.Y = value.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Left
|
||||||
|
{
|
||||||
|
get => _topLeft.X;
|
||||||
|
set mut => _topLeft.X = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Top
|
||||||
|
{
|
||||||
|
get => _topLeft.Y;
|
||||||
|
set mut => _topLeft.Y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Right
|
||||||
|
{
|
||||||
|
get => _topLeft.X + _size.X;
|
||||||
|
set mut => _size.X = value - _topLeft.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Bottom
|
||||||
|
{
|
||||||
|
get => _topLeft.Y + _size.Y;
|
||||||
|
set mut => _size.Y = value - _topLeft.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(float2 topLeft, float2 size)
|
||||||
|
{
|
||||||
|
_topLeft = topLeft;
|
||||||
|
_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(float2 point)
|
||||||
|
{
|
||||||
|
return all(_topLeft <= point) && all(BottomRight >= point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntersectionMode Collision(Rectangle other)
|
||||||
|
{
|
||||||
|
if (any(other.TopLeft >= this.BottomRight) || any(other.BottomRight <= this.TopLeft))
|
||||||
|
{
|
||||||
|
return .Disjoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all(other.TopLeft >= this.TopLeft) && all(other.BottomRight <= this.BottomRight))
|
||||||
|
{
|
||||||
|
return .Contains;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Intersects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Intersects(Rectangle other)
|
||||||
|
{
|
||||||
|
return !(other.Left > Right
|
||||||
|
|| other.Top > Bottom
|
||||||
|
|| other.Right < Left
|
||||||
|
|| other.Bottom < Top
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user