154 lines
5.4 KiB
C#
154 lines
5.4 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System.Linq;
|
|
using UnityEngine.ProBuilder;
|
|
using UnityEngine.ProBuilder.MeshOperations;
|
|
|
|
namespace UnityEditor.ProBuilder.Actions
|
|
{
|
|
sealed class DuplicateFaces : MenuAction
|
|
{
|
|
Pref<DuplicateFaceSetting> m_DuplicateFaceSetting = new Pref<DuplicateFaceSetting>("DuplicateFaces.target", DuplicateFaceSetting.GameObject);
|
|
|
|
public override ToolbarGroup group { get { return ToolbarGroup.Geometry; } }
|
|
public override Texture2D icon { get { return IconUtility.GetIcon("Toolbar/Face_Duplicate", IconSkin.Pro); } } //icon to be replaced
|
|
public override TooltipContent tooltip { get { return s_Tooltip; } }
|
|
|
|
static readonly TooltipContent s_Tooltip = new TooltipContent
|
|
(
|
|
"Duplicate Faces",
|
|
"Makes an exact copy of the selected faces, and either adds them to this mesh or creates a new Game Object"
|
|
);
|
|
|
|
public override SelectMode validSelectModes
|
|
{
|
|
get { return SelectMode.Face; }
|
|
}
|
|
|
|
public override bool enabled
|
|
{
|
|
get { return base.enabled && MeshSelection.selectedFaceCount > 0; }
|
|
}
|
|
|
|
protected override MenuActionState optionsMenuState
|
|
{
|
|
get { return MenuActionState.VisibleAndEnabled; }
|
|
}
|
|
|
|
internal enum DuplicateFaceSetting
|
|
{
|
|
GameObject,
|
|
Submesh
|
|
};
|
|
|
|
protected override void OnSettingsGUI()
|
|
{
|
|
GUILayout.Label("Duplicate Face Settings", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.HelpBox("You can create a new Game Object with the selected face(s), or keep them as part of this object by using a Submesh.", MessageType.Info);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
m_DuplicateFaceSetting.value = (DuplicateFaceSetting)EditorGUILayout.EnumPopup("Duplicate To", m_DuplicateFaceSetting);
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
ProBuilderSettings.Save();
|
|
|
|
GUILayout.FlexibleSpace();
|
|
|
|
if (GUILayout.Button("Duplicate Selection"))
|
|
EditorUtility.ShowNotification(PerformAction().notification);
|
|
}
|
|
|
|
protected override ActionResult PerformActionImplementation()
|
|
{
|
|
if (MeshSelection.selectedObjectCount < 1)
|
|
return ActionResult.NoSelection;
|
|
|
|
UndoUtility.RecordSelection("Duplicate Face(s)");
|
|
|
|
if (m_DuplicateFaceSetting == DuplicateFaceSetting.GameObject)
|
|
return DuplicateFacesToObject();
|
|
|
|
return DuplicateFacesToSubmesh();
|
|
}
|
|
|
|
static ActionResult DuplicateFacesToSubmesh()
|
|
{
|
|
int count = 0;
|
|
|
|
foreach (ProBuilderMesh pb in MeshSelection.topInternal)
|
|
{
|
|
pb.ToMesh();
|
|
List<Face> res = pb.DetachFaces(pb.selectedFacesInternal, false);
|
|
pb.Refresh();
|
|
pb.Optimize();
|
|
|
|
pb.SetSelectedFaces(res.ToArray());
|
|
|
|
count += pb.selectedFaceCount;
|
|
}
|
|
|
|
ProBuilderEditor.Refresh();
|
|
|
|
if (count > 0)
|
|
return new ActionResult(ActionResult.Status.Success, "Duplicate " + count + (count > 1 ? " Faces" : " Face"));
|
|
|
|
return new ActionResult(ActionResult.Status.Success, "Duplicate Faces");
|
|
}
|
|
|
|
static ActionResult DuplicateFacesToObject()
|
|
{
|
|
int duplicatedFaceCount = 0;
|
|
List<GameObject> duplicated = new List<GameObject>();
|
|
|
|
foreach (ProBuilderMesh mesh in MeshSelection.topInternal)
|
|
{
|
|
if (mesh.selectedFaceCount < 1)
|
|
continue;
|
|
|
|
var primary = mesh.selectedFaceIndexes;
|
|
duplicatedFaceCount += primary.Count;
|
|
|
|
List<int> inverse = new List<int>();
|
|
|
|
for (int i = 0; i < mesh.facesInternal.Length; i++)
|
|
if (!primary.Contains(i))
|
|
inverse.Add(i);
|
|
|
|
ProBuilderMesh copy = Object.Instantiate(mesh.gameObject, mesh.transform.parent).GetComponent<ProBuilderMesh>();
|
|
EditorUtility.SynchronizeWithMeshFilter(copy);
|
|
|
|
if (copy.transform.childCount > 0)
|
|
{
|
|
for (int i = copy.transform.childCount - 1; i > -1; i--)
|
|
Object.DestroyImmediate(copy.transform.GetChild(i).gameObject);
|
|
|
|
foreach (var child in mesh.transform.GetComponentsInChildren<ProBuilderMesh>())
|
|
EditorUtility.SynchronizeWithMeshFilter(child);
|
|
}
|
|
|
|
Undo.RegisterCreatedObjectUndo(copy.gameObject, "Duplicate Selection");
|
|
|
|
copy.DeleteFaces(inverse);
|
|
copy.Rebuild();
|
|
copy.Optimize();
|
|
mesh.ClearSelection();
|
|
copy.ClearSelection();
|
|
copy.SetSelectedFaces(copy.faces);
|
|
|
|
copy.gameObject.name = GameObjectUtility.GetUniqueNameForSibling(mesh.transform.parent, mesh.gameObject.name);
|
|
duplicated.Add(copy.gameObject);
|
|
}
|
|
|
|
MeshSelection.SetSelection(duplicated);
|
|
ProBuilderEditor.Refresh();
|
|
|
|
if (duplicatedFaceCount > 0)
|
|
return new ActionResult(ActionResult.Status.Success, "Duplicate " + duplicatedFaceCount + " faces to new Object");
|
|
|
|
return new ActionResult(ActionResult.Status.Failure, "No Faces Selected");
|
|
}
|
|
}
|
|
}
|