TurnBasedStrategyCourse/Library/PackageCache/com.unity.probuilder@5.1.0/Editor/MenuActions/Object/MirrorObjects.cs

154 lines
5.3 KiB
C#

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.ProBuilder;
using UnityEngine.ProBuilder.MeshOperations;
namespace UnityEditor.ProBuilder.Actions
{
sealed class MirrorObjects : MenuAction
{
Pref<MirrorSettings> m_MirrorAxes = new Pref<MirrorSettings>("MirrorObjects.mirrorAxes", MirrorSettings.X);
public override ToolbarGroup group
{
get { return ToolbarGroup.Object; }
}
public override Texture2D icon
{
get { return IconUtility.GetIcon("Toolbar/Object_Mirror", IconSkin.Pro); }
}
public override TooltipContent tooltip
{
get { return s_Tooltip; }
}
[System.Flags]
enum MirrorSettings
{
X = 0x1,
Y = 0x2,
Z = 0x4,
Duplicate = 0x8
}
static readonly TooltipContent s_Tooltip = new TooltipContent
(
"Mirror Objects",
@"Mirroring objects will duplicate and flip objects on the specified axes."
);
public override bool enabled
{
get { return base.enabled && MeshSelection.selectedObjectCount > 0; }
}
protected override MenuActionState optionsMenuState
{
get { return MenuActionState.VisibleAndEnabled; }
}
protected override void OnSettingsGUI()
{
GUILayout.Label("Mirror Settings", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("Mirror objects on the selected axes.\n\nIf Duplicate is toggled a new object will be instantiated from the selection and mirrored, or if disabled the selection will be moved.", MessageType.Info);
MirrorSettings scale = m_MirrorAxes;
bool x = (scale & MirrorSettings.X) != 0 ? true : false;
bool y = (scale & MirrorSettings.Y) != 0 ? true : false;
bool z = (scale & MirrorSettings.Z) != 0 ? true : false;
bool d = (scale & MirrorSettings.Duplicate) != 0 ? true : false;
EditorGUI.BeginChangeCheck();
x = EditorGUILayout.Toggle("X", x);
y = EditorGUILayout.Toggle("Y", y);
z = EditorGUILayout.Toggle("Z", z);
d = EditorGUILayout.Toggle("Duplicate", d);
if (EditorGUI.EndChangeCheck())
m_MirrorAxes.SetValue((MirrorSettings)
(x ? MirrorSettings.X : 0) |
(y ? MirrorSettings.Y : 0) |
(z ? MirrorSettings.Z : 0) |
(d ? MirrorSettings.Duplicate : 0));
GUILayout.FlexibleSpace();
if (GUILayout.Button("Mirror"))
EditorUtility.ShowNotification(PerformAction().notification);
}
protected override ActionResult PerformActionImplementation()
{
Vector3 scale = new Vector3(
(m_MirrorAxes & MirrorSettings.X) > 0 ? -1f : 1f,
(m_MirrorAxes & MirrorSettings.Y) > 0 ? -1f : 1f,
(m_MirrorAxes & MirrorSettings.Z) > 0 ? -1f : 1f);
bool duplicate = (m_MirrorAxes & MirrorSettings.Duplicate) > 0;
List<GameObject> res = new List<GameObject>();
foreach (ProBuilderMesh pb in MeshSelection.topInternal)
res.Add(Mirror(pb, scale, duplicate).gameObject);
MeshSelection.SetSelection(res);
ProBuilderEditor.Refresh();
return res.Count > 0 ?
new ActionResult(ActionResult.Status.Success, string.Format("Mirror {0} {1}", res.Count, res.Count > 1 ? "Objects" : "Object")) :
new ActionResult(ActionResult.Status.NoChange, "No Objects Selected");
}
/**
* \brief Duplicates and mirrors the passed pb_Object.
* @param pb The donor pb_Object.
* @param axe The axis to mirror the object on.
* \returns The newly duplicated pb_Object.
* \sa ProBuilder.Axis
*/
public static ProBuilderMesh Mirror(ProBuilderMesh pb, Vector3 scale, bool duplicate = true)
{
ProBuilderMesh mirredObject;
if (duplicate)
{
mirredObject = Object.Instantiate(pb.gameObject, pb.transform.parent, false).GetComponent<ProBuilderMesh>();
mirredObject.MakeUnique();
mirredObject.transform.parent = pb.transform.parent;
mirredObject.transform.localRotation = pb.transform.localRotation;
Undo.RegisterCreatedObjectUndo(mirredObject.gameObject, "Mirror Object");
}
else
{
UndoUtility.RecordObject(pb, "Mirror");
mirredObject = pb;
}
Vector3 lScale = mirredObject.gameObject.transform.localScale;
mirredObject.transform.localScale = scale;
// if flipping on an odd number of axes, flip winding order
if ((scale.x * scale.y * scale.z) < 0)
{
foreach (var face in mirredObject.facesInternal)
face.Reverse();
}
mirredObject.FreezeScaleTransform();
mirredObject.transform.localScale = lScale;
mirredObject.ToMesh();
mirredObject.Refresh();
mirredObject.Optimize();
return mirredObject;
}
}
}