223 lines
8.1 KiB
C#
223 lines
8.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine.ProBuilder;
|
|
using UnityEngine.ProBuilder.MeshOperations;
|
|
|
|
|
|
namespace UnityEditor.ProBuilder.Actions
|
|
{
|
|
sealed class GrowSelection : MenuAction
|
|
{
|
|
Pref<bool> m_GrowSelectionWithAngle = new Pref<bool>("GrowSelection.useAngle", true);
|
|
Pref<bool> m_GrowSelectionAngleIterative = new Pref<bool>("GrowSelection.iterativeGrow", false);
|
|
Pref<float> m_GrowSelectionAngleValue = new Pref<float>("GrowSelection.angleValue", 15f);
|
|
|
|
public override ToolbarGroup group
|
|
{
|
|
get { return ToolbarGroup.Selection; }
|
|
}
|
|
public override string iconPath => "Toolbar/Selection_Grow";
|
|
public override Texture2D icon => IconUtility.GetIcon(iconPath);
|
|
|
|
public override TooltipContent tooltip
|
|
{
|
|
get { return s_Tooltip; }
|
|
}
|
|
|
|
static readonly TooltipContent s_Tooltip = new TooltipContent
|
|
(
|
|
"Grow Selection",
|
|
@"Adds adjacent elements to the current selection, optionally testing to see if they are within a specified angle.
|
|
|
|
Grow by angle is enabled by Option + Clicking the <b>Grow Selection</b> button.",
|
|
keyCommandAlt, 'G'
|
|
);
|
|
|
|
public override SelectMode validSelectModes
|
|
{
|
|
get { return SelectMode.Vertex | SelectMode.Edge | SelectMode.Face | SelectMode.TextureFace; }
|
|
}
|
|
|
|
public override bool enabled
|
|
{
|
|
get { return base.enabled && VerifyGrowSelection(); }
|
|
}
|
|
|
|
protected override MenuActionState optionsMenuState => MenuActionState.VisibleAndEnabled;
|
|
|
|
public override VisualElement CreateSettingsContent()
|
|
{
|
|
var root = new VisualElement();
|
|
root.enabledSelf = enabled && ProBuilderEditor.selectMode == SelectMode.Face;
|
|
|
|
var angleToggle = new Toggle("Restrict to Angle");
|
|
angleToggle.SetValueWithoutNotify(m_GrowSelectionWithAngle);
|
|
root.Add(angleToggle);
|
|
|
|
var floatField = new FloatField("Max Angle");
|
|
floatField.SetValueWithoutNotify(m_GrowSelectionAngleValue);
|
|
floatField.isDelayed = PreviewActionManager.delayedPreview;
|
|
floatField.SetEnabled(m_GrowSelectionWithAngle);
|
|
root.Add(floatField);
|
|
|
|
var iterativeToggle = new Toggle("Iterative");
|
|
iterativeToggle.SetValueWithoutNotify(m_GrowSelectionWithAngle ? m_GrowSelectionAngleIterative : true);
|
|
iterativeToggle.SetEnabled(m_GrowSelectionWithAngle);
|
|
root.Add(iterativeToggle);
|
|
|
|
angleToggle.RegisterCallback<ChangeEvent<bool>>(evt =>
|
|
{
|
|
m_GrowSelectionWithAngle.SetValue(evt.newValue);
|
|
floatField.SetEnabled(m_GrowSelectionWithAngle);
|
|
iterativeToggle.SetValueWithoutNotify(m_GrowSelectionWithAngle ? m_GrowSelectionAngleIterative : true);
|
|
iterativeToggle.SetEnabled(m_GrowSelectionWithAngle);
|
|
PreviewActionManager.UpdatePreview();
|
|
});
|
|
floatField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
m_GrowSelectionAngleValue.SetValue(evt.newValue);
|
|
PreviewActionManager.UpdatePreview();
|
|
});
|
|
iterativeToggle.RegisterCallback<ChangeEvent<bool>>(evt =>
|
|
{
|
|
m_GrowSelectionAngleIterative.SetValue(evt.newValue);
|
|
PreviewActionManager.UpdatePreview();
|
|
});
|
|
System.Action onDelayedPreviewChanged = () =>
|
|
{
|
|
floatField.isDelayed = PreviewActionManager.delayedPreview;
|
|
};
|
|
PreviewActionManager.delayedPreviewChanged += onDelayedPreviewChanged;
|
|
root.RegisterCallback<DetachFromPanelEvent>(evt =>
|
|
{
|
|
PreviewActionManager.delayedPreviewChanged -= onDelayedPreviewChanged;
|
|
});
|
|
return root;
|
|
}
|
|
|
|
protected override void OnSettingsGUI()
|
|
{
|
|
GUILayout.Label("Grow Selection Options", EditorStyles.boldLabel);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
m_GrowSelectionWithAngle.value = EditorGUILayout.Toggle("Restrict to Angle", m_GrowSelectionWithAngle.value);
|
|
|
|
GUI.enabled = m_GrowSelectionWithAngle;
|
|
|
|
m_GrowSelectionAngleValue.value = EditorGUILayout.FloatField("Max Angle", m_GrowSelectionAngleValue);
|
|
|
|
GUI.enabled = m_GrowSelectionWithAngle;
|
|
|
|
bool iterative = m_GrowSelectionWithAngle ? m_GrowSelectionAngleIterative : true;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
iterative = EditorGUILayout.Toggle("Iterative", iterative);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
m_GrowSelectionAngleIterative.value = iterative;
|
|
}
|
|
|
|
GUI.enabled = true;
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
ProBuilderSettings.Save();
|
|
|
|
GUILayout.FlexibleSpace();
|
|
|
|
if (GUILayout.Button("Grow Selection"))
|
|
PerformAction();
|
|
}
|
|
|
|
protected override ActionResult PerformActionImplementation()
|
|
{
|
|
if (MeshSelection.selectedObjectCount < 1)
|
|
return ActionResult.NoSelection;
|
|
|
|
UndoUtility.RecordSelection("Grow Selection");
|
|
|
|
int grown = 0;
|
|
bool angleGrow = m_GrowSelectionWithAngle;
|
|
bool iterative = m_GrowSelectionAngleIterative;
|
|
float growSelectionAngle = m_GrowSelectionAngleValue;
|
|
|
|
if (!angleGrow && !iterative)
|
|
iterative = true;
|
|
|
|
foreach (ProBuilderMesh pb in InternalUtility.GetComponents<ProBuilderMesh>(Selection.transforms))
|
|
{
|
|
int previousTriCount = pb.selectedVertexCount;
|
|
|
|
switch (ProBuilderEditor.selectMode)
|
|
{
|
|
case SelectMode.Vertex:
|
|
pb.SetSelectedEdges(ElementSelection.GetConnectedEdges(pb, pb.selectedIndexesInternal));
|
|
break;
|
|
|
|
case SelectMode.Edge:
|
|
pb.SetSelectedEdges(ElementSelection.GetConnectedEdges(pb, pb.selectedIndexesInternal));
|
|
break;
|
|
|
|
case SelectMode.TextureFace:
|
|
case SelectMode.Face:
|
|
|
|
Face[] selectedFaces = pb.GetSelectedFaces();
|
|
|
|
HashSet<Face> sel;
|
|
|
|
if (iterative)
|
|
{
|
|
sel = ElementSelection.GrowSelection(pb, selectedFaces, angleGrow ? growSelectionAngle : -1f);
|
|
sel.UnionWith(selectedFaces);
|
|
}
|
|
else
|
|
{
|
|
sel = ElementSelection.FloodSelection(pb, selectedFaces, angleGrow ? growSelectionAngle : -1f);
|
|
}
|
|
|
|
pb.SetSelectedFaces(sel.ToArray());
|
|
|
|
break;
|
|
}
|
|
|
|
grown += pb.selectedVertexCount - previousTriCount;
|
|
}
|
|
|
|
ProBuilderEditor.Refresh();
|
|
SceneView.RepaintAll();
|
|
|
|
if (grown > 0)
|
|
return new ActionResult(ActionResult.Status.Success, "Grow Selection");
|
|
|
|
return new ActionResult(ActionResult.Status.Failure, "Nothing to Grow");
|
|
}
|
|
|
|
static bool VerifyGrowSelection()
|
|
{
|
|
int sel, max;
|
|
|
|
switch (ProBuilderEditor.selectMode)
|
|
{
|
|
case SelectMode.Face:
|
|
sel = MeshSelection.selectedFaceCount;
|
|
max = MeshSelection.totalFaceCount;
|
|
break;
|
|
|
|
case SelectMode.Edge:
|
|
sel = MeshSelection.selectedEdgeCount;
|
|
max = MeshSelection.totalEdgeCount;
|
|
break;
|
|
|
|
default:
|
|
sel = MeshSelection.selectedVertexCount;
|
|
max = MeshSelection.totalVertexCount;
|
|
break;
|
|
}
|
|
|
|
return sel > 0 && sel < max;
|
|
}
|
|
}
|
|
}
|