// This script demonstrates how to create a new action that can be accessed from the ProBuilder toolbar.
// A new menu item is registered under "Geometry" actions called "Remove edges soft".
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.ProBuilder;
using UnityEngine.ProBuilder.MeshOperations;
namespace UnityEditor.ProBuilder.Actions
{
///
/// This is the actual action that will be executed.
///
[ProBuilderMenuAction]
public class SoftDeleteEdgesAction : MenuAction
{
public override ToolbarGroup group { get { return ToolbarGroup.Geometry; } }
public override Texture2D icon { get { return null; } }
public override TooltipContent tooltip { get { return k_Tooltip; } }
///
/// What to show in the hover tooltip window.
/// TooltipContent is similar to GUIContent, with the exception that it also includes an optional params[]
/// char list in the constructor to define shortcut keys (ex, CMD_CONTROL, K).
///
static readonly TooltipContent k_Tooltip = new TooltipContent
(
"Remove Edges",
"Remove selected edges and merge faces."
);
///
/// Determines if the action should be enabled or grayed out. Here when at least one edge is selected.
///
///
public override bool enabled
{
get { return MeshSelection.selectedEdgeCount > 0; }
}
///
/// This action is applicable in Edge selection modes.
///
public override SelectMode validSelectModes
{
get { return SelectMode.Edge; }
}
///
/// Return a pb_ActionResult indicating the success/failure of action.
///
///
protected override ActionResult PerformActionImplementation()
{
var selection = MeshSelection.top.ToArray();
Undo.RecordObjects(selection, "Removing Edges");
List edgeFaces = new List();
Dictionary faceToMergeGroup = new Dictionary();
HashSet mergeGroupIDs = new HashSet();
List> mergeGroups = new List>();
foreach (ProBuilderMesh pbMesh in selection)
{
if(pbMesh.selectedEdgeCount > 0)
{
var selectedEdges = pbMesh.selectedEdges;
faceToMergeGroup.Clear();
foreach(var edge in selectedEdges)
{
edgeFaces.Clear();
mergeGroupIDs.Clear();
//Retrieving impacted faces from edge
ElementSelection.GetNeighborFaces(pbMesh, edge, edgeFaces);
//Chacking all edges status
foreach(var face in edgeFaces)
{
if(faceToMergeGroup.ContainsKey(face))
mergeGroupIDs.Add(faceToMergeGroup[face]);
else
faceToMergeGroup.Add(face, -1);
}
//These faces haven't been seen before
if(mergeGroupIDs.Count == 0)
{
foreach(var face in edgeFaces)
faceToMergeGroup[face] = mergeGroups.Count;
mergeGroups.Add(new List(edgeFaces));
}
//If only a face should already be merge, add other faces to the same merge group
else if(mergeGroupIDs.Count == 1)
{
foreach(var face in edgeFaces)
{
if(faceToMergeGroup[face] == -1)
{
int index = mergeGroupIDs.First();
faceToMergeGroup[face] = index;
mergeGroups[index].Add(face);
}
}
}
//If more than a face already belongs to a merge group, merge these groups together
else
{
//Group the different mergeGroups together
List facesToMerge = new List();
foreach(var groupID in mergeGroupIDs)
{
facesToMerge.AddRange(mergeGroups[groupID]);
mergeGroups[groupID] = null;
}
foreach(var face in edgeFaces)
if(!facesToMerge.Contains(face))
facesToMerge.Add(face);
//Remove unnecessary groups
mergeGroups.RemoveAll(group => group == null);
//Add newly created one
mergeGroups.Add(facesToMerge);
//Update groups references
for(int i = 0; i < mergeGroups.Count; i++)
{
foreach(var face in mergeGroups[i])
faceToMergeGroup[face] = i;
}
}
}
foreach(var mergeGroup in mergeGroups)
MergeElements.Merge(pbMesh, mergeGroup);
pbMesh.ToMesh();
pbMesh.Refresh();
pbMesh.Optimize();
}
}
MeshSelection.ClearElementSelection();
// Rebuild the pb_Editor caches
ProBuilderEditor.Refresh();
return new ActionResult(ActionResult.Status.Success, "Edges Removed");
}
}
}