Firstborn/Assets/MeshCombiner/Editor/MeshCombinerEditor.cs
Schaken-Mods f35c8a6d6e 6/21/23 update
Upgraded the framework which includes the Distant cell rendering. I have been merging meshes to cut down the Draw calls, so far gaining on average 20FPS everywhere. New bugs are the magic fails (Again) and the environment presets fail to call when outside. Currently trying to build new lightmaps for the combined meshes.
2023-06-21 11:09:52 -05:00

145 lines
5.7 KiB
C#

using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MeshCombiner))]
public class MeshCombinerEditor : Editor
{
public override void OnInspectorGUI()
{
MeshCombiner meshCombiner = (MeshCombiner)target;
Mesh mesh = meshCombiner.GetComponent<MeshFilter>().sharedMesh;
#region Script:
GUI.enabled = false;
EditorGUILayout.ObjectField("Script", MonoScript.FromMonoBehaviour((MeshCombiner)target), typeof(MeshCombiner), false);
GUI.enabled = true;
#endregion Script.
#region MeshFiltersToSkip array:
SerializedProperty meshFiltersToSkip = serializedObject.FindProperty("meshFiltersToSkip");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(meshFiltersToSkip, true);
if(EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
#endregion MeshFiltersToSkip array.
#region Button which combine Meshes into one Mesh & Toggles with combine options:
// Button:
if(GUILayout.Button("Combine Meshes"))
{
meshCombiner.CombineMeshes(true);
}
// Toggles:
meshCombiner.CreateMultiMaterialMesh = GUILayout.Toggle(meshCombiner.CreateMultiMaterialMesh, "Create Multi-Material Mesh");
meshCombiner.CombineInactiveChildren = GUILayout.Toggle(meshCombiner.CombineInactiveChildren, "Combine Inactive Children");
meshCombiner.DeactivateCombinedChildren = GUILayout.Toggle(meshCombiner.DeactivateCombinedChildren, "Deactivate Combined Children");
meshCombiner.DeactivateCombinedChildrenMeshRenderers = GUILayout.Toggle(meshCombiner.DeactivateCombinedChildrenMeshRenderers,
"Deactivate Combined Children's MeshRenderers");
meshCombiner.GenerateUVMap = GUILayout.Toggle(meshCombiner.GenerateUVMap, new GUIContent("Generate UV Map", "It is a slow operation that "+
"generates a UV map (required for the lightmap).\n\nCan be used only in the Editor."));
// The last (6) "Destroy Combined Children" Toggle:
GUIStyle style = new GUIStyle(EditorStyles.toggle);
if(meshCombiner.DestroyCombinedChildren)
{
style.onNormal.textColor = new Color(1, 0.15f, 0);
}
meshCombiner.DestroyCombinedChildren = GUILayout.Toggle(meshCombiner.DestroyCombinedChildren,
new GUIContent("Destroy Combined Children", "In the editor this operation can NOT be undone!\n\n"+
"If you want to bring back destroyed GameObjects, you have to load again the scene without saving."), style);
#endregion Button which combine Meshes into one Mesh & Toggles with combine options.
#region Path to the folder where combined Meshes will be saved:
// Create Labels:
GUILayout.Label("");
GUILayout.Label(new GUIContent("Folder path:", "Folder path to save combined Mesh."));
// Create style wherein text color will be red if folder path is not valid:
style = new GUIStyle(EditorStyles.textField);
bool isValidPath = IsValidPath(meshCombiner.FolderPath);
if(!isValidPath)
{
style.normal.textColor = Color.red;
style.focused.textColor = Color.red;
}
// Create TextField with custom style:
meshCombiner.FolderPath = EditorGUILayout.TextField(meshCombiner.FolderPath, style);
#endregion Path to the folder where combined Meshes will be saved.
#region Button which save/show combined Mesh:
bool meshIsSaved = (mesh != null && AssetDatabase.Contains(mesh));
GUI.enabled = (mesh != null && (isValidPath || meshIsSaved)); // Valid path is required for not saved Mesh.
string saveMeshButtonText = (meshIsSaved) ? "Show Saved Combined Mesh" : "Save Combined Mesh";
if(GUILayout.Button(saveMeshButtonText))
{
meshCombiner.FolderPath = SaveCombinedMesh(mesh, meshCombiner.FolderPath);
}
GUI.enabled = true;
#endregion Button which save/show combined Mesh.
}
private bool IsValidPath(string folderPath)
{
string pattern = "[:*?\"<>|]"; // Prohibited characters.
Regex regex = new Regex(pattern);
return (!regex.IsMatch(folderPath));
}
private string SaveCombinedMesh(Mesh mesh, string folderPath)
{
bool meshIsSaved = AssetDatabase.Contains(mesh); // If is saved then only show it in the project view.
#region Create directories if Mesh and path doesn't exists:
folderPath = folderPath.Replace('\\', '/');
if(!meshIsSaved && !AssetDatabase.IsValidFolder("Assets/"+folderPath))
{
string[] folderNames = folderPath.Split('/');
folderNames = folderNames.Where((folderName) => !folderName.Equals("")).ToArray();
folderNames = folderNames.Where((folderName) => !folderName.Equals(" ")).ToArray();
folderPath = "/"; // Reset folder path.
for(int i = 0; i < folderNames.Length; i++)
{
folderNames[i] = folderNames[i].Trim();
if(!AssetDatabase.IsValidFolder("Assets"+folderPath+folderNames[i]))
{
string folderPathWithoutSlash = folderPath.Substring(0, folderPath.Length-1); // Delete last "/" character.
AssetDatabase.CreateFolder("Assets"+folderPathWithoutSlash, folderNames[i]);
}
folderPath += folderNames[i]+"/";
}
folderPath = folderPath.Substring(1, folderPath.Length-2); // Delete first and last "/" character.
}
#endregion Create directories if Mesh and path doesn't exists.
#region Save Mesh:
if(!meshIsSaved)
{
string meshPath = "Assets/"+folderPath+"/"+mesh.name+".asset";
int assetNumber = 1;
while(AssetDatabase.LoadAssetAtPath(meshPath, typeof(Mesh)) != null) // If Mesh with same name exists, change name.
{
meshPath = "Assets/"+folderPath+"/"+mesh.name+" ("+assetNumber+").asset";
assetNumber++;
}
AssetDatabase.CreateAsset(mesh, meshPath);
AssetDatabase.SaveAssets();
Debug.Log("<color=#ff9900><b>Mesh \""+mesh.name+"\" was saved in the \""+folderPath+"\" folder.</b></color>"); // Show info about saved mesh.
}
#endregion Save Mesh.
EditorGUIUtility.PingObject(mesh); // Show Mesh in the project view.
return folderPath;
}
}