#pragma warning disable 0618
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.ProBuilder;
using UnityEngine.ProBuilder.MeshOperations;
namespace UnityEditor.ProBuilder
{
///
/// Assign materials to faces and objects.
///
sealed class MaterialEditor : ConfigurableWindow
{
// Reference to pb_Editor instance.
static ProBuilderEditor editor { get { return ProBuilderEditor.instance; } }
// Reference to the currently open pb_Material_Editor
public static MaterialEditor instance { get; private set; }
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 1 &1", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 2 &2", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 3 &3", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 4 &4", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 5 &5", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 6 &6", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 7 &7", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 8 &8", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 9 &9", true, PreferenceKeys.menuMaterialColors)]
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 10 &0", true, PreferenceKeys.menuMaterialColors)]
public static bool VerifyMaterialAction()
{
return ProBuilderEditor.instance != null && MeshSelection.selectedObjectCount > 0;
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 1 &1", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial0()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[0]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 2 &2", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial1()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[1]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 3 &3", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial2()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[2]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 4 &4", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial3()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[3]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 5 &5", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial4()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[4]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 6 &6", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial5()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[5]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 7 &7", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial6()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[6]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 8 &8", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial7()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[7]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 9 &9", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial8()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[8]);
}
[MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/Materials/Apply Material Preset 10 &0", false, PreferenceKeys.menuMaterialColors)]
public static void ApplyMaterial9()
{
ApplyMaterial(MeshSelection.topInternal, CurrentPalette[9]);
}
// Path to the required default material palette. If not valid material palettes are
// found a new one will be created with this path (relative to ProBuilder folder).
static Pref s_MaterialPalettePath = new Pref("editor.materialPalettePath", FileUtility.GetLocalDataDirectory() + "/Default Material Palette.asset");
// The currently loaded material palette asset.
static MaterialPalette s_CurrentPalette = null;
// The user set "quick material"
[SerializeField]
Material m_QueuedMaterial;
// Custom style for material row background
GUIStyle m_RowBackgroundStyle;
// The view scroll position.
Vector2 m_ViewScroll = Vector2.zero;
// All available material palettes
MaterialPalette[] m_AvailablePalettes = null;
// List of string names for all available palettes (plus one entry for 'Add New')
string[] m_AvailablePalettes_Str = null;
// The index of the currently loaded material palette in m_AvailablePalettes
int m_CurrentPaletteIndex = 0;
///
/// The currently loaded material palette, or a default.
///
public static MaterialPalette CurrentPalette
{
get
{
if (s_CurrentPalette == null)
{
// Attempt to load the last user-set material palette
s_CurrentPalette = AssetDatabase.LoadAssetAtPath(s_MaterialPalettePath);
// If not set (or deleted), fall back on default
if (s_CurrentPalette != null)
return s_CurrentPalette;
// No dice - iterate any other pb_MaterialPalette objects in the project (favoring first found)
s_CurrentPalette = FileUtility.FindAssetOfType();
if (s_CurrentPalette != null)
return s_CurrentPalette;
// If no existing pb_MaterialPalette objects in project:
// - create a new one
// - check for the older pb_ObjectArray and copy data to new default
s_CurrentPalette = FileUtility.LoadRequired(s_MaterialPalettePath);
string[] m_LegacyMaterialArrays = AssetDatabase.FindAssets("t:pb_ObjectArray");
for (int i = 0; m_LegacyMaterialArrays != null && i < m_LegacyMaterialArrays.Length; i++)
{
pb_ObjectArray poa = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(m_LegacyMaterialArrays[i]));
// Make sure there's actually something worth copying
if (poa != null && poa.array != null && poa.array.Any(x => x != null && x is Material))
{
s_CurrentPalette.array = poa.GetArray();
break;
}
}
}
return s_CurrentPalette;
}
}
public static void MenuOpenMaterialEditor()
{
GetWindow("Material Editor");
}
void OnEnable()
{
instance = this;
this.autoRepaintOnSceneChange = true;
this.minSize = new Vector2(236, 250);
m_RowBackgroundStyle = new GUIStyle();
m_RowBackgroundStyle.normal.background = EditorGUIUtility.whiteTexture;
s_CurrentPalette = null;
RefreshAvailablePalettes();
}
void OnDisable()
{
instance = null;
}
void OnGUI()
{
DoContextMenu();
GUILayout.Label("Quick Material", EditorStyles.boldLabel);
Rect r = GUILayoutUtility.GetLastRect();
int left = Screen.width - 68;
GUILayout.BeginHorizontal(GUILayout.MaxWidth(Screen.width - 74));
GUILayout.BeginVertical();
m_QueuedMaterial = (Material)EditorGUILayout.ObjectField(m_QueuedMaterial, typeof(Material), true);
GUILayout.Space(2);
if (GUILayout.Button("Apply (Ctrl+Shift+Click)"))
ApplyMaterial(MeshSelection.topInternal, m_QueuedMaterial);
GUI.enabled = editor != null && MeshSelection.selectedFaceCount > 0;
if (GUILayout.Button("Match Selection"))
{
m_QueuedMaterial = EditorMaterialUtility.GetActiveSelection();
}
GUI.enabled = true;
GUILayout.EndVertical();
GUI.Box(new Rect(left, r.y + r.height + 2, 64, 64), "");
var previewTexture = EditorMaterialUtility.GetPreviewTexture(m_QueuedMaterial);
if (previewTexture != null)
{
GUI.Label(new Rect(left + 2, r.y + r.height + 4, 60, 60), previewTexture);
}
else
{
GUI.Box(new Rect(left + 2, r.y + r.height + 4, 60, 60), "");
GUI.Label(new Rect(left + 2, r.height + 28, 120, 32), "None\n(Texture)");
}
GUILayout.EndHorizontal();
GUILayout.Space(4);
GUI.backgroundColor = PreferenceKeys.proBuilderDarkGray;
UI.EditorGUIUtility.DrawSeparator(2);
GUI.backgroundColor = Color.white;
GUILayout.Label("Material Palette", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
m_CurrentPaletteIndex = EditorGUILayout.Popup("", m_CurrentPaletteIndex, m_AvailablePalettes_Str);
if (EditorGUI.EndChangeCheck())
{
MaterialPalette newPalette = null;
// Add a new material palette
if (m_CurrentPaletteIndex >= m_AvailablePalettes.Length)
{
string path = AssetDatabase.GenerateUniqueAssetPath("Assets/Material Palette.asset");
newPalette = FileUtility.LoadRequired(path);
EditorGUIUtility.PingObject(newPalette);
}
else
{
newPalette = m_AvailablePalettes[m_CurrentPaletteIndex];
}
SetMaterialPalette(newPalette);
}
EditorGUI.BeginChangeCheck();
s_CurrentPalette = (MaterialPalette)EditorGUILayout.ObjectField(s_CurrentPalette, typeof(MaterialPalette), false);
if (EditorGUI.EndChangeCheck())
SetMaterialPalette(s_CurrentPalette);
GUILayout.Space(4);
Material[] materials = CurrentPalette;
m_ViewScroll = GUILayout.BeginScrollView(m_ViewScroll);
for (int i = 0; i < materials.Length; i++)
{
if (i == 10)
{
GUILayout.Space(2);
GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
UI.EditorGUIUtility.DrawSeparator(1);
GUI.backgroundColor = Color.white;
GUILayout.Space(2);
}
GUILayout.BeginHorizontal();
if (i < 10)
{
if (GUILayout.Button("Alt + " + (i == 9 ? 0 : (i + 1)).ToString(), EditorStyles.miniButton, GUILayout.MaxWidth(58)))
ApplyMaterial(MeshSelection.topInternal, materials[i]);
}
else
{
if (GUILayout.Button("Apply", EditorStyles.miniButtonLeft, GUILayout.MaxWidth(44)))
ApplyMaterial(MeshSelection.topInternal, materials[i]);
GUI.backgroundColor = Color.red;
if (GUILayout.Button("", EditorStyles.miniButtonRight, GUILayout.MaxWidth(14)))
{
Material[] temp = new Material[materials.Length - 1];
System.Array.Copy(materials, 0, temp, 0, materials.Length - 1);
materials = temp;
SaveUserMaterials(materials);
return;
}
GUI.backgroundColor = Color.white;
}
EditorGUI.BeginChangeCheck();
materials[i] = (Material)EditorGUILayout.ObjectField(materials[i], typeof(Material), false);
if (EditorGUI.EndChangeCheck())
SaveUserMaterials(materials);
GUILayout.EndHorizontal();
}
if (GUILayout.Button("Add"))
{
Material[] temp = new Material[materials.Length + 1];
System.Array.Copy(materials, 0, temp, 0, materials.Length);
materials = temp;
SaveUserMaterials(materials);
}
GUILayout.EndScrollView();
}
///
/// Applies the currently queued material to the selected face and eats the event.
///
///
///
///
///
public bool ClickShortcutCheck(EventModifiers em, ProBuilderMesh pb, Face quad)
{
if (UVEditor.instance == null)
{
if (em == (EventModifiers.Control | EventModifiers.Shift))
{
UndoUtility.RecordObject(pb, "Quick Apply");
quad.material = m_QueuedMaterial;
pb.ToMesh();
pb.Refresh();
pb.Optimize();
EditorUtility.ShowNotification("Quick Apply Material");
return true;
}
}
return false;
}
static void ApplyMaterial(IEnumerable selection, Material mat)
{
if (mat == null)
return;
UndoUtility.RecordSelection(selection.ToArray(), "Set Face Materials");
foreach (var mesh in selection)
{
var applyPerFace = ProBuilderEditor.selectMode.ContainsFlag(SelectMode.Face) && mesh.faceCount > 0;
mesh.SetMaterial(applyPerFace ? mesh.GetSelectedFaces() : mesh.facesInternal, mat);
InternalMeshUtility.FilterUnusedSubmeshIndexes(mesh);
mesh.Rebuild();
mesh.Optimize();
}
if (ProBuilderEditor.instance != null && MeshSelection.selectedFaceCount > 0)
EditorUtility.ShowNotification("Set Material\n" + mat.name);
}
static void SaveUserMaterials(Material[] materials)
{
s_CurrentPalette.array = materials;
UnityEditor.EditorUtility.SetDirty(s_CurrentPalette);
AssetDatabase.SaveAssets();
}
void SetMaterialPalette(MaterialPalette palette)
{
s_CurrentPalette = palette;
RefreshAvailablePalettes();
}
void RefreshAvailablePalettes()
{
MaterialPalette cur = CurrentPalette;
m_AvailablePalettes = FileUtility.FindAndLoadAssets();
m_AvailablePalettes_Str = m_AvailablePalettes.Select(x => x.name).ToArray();
ArrayUtility.Add(ref m_AvailablePalettes_Str, string.Empty);
ArrayUtility.Add(ref m_AvailablePalettes_Str, "New Material Palette...");
m_CurrentPaletteIndex = System.Array.IndexOf(m_AvailablePalettes, cur);
s_MaterialPalettePath.SetValue(AssetDatabase.GetAssetPath(cur), true);
}
}
}