200 lines
7.5 KiB
C#
200 lines
7.5 KiB
C#
using UnityEngine;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.ProBuilder;
|
|
using UnityEngine.ProBuilder.MeshOperations;
|
|
|
|
namespace UnityEditor.ProBuilder.Actions
|
|
{
|
|
sealed class ProBuilderize : MenuAction
|
|
{
|
|
bool m_Enabled;
|
|
Pref<bool> m_Quads = new Pref<bool>("meshImporter.quads", true);
|
|
Pref<bool> m_Smoothing = new Pref<bool>("meshImporter.smoothing", true);
|
|
Pref<float> m_SmoothingAngle = new Pref<float>("meshImporter.smoothingAngle", 1f);
|
|
|
|
public ProBuilderize()
|
|
{
|
|
MeshSelection.objectSelectionChanged += OnObjectSelectionChanged;
|
|
|
|
OnObjectSelectionChanged(); // invoke once as we might already have a selection in Hierarchy
|
|
}
|
|
|
|
private void OnObjectSelectionChanged()
|
|
{
|
|
// can't just check if any MeshFilter is present because we need to know whether or not it's already a
|
|
// probuilder mesh
|
|
int meshCount = Selection.transforms.SelectMany(x => x.GetComponentsInChildren<MeshFilter>()).Count();
|
|
m_Enabled = meshCount > 0 && meshCount != MeshSelection.selectedObjectCount;
|
|
}
|
|
|
|
public override ToolbarGroup group
|
|
{
|
|
get { return ToolbarGroup.Object; }
|
|
}
|
|
|
|
public override Texture2D icon
|
|
{
|
|
get { return IconUtility.GetIcon("Toolbar/Object_ProBuilderize", IconSkin.Pro); }
|
|
}
|
|
|
|
public override TooltipContent tooltip
|
|
{
|
|
get { return s_Tooltip; }
|
|
}
|
|
|
|
GUIContent m_QuadsTooltip = new GUIContent("Import Quads", "Create ProBuilder mesh using quads where " +
|
|
"possible instead of triangles.");
|
|
GUIContent m_SmoothingTooltip = new GUIContent("Import Smoothing", "Import smoothing groups by " +
|
|
"testing adjacent faces against an angle threshold.");
|
|
GUIContent m_SmoothingThresholdTooltip = new GUIContent("Smoothing Threshold", "When importing " +
|
|
"smoothing groups any adjacent faces with an adjoining angle difference of less than this value will be " +
|
|
"grouped together in a smoothing group.");
|
|
|
|
private static readonly TooltipContent s_Tooltip = new TooltipContent
|
|
(
|
|
"ProBuilderize",
|
|
@"Creates ProBuilder-modifiable objects from meshes."
|
|
);
|
|
|
|
public override bool enabled
|
|
{
|
|
get { return base.enabled && m_Enabled; }
|
|
}
|
|
|
|
protected override MenuActionState optionsMenuState
|
|
{
|
|
get { return MenuActionState.VisibleAndEnabled; }
|
|
}
|
|
|
|
protected override void OnSettingsGUI()
|
|
{
|
|
GUILayout.Label("ProBuilderize Options", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.HelpBox("When Preserve Faces is enabled ProBuilder will try to group adjacent triangles into faces.", MessageType.Info);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
m_Quads.value = EditorGUILayout.Toggle(m_QuadsTooltip, m_Quads);
|
|
m_Smoothing.value = EditorGUILayout.Toggle(m_SmoothingTooltip, m_Smoothing);
|
|
GUI.enabled = m_Smoothing;
|
|
EditorGUILayout.PrefixLabel(m_SmoothingThresholdTooltip);
|
|
m_SmoothingAngle.value = EditorGUILayout.Slider(m_SmoothingAngle, 0.0001f, 45f);
|
|
|
|
GUI.enabled = true;
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
ProBuilderSettings.Save();
|
|
|
|
GUILayout.FlexibleSpace();
|
|
|
|
GUI.enabled = enabled;
|
|
|
|
if (GUILayout.Button("ProBuilderize"))
|
|
EditorUtility.ShowNotification(PerformAction().notification);
|
|
|
|
GUI.enabled = true;
|
|
}
|
|
|
|
protected override ActionResult PerformActionImplementation()
|
|
{
|
|
IEnumerable<MeshFilter> top = Selection.transforms.Select(x => x.GetComponent<MeshFilter>()).Where(y => y != null);
|
|
IEnumerable<MeshFilter> all = Selection.gameObjects.SelectMany(x => x.GetComponentsInChildren<MeshFilter>()).Where(x => x != null);
|
|
|
|
MeshImportSettings settings = new MeshImportSettings()
|
|
{
|
|
quads = m_Quads,
|
|
smoothing = m_Smoothing,
|
|
smoothingAngle = m_SmoothingAngle
|
|
};
|
|
|
|
if (top.Count() != all.Count())
|
|
{
|
|
int result = UnityEditor.EditorUtility.DisplayDialogComplex("ProBuilderize Selection",
|
|
"ProBuilderize children of selection?",
|
|
"Yes",
|
|
"No",
|
|
"Cancel");
|
|
|
|
if (result == 0)
|
|
return DoProBuilderize(all, settings);
|
|
else if (result == 1)
|
|
return DoProBuilderize(top, settings);
|
|
else
|
|
return ActionResult.UserCanceled;
|
|
}
|
|
|
|
return DoProBuilderize(all, settings);
|
|
}
|
|
|
|
[System.Obsolete("Please use DoProBuilderize(IEnumerable<MeshFilter>, pb_MeshImporter.Settings")]
|
|
public static ActionResult DoProBuilderize(
|
|
IEnumerable<MeshFilter> selected,
|
|
bool preserveFaces)
|
|
{
|
|
return DoProBuilderize(selected, new MeshImportSettings()
|
|
{
|
|
quads = preserveFaces,
|
|
smoothing = false,
|
|
smoothingAngle = 1f
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds pb_Object component without duplicating the objcet. Is undo-able.
|
|
/// </summary>
|
|
/// <param name="selected"></param>
|
|
/// <param name="settings"></param>
|
|
/// <returns></returns>
|
|
public static ActionResult DoProBuilderize(
|
|
IEnumerable<MeshFilter> selected,
|
|
MeshImportSettings settings)
|
|
{
|
|
|
|
int i = 0;
|
|
float count = selected.Count();
|
|
|
|
// Return immediately from the action so that the GUI can resolve. Displaying a progress bar interrupts the
|
|
// event loop causing a layoutting error.
|
|
EditorApplication.delayCall += () =>
|
|
{
|
|
foreach (var mf in selected)
|
|
{
|
|
if (mf.sharedMesh == null)
|
|
continue;
|
|
|
|
GameObject go = mf.gameObject;
|
|
Mesh sourceMesh = mf.sharedMesh;
|
|
Material[] sourceMaterials = go.GetComponent<MeshRenderer>()?.sharedMaterials;
|
|
|
|
try
|
|
{
|
|
var destination = Undo.AddComponent<ProBuilderMesh>(go);
|
|
var meshImporter = new MeshImporter(sourceMesh, sourceMaterials, destination);
|
|
meshImporter.Import(settings);
|
|
|
|
destination.Rebuild();
|
|
destination.Optimize();
|
|
|
|
i++;
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
Debug.LogWarning("Failed ProBuilderizing: " + go.name + "\n" + e.ToString());
|
|
}
|
|
|
|
UnityEditor.EditorUtility.DisplayProgressBar("ProBuilderizing", mf.gameObject.name, i / count);
|
|
}
|
|
|
|
UnityEditor.EditorUtility.ClearProgressBar();
|
|
MeshSelection.OnObjectSelectionChanged();
|
|
ProBuilderEditor.Refresh();
|
|
};
|
|
|
|
if (i < 1)
|
|
return new ActionResult(ActionResult.Status.Canceled, "Nothing Selected");
|
|
return new ActionResult(ActionResult.Status.Success, "ProBuilderize " + i + (i > 1 ? " Objects" : " Object").ToString());
|
|
}
|
|
}
|
|
}
|