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

@@ -182,6 +182,51 @@ namespace FlaxEditor.SceneGraph
return null;
}
/// <summary>
/// Get all nested actor nodes under this actor node.
/// </summary>
/// <returns>An array of ActorNodes</returns>
public ActorNode[] GetAllChildActorNodes()
{
// Check itself
if (ChildNodes == null || ChildNodes.Count == 0)
return [];
// Check deeper
var nodes = new List<ActorNode>();
for (int i = 0; i < ChildNodes.Count; i++)
{
if (ChildNodes[i] is ActorNode node)
{
nodes.Add(node);
var childNodes = node.GetAllChildActorNodes();
if (childNodes.Length > 0)
{
nodes.AddRange(childNodes);
}
}
}
return nodes.ToArray();
}
/// <summary>
/// Whether an actor node can be selected with a selector.
/// </summary>
/// <returns>True if the actor node can be selected</returns>
public virtual bool CanSelectActorNodeWithSelector()
{
return Actor && Actor.HideFlags is not (HideFlags.DontSelect or HideFlags.FullyHidden) && Actor is not EmptyActor && IsActive;
}
/// <summary>
/// The selection points used to check if an actor node can be selected.
/// </summary>
/// <returns>The points to use if the actor can be selected.</returns>
public virtual Vector3[] GetActorSelectionPoints()
{
return Actor.EditorBox.GetCorners();
}
/// <summary>
/// Gets a value indicating whether this actor can be used to create prefab from it (as a root).
/// </summary>

View File

@@ -58,5 +58,11 @@ namespace FlaxEditor.SceneGraph.Actors
return Camera.Internal_IntersectsItselfEditor(FlaxEngine.Object.GetUnmanagedPtr(_actor), ref ray.Ray, out distance);
}
/// <inheritdoc />
public override Vector3[] GetActorSelectionPoints()
{
return [Actor.Position];
}
}
}

View File

@@ -33,6 +33,12 @@ namespace FlaxEditor.SceneGraph.Actors
}
}
/// <inheritdoc />
public override bool CanSelectActorNodeWithSelector()
{
return false;
}
/// <summary>
/// Gets the scene.
/// </summary>

View File

@@ -88,6 +88,30 @@ namespace FlaxEditor.SceneGraph.Actors
contextMenu.AddButton("Add collider", () => OnAddMeshCollider(window)).Enabled = ((StaticModel)Actor).Model != null;
}
/// <inheritdoc />
public override Vector3[] GetActorSelectionPoints()
{
if (Actor is not StaticModel sm || !sm.Model)
return base.GetActorSelectionPoints();
// Check collision proxy points for more accurate selection.
var vecPoints = new List<Vector3>();
var m = sm.Model.LODs[0];
foreach (var mesh in m.Meshes)
{
var points = mesh.GetCollisionProxyPoints();
foreach (var point in points)
{
vecPoints.Add(Actor.Transform.LocalToWorld(point));
}
}
// Fall back to base actor editor box if no points from collision proxy.
if (vecPoints.Count == 0)
return base.GetActorSelectionPoints();
return vecPoints.ToArray();
}
private void OnAddMeshCollider(EditorWindow window)
{
// Allow collider to be added to evey static model selection

View File

@@ -78,5 +78,11 @@ namespace FlaxEditor.SceneGraph.Actors
if (Actor is UICanvas uiCanvas && uiCanvas.Is3D)
DebugDraw.DrawWireBox(uiCanvas.Bounds, Color.BlueViolet);
}
/// <inheritdoc />
public override bool CanSelectActorNodeWithSelector()
{
return Actor is UICanvas uiCanvas && uiCanvas.Is3D;
}
}
}

View File

@@ -40,5 +40,31 @@ namespace FlaxEditor.SceneGraph.Actors
control.PerformLayout();
}
}
/// <inheritdoc />
public override bool CanSelectActorNodeWithSelector()
{
// Check if control and skip if canvas is 2D
if (Actor is not UIControl uiControl)
return false;
UICanvas canvas = null;
var controlParent = uiControl.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)
return false;
}
return true;
}
}
}