Refactor to ViewportRubberBandSelector class and use actor node virtual methods.

This commit is contained in:
Chandler Cox
2025-03-08 09:38:01 -06:00
parent 45a24a05c5
commit 5ea6e7b49d
9 changed files with 337 additions and 188 deletions

View File

@@ -11,6 +11,7 @@ using FlaxEditor.Tools;
using FlaxEditor.Viewport.Modes;
using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.Gizmo;
using FlaxEngine.GUI;
using FlaxEngine.Tools;
@@ -111,11 +112,7 @@ namespace FlaxEditor.Viewport
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
private EditorSpritesRenderer _editorSpritesRenderer;
private bool _isRubberBandSpanning;
private bool _tryStartRubberBand;
private Float2 _cachedStartingMousePosition;
private Rectangle _rubberBandRect;
private Rectangle _lastRubberBandRect;
private ViewportRubberBandSelector _rubberBandSelector;
/// <summary>
/// Drag and drop handlers
@@ -222,6 +219,9 @@ namespace FlaxEditor.Viewport
TransformGizmo.ApplyTransformation += ApplyTransform;
TransformGizmo.Duplicate += _editor.SceneEditing.Duplicate;
Gizmos.Active = TransformGizmo;
// Add rubber band selector
_rubberBandSelector = new ViewportRubberBandSelector(this);
// Add grid
Grid = new GridGizmo(this);
@@ -378,13 +378,7 @@ namespace FlaxEditor.Viewport
}
// Draw RubberBand for rect selection
if (_isRubberBandSpanning)
{
Render2D.Begin(context, target, targetDepth);
Render2D.FillRectangle(_rubberBandRect, Style.Current.Selection);
Render2D.DrawRectangle(_rubberBandRect, Style.Current.SelectionBorder);
Render2D.End();
}
_rubberBandSelector.Draw(context, target, targetDepth);
// Draw selected objects debug shapes and visuals
if (DrawDebugDraw && (renderContext.View.Flags & ViewFlags.DebugDraw) == ViewFlags.DebugDraw)
@@ -500,16 +494,14 @@ namespace FlaxEditor.Viewport
public override void OnLostFocus()
{
base.OnLostFocus();
_isRubberBandSpanning = false;
_tryStartRubberBand = false;
_rubberBandSelector.StopRubberBand();
}
/// <inheritdoc />
public override void OnMouseLeave()
{
base.OnMouseLeave();
_isRubberBandSpanning = false;
_tryStartRubberBand = false;
_rubberBandSelector.StopRubberBand();
}
/// <summary>
@@ -616,172 +608,16 @@ namespace FlaxEditor.Viewport
base.OnMouseMove(location);
// Dont allow rubber band selection when gizmo is controlling mouse, vertex painting mode, or cloth painting is enabled
if (_isRubberBandSpanning && ((Gizmos.Active.IsControllingMouse || Gizmos.Active is VertexPaintingGizmo || Gizmos.Active is ClothPaintingGizmo) || IsControllingMouse || IsRightMouseButtonDown))
{
_isRubberBandSpanning = false;
}
if (_tryStartRubberBand && (Mathf.Abs(MouseDelta.X) > 0.1f || Mathf.Abs(MouseDelta.Y) > 0.1f) && !_isRubberBandSpanning && !Gizmos.Active.IsControllingMouse && !IsControllingMouse && !IsRightMouseButtonDown)
{
_isRubberBandSpanning = true;
_cachedStartingMousePosition = _viewMousePos;
_rubberBandRect = new Rectangle(_cachedStartingMousePosition, Float2.Zero);
}
else if (_isRubberBandSpanning && !Gizmos.Active.IsControllingMouse && !IsControllingMouse && !IsRightMouseButtonDown)
{
_rubberBandRect.Width = _viewMousePos.X - _cachedStartingMousePosition.X;
_rubberBandRect.Height = _viewMousePos.Y - _cachedStartingMousePosition.Y;
if (_lastRubberBandRect != _rubberBandRect)
{
// Select rubberbanded rect actor nodes
var adjustedRect = _rubberBandRect;
_lastRubberBandRect = _rubberBandRect;
if (adjustedRect.Width < 0 || adjustedRect.Height < 0)
{
// make sure we have a well-formed rectangle i.e. size is positive and X/Y is upper left corner
var size = adjustedRect.Size;
adjustedRect.X = Mathf.Min(adjustedRect.X, adjustedRect.X + adjustedRect.Width);
adjustedRect.Y = Mathf.Min(adjustedRect.Y, adjustedRect.Y + adjustedRect.Height);
size.X = Mathf.Abs(size.X);
size.Y = Mathf.Abs(size.Y);
adjustedRect.Size = size;
}
List<SceneGraphNode> hits = new List<SceneGraphNode>();
var allActors = Level.GetActors<Actor>(true);
foreach (var a in allActors)
{
if (a.HideFlags is HideFlags.DontSelect or HideFlags.FullyHidden || a is EmptyActor || a is Scene || !a.IsActive)
continue;
var actorBox = a.EditorBox;
if (ViewFrustum.Contains(actorBox) == ContainmentType.Disjoint)
continue;
// Check if control and skip if canvas is 2D
if (a is UIControl control)
{
UICanvas canvas = null;
var controlParent = control.Parent;
while (controlParent != null && controlParent is not Scene)
{
if (controlParent is UICanvas uiCanvas)
{
canvas = uiCanvas;
break;
}
controlParent = controlParent.Parent;
}
if (canvas != null)
{
if (canvas.Is2D)
continue;
}
}
else if (a is UICanvas uiCanvas)
{
if (uiCanvas.Is2D)
continue;
}
var containsAllPoints = true;
var fallBackToBox = false;
if (a is StaticModel sm)
{
if (sm.Model)
{
var m = sm.Model.LODs[0];
foreach (var mesh in m.Meshes)
{
var points = mesh.GetCollisionProxyPoints();
if (points.Length == 0)
{
fallBackToBox = true;
break;
}
foreach (var point in points)
{
Viewport.ProjectPoint(a.Transform.LocalToWorld(point), out var loc);
if (!adjustedRect.Contains(loc))
{
containsAllPoints = false;
break;
}
}
}
}
}
else
{
fallBackToBox = true;
}
if (fallBackToBox)
{
// Check if all corners are in box to select it.
var corners = actorBox.GetCorners();
foreach (var c in corners)
{
Viewport.ProjectPoint(c, out var loc);
if (!adjustedRect.Contains(loc))
{
containsAllPoints = false;
break;
}
}
}
if (containsAllPoints)
{
if (a.HasPrefabLink)
hits.Add(SceneGraphRoot.Find(a.GetPrefabRoot()));
else
hits.Add(SceneGraphRoot.Find(a));
}
}
if (IsControlDown)
{
var newSelection = new List<SceneGraphNode>();
var currentSelection = _editor.SceneEditing.Selection;
newSelection.AddRange(currentSelection);
foreach (var hit in hits)
{
if (currentSelection.Contains(hit))
newSelection.Remove(hit);
else
newSelection.Add(hit);
}
Select(newSelection);
}
else if (((WindowRootControl)Root).GetKey(KeyboardKeys.Shift))
{
var newSelection = new List<SceneGraphNode>();
var currentSelection = _editor.SceneEditing.Selection;
newSelection.AddRange(hits);
newSelection.AddRange(currentSelection);
Select(newSelection);
}
else
{
Select(hits);
}
}
}
_rubberBandSelector.TryCreateRubberBand(!((Gizmos.Active.IsControllingMouse || Gizmos.Active is VertexPaintingGizmo || Gizmos.Active is ClothPaintingGizmo) || IsControllingMouse || IsRightMouseButtonDown),
_viewMousePos, ViewFrustum);
}
/// <inheritdoc />
protected override void OnLeftMouseButtonDown()
{
base.OnLeftMouseButtonDown();
if (!_isRubberBandSpanning && !Gizmos.Active.IsControllingMouse && !IsControllingMouse && !IsRightMouseButtonDown)
{
_tryStartRubberBand = true;
}
_rubberBandSelector.TryStartingRubberBandSelection();
}
/// <inheritdoc />
@@ -791,17 +627,8 @@ namespace FlaxEditor.Viewport
if (_prevInput.IsControllingMouse || !Bounds.Contains(ref _viewMousePos))
return;
if (_tryStartRubberBand)
{
_tryStartRubberBand = false;
}
// Select rubberbanded rect actor nodes
if (_isRubberBandSpanning)
{
_isRubberBandSpanning = false;
}
else
// Select rubberbanded rect actor nodes or pick with gizmo
if (!_rubberBandSelector.ReleaseRubberBandSelection())
{
// Try to pick something with the current gizmo
Gizmos.Active?.Pick();