test : opti
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e19eba2cab22ccf48af53f3a60cb6823
|
guid: 511a1ec77b61e6c48b73accc23ea433f
|
||||||
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bed2530773cba054c89b4104ccef2743
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(MB3_BatchPrefabBaker))]
|
||||||
|
public class MB3_BatchPrefabBakerEditor : Editor
|
||||||
|
{
|
||||||
|
SerializedObject prefabBaker = null;
|
||||||
|
|
||||||
|
GUIContent GUIContentLogLevelContent = new GUIContent("Log Level");
|
||||||
|
GUIContent GUIContentBatchBakePrefabReplacePrefab = new GUIContent("Batch Bake Prefabs (Replace Prefab)",
|
||||||
|
"This will clone the source prefab, replace the meshes in the clone with baked versions, and replace the target prefab with the clone.\n\n" +
|
||||||
|
"IF ANY CHANGES HAD BEEN MADE TO THE TARGET PREFAB, THOSE WILL BE LOST.");
|
||||||
|
GUIContent GUIContentBatchBakePrefabOnlyMeshesAndMats = new GUIContent("Batch Bake Prefabs (Only Replace Meshes & Materials)",
|
||||||
|
"This will attempt to match the meshes used by the target prefab to those used by the source prefab. For this to work well," +
|
||||||
|
" the source and target prefabs should have the same hierarchy. The meshes and materials in the target prefab will be updated to baked versions." +
|
||||||
|
" Modifications to the target prefab other than the meshes and materials will be preserved.\n\n" +
|
||||||
|
"Check the console for errors after baking the prefabs.");
|
||||||
|
|
||||||
|
SerializedProperty prefabRows, outputFolder, logLevel;
|
||||||
|
|
||||||
|
private int prefabRows_CurrentPage = 1;
|
||||||
|
private int prefabRows_NumPerPage = 50;
|
||||||
|
|
||||||
|
Color buttonColor = new Color(.8f, .8f, 1f, 1f);
|
||||||
|
|
||||||
|
[MenuItem("GameObject/Create Other/Mesh Baker/Batch Prefab Baker", false, 1000)]
|
||||||
|
public static void CreateNewBatchPrefabBaker()
|
||||||
|
{
|
||||||
|
//if (MB3_MeshCombiner.EVAL_VERSION)
|
||||||
|
//{
|
||||||
|
// Debug.LogError("The prefab baker is only available in the full version of MeshBaker.");
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
MB3_TextureBaker[] mbs = (MB3_TextureBaker[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_TextureBaker));
|
||||||
|
// Generate unique name
|
||||||
|
int largest = 0;
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mbs.Length; i++)
|
||||||
|
{
|
||||||
|
Match match = regex.Match(mbs[i].name);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
int val = Convert.ToInt32(match.Groups[1].Value);
|
||||||
|
if (val >= largest)
|
||||||
|
largest = val + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e == null) e = null; //Do nothing supress compiler warning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject nmb = new GameObject("BatchPrefabBaker (" + largest + ")");
|
||||||
|
nmb.transform.position = Vector3.zero;
|
||||||
|
|
||||||
|
MB3_BatchPrefabBaker bpb = nmb.AddComponent<MB3_BatchPrefabBaker>();
|
||||||
|
nmb.AddComponent<MB3_TextureBaker>();
|
||||||
|
nmb.AddComponent<MB3_MeshBaker>();
|
||||||
|
bpb.prefabRows = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow[0];
|
||||||
|
bpb.outputPrefabFolder = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
prefabBaker = new SerializedObject(target);
|
||||||
|
prefabRows = prefabBaker.FindProperty("prefabRows");
|
||||||
|
outputFolder = prefabBaker.FindProperty("outputPrefabFolder");
|
||||||
|
logLevel = prefabBaker.FindProperty("LOG_LEVEL");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable()
|
||||||
|
{
|
||||||
|
prefabBaker = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
prefabBaker.Update();
|
||||||
|
|
||||||
|
EditorGUILayout.HelpBox(
|
||||||
|
"This tool speeds up the process of preparing prefabs" +
|
||||||
|
" for static and dynamic batching. It creates duplicate prefab assets and meshes" +
|
||||||
|
" that share a combined material. Source assets are not touched.\n\n" +
|
||||||
|
"1) Create instances of source prefabs to this scene.\n" +
|
||||||
|
"2) Add these instances to the TextureBaker on this GameObject and bake the textures used by the prefabs.\n" +
|
||||||
|
"3) Using the BatchPrefabBaker component, click 'Populate Prefab Rows From Texture Baker' or manually set up Prefab Rows by dragging to the Prefab Rows list.\n" +
|
||||||
|
"4) Choose a folder where the result prefabs will be stored and click 'Create Empty Result Prefabs'\n" +
|
||||||
|
"5) Click 'Batch Bake Prefabs'\n" +
|
||||||
|
"6) Check the console for messages and errors\n" +
|
||||||
|
"7) (Optional) If you want to compare the source objects to the result objects use the BatchPrefabBaker '...' menu command 'Create Instances For Prefab Rows'. This will create aligned instances of the prefabs in the scene so that it is easy to see any differences.\n", MessageType.Info);
|
||||||
|
EditorGUILayout.PropertyField(logLevel, GUIContentLogLevelContent);
|
||||||
|
|
||||||
|
MB_PaginatedList.GenerateObjectsToBeCombinedList(prefabRows, ref prefabRows_CurrentPage, ref prefabRows_NumPerPage);
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Output Folder", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.LabelField(outputFolder.stringValue);
|
||||||
|
|
||||||
|
if (GUILayout.Button("Browse For Output Folder"))
|
||||||
|
{
|
||||||
|
string path = EditorUtility.OpenFolderPanel("Browse For Output Folder", "", "");
|
||||||
|
path = MB_BatchPrefabBakerEditorFunctionsCore.ConvertFullPathToProjectRelativePath(path);
|
||||||
|
outputFolder.stringValue = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Create Empty Result Prefabs"))
|
||||||
|
{
|
||||||
|
MB_BatchPrefabBakerEditorFunctions.CreateEmptyOutputPrefabs(outputFolder.stringValue, (MB3_BatchPrefabBaker) target);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color oldColor = GUI.backgroundColor;
|
||||||
|
GUI.backgroundColor = buttonColor;
|
||||||
|
if (GUILayout.Button(GUIContentBatchBakePrefabReplacePrefab))
|
||||||
|
{
|
||||||
|
MB3_BatchPrefabBaker pb = (MB3_BatchPrefabBaker)target;
|
||||||
|
MB_BatchPrefabBakerEditorFunctions.BakePrefabs(pb, true);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(GUIContentBatchBakePrefabOnlyMeshesAndMats))
|
||||||
|
{
|
||||||
|
MB3_BatchPrefabBaker pb = (MB3_BatchPrefabBaker)target;
|
||||||
|
MB_BatchPrefabBakerEditorFunctions.BakePrefabs(pb, false);
|
||||||
|
}
|
||||||
|
GUI.backgroundColor = oldColor;
|
||||||
|
|
||||||
|
if (GUILayout.Button("Populate Prefab Rows From Texture Baker"))
|
||||||
|
{
|
||||||
|
PopulatePrefabRowsFromTextureBaker((MB3_BatchPrefabBaker)prefabBaker.targetObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Open Replace Prefabs In Scene Window"))
|
||||||
|
{
|
||||||
|
MB3_BatchPrefabBaker pb = (MB3_BatchPrefabBaker)target;
|
||||||
|
MB_ReplacePrefabsInSceneEditorWindow.ShowWindow(pb.prefabRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
prefabBaker.ApplyModifiedProperties();
|
||||||
|
prefabBaker.SetIsDifferentCacheDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PopulatePrefabRowsFromTextureBaker(MB3_BatchPrefabBaker prefabBaker)
|
||||||
|
{
|
||||||
|
MB3_TextureBaker texBaker = prefabBaker.GetComponent<MB3_TextureBaker>();
|
||||||
|
List<GameObject> newPrefabs = new List<GameObject>();
|
||||||
|
List<GameObject> gos = texBaker.GetObjectsToCombine();
|
||||||
|
for (int i = 0; i < gos.Count; i++)
|
||||||
|
{
|
||||||
|
if (gos[i] == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Prefab in Objects To Be Combined at index " + i + " is null. Make sure that all objects to be batched are non-null prefabs.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GameObject go = (GameObject)MBVersionEditor.PrefabUtility_FindPrefabRoot(gos[i]);
|
||||||
|
if (go == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Could not find prefab root for " + gos[i] + " at index " + i + ". Make sure that all objects to be batched are non-null prefabs.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UnityEngine.Object obj = MBVersionEditor.PrefabUtility_GetCorrespondingObjectFromSource(go);
|
||||||
|
|
||||||
|
if (obj != null && obj is GameObject)
|
||||||
|
{
|
||||||
|
if (!newPrefabs.Contains((GameObject)obj)) newPrefabs.Add((GameObject)obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning(String.Format("Object {0} did not have a prefab", gos[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove prefabs that are already in the list of batch prefab baker's prefabs.
|
||||||
|
{
|
||||||
|
List<GameObject> tmpNewPrefabs = new List<GameObject>();
|
||||||
|
for (int i = 0; i < newPrefabs.Count; i++)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (int j = 0; j < prefabBaker.prefabRows.Length; j++)
|
||||||
|
{
|
||||||
|
if (prefabBaker.prefabRows[j].sourcePrefab == newPrefabs[i])
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
tmpNewPrefabs.Add(newPrefabs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newPrefabs = tmpNewPrefabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MB3_MeshCombiner.EVAL_VERSION)
|
||||||
|
{
|
||||||
|
int numPrefabsLimit = MB_BatchPrefabBakerEditorFunctions.EvalVersionPrefabLimit;
|
||||||
|
int numNew = numPrefabsLimit - prefabBaker.prefabRows.Length;
|
||||||
|
if (newPrefabs.Count + prefabBaker.prefabRows.Length > numPrefabsLimit)
|
||||||
|
{
|
||||||
|
Debug.LogError("The free version of Mesh Baker is limited to batch baking " + numPrefabsLimit +
|
||||||
|
" prefabs. The full version has no limit on the number of prefabs that can be baked. " + (newPrefabs.Count - numNew) + " prefabs were not added.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = newPrefabs.Count - 1; i >= numNew; i--)
|
||||||
|
{
|
||||||
|
newPrefabs.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MB3_BatchPrefabBaker.MB3_PrefabBakerRow> newRows = new List<MB3_BatchPrefabBaker.MB3_PrefabBakerRow>();
|
||||||
|
if (prefabBaker.prefabRows == null) prefabBaker.prefabRows = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow[0];
|
||||||
|
newRows.AddRange(prefabBaker.prefabRows);
|
||||||
|
for (int i = 0; i < newPrefabs.Count; i++)
|
||||||
|
{
|
||||||
|
MB3_BatchPrefabBaker.MB3_PrefabBakerRow row = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow();
|
||||||
|
row.sourcePrefab = newPrefabs[i];
|
||||||
|
newRows.Add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Undo.RecordObject(prefabBaker, "Populate prefab rows");
|
||||||
|
prefabBaker.prefabRows = newRows.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9eec7d996f61d7245a9c9d169979b8dd
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_BatchPrefabBakerEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2015-2016 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
[CustomEditor(typeof(MB3_BoneWeightCopier))]
|
||||||
|
public class MB3_BoneWeightCopierEditor : Editor
|
||||||
|
{
|
||||||
|
SerializedProperty inputGameObjectProp;
|
||||||
|
SerializedProperty outputPrefabProp;
|
||||||
|
SerializedProperty radiusProp;
|
||||||
|
SerializedProperty seamMeshProp;
|
||||||
|
SerializedProperty targetMeshesProp;
|
||||||
|
SerializedProperty outputFolderProp;
|
||||||
|
|
||||||
|
GameObject copyOfInput;
|
||||||
|
|
||||||
|
GUIContent gc_inputGameObject = new GUIContent("Input Game Object", "Assign the parent object of all the Skinned Meshes to this field.");
|
||||||
|
GUIContent gc_outputPrefab = new GUIContent("Output Prefab", "Provide a GameObject Prefab that the Bone Weight Copier will output to.");
|
||||||
|
GUIContent gc_radius = new GUIContent("Radius", "Vertices in each Target Mesh that are within Radius of a vertex in the Seam Mesh will be assigned the same bone weight as the Seam Mesh vertex.");
|
||||||
|
GUIContent gc_seamMesh = new GUIContent("Seam Mesh", "The seam mesh should contain vertices for the seams with correct bone weights. Seams are the vertices that are shared by two skinned meshes that overlap. For example there should be a seam between an arm skinned mesh and a hand skinned mesh.");
|
||||||
|
GUIContent gc_outputFolder = new GUIContent("Output Folder", "Copies of the Skinned Meshes will be saved to this folder, must be located in the project Assets folder.");
|
||||||
|
|
||||||
|
[MenuItem("GameObject/Create Other/Mesh Baker/Bone Weight Copier", false, 1000)]
|
||||||
|
public static GameObject CreateNewMeshBaker()
|
||||||
|
{
|
||||||
|
GameObject nmb = new GameObject("BoneWeightCopier");
|
||||||
|
nmb.transform.position = Vector3.zero;
|
||||||
|
nmb.AddComponent<MB3_BoneWeightCopier>();
|
||||||
|
return nmb.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
radiusProp = serializedObject.FindProperty("radius");
|
||||||
|
seamMeshProp = serializedObject.FindProperty("seamMesh");
|
||||||
|
//targetMeshesProp = serializedObject.FindProperty("targetMeshes");
|
||||||
|
outputFolderProp = serializedObject.FindProperty("outputFolder");
|
||||||
|
inputGameObjectProp = serializedObject.FindProperty("inputGameObject");
|
||||||
|
outputPrefabProp = serializedObject.FindProperty("outputPrefab");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
serializedObject.Update();
|
||||||
|
MB3_BoneWeightCopier bwc = (MB3_BoneWeightCopier)target;
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.HelpBox("== BETA (please report problems) ==\n\n" +
|
||||||
|
"This tool helps create skinned mesh parts that can be mix and matched to customize characters. " +
|
||||||
|
"It adjusts the boneWeights, positions, normals and tangents at the joins to have the same values so there are no tears." +
|
||||||
|
"\n\n" +
|
||||||
|
"1) Model the skinned meshes and attach them all to the same rig. The rig may have multiple arms, hands, hair etc...\n" +
|
||||||
|
"2) At every seam (eg. between an arm mesh and hand mesh) there must be a set of vertices duplicated in both meshes.\n" +
|
||||||
|
"3) Create one additional mesh that contains another copy of all the geometry. This will be called the Seam Mesh\n" +
|
||||||
|
"4) Attach it to the rig and adjust the bone weights. This will be the master set of bone weights that will be copied to all the other skinned meshes.\n" +
|
||||||
|
"5) Mark the seam vertices using the UV channel.\n" +
|
||||||
|
" verts with UV > (.5,.5) are seam verts\n" +
|
||||||
|
" verts with UV < (.5,.5) are ignored\n" +
|
||||||
|
"6) Import the model into Unity and create an instance of it in the scene\n" +
|
||||||
|
"7) Assign the Seam Mesh to the Seam Mesh field\n" +
|
||||||
|
"8) Assign the parent game object of all the skinned meshes to the Input Game Object field\n" +
|
||||||
|
"9) Adjust the radius\n" +
|
||||||
|
"10) Choose an output folder and save the meshes\n" +
|
||||||
|
"11) Click 'Copy Bone Weights From Seam Mesh'\n", MessageType.Info);
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(radiusProp, gc_radius);
|
||||||
|
EditorGUILayout.PropertyField(seamMeshProp, gc_seamMesh);
|
||||||
|
EditorGUILayout.PropertyField(inputGameObjectProp, gc_inputGameObject);
|
||||||
|
EditorGUILayout.PropertyField(outputPrefabProp, gc_outputPrefab);
|
||||||
|
//if (GUILayout.Button("Get Skinned Meshes From Input Game Object")) {
|
||||||
|
// GetSkinnedMeshesFromGameObject(bwc);
|
||||||
|
//}
|
||||||
|
//EditorGUILayout.PropertyField(targetMeshesProp,true);
|
||||||
|
|
||||||
|
if (GUILayout.Button("Copy Bone Weights From Seam Mesh"))
|
||||||
|
{
|
||||||
|
CopyBoneWeightsFromSeamMeshToOtherMeshes(bwc);
|
||||||
|
}
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
EditorGUILayout.LabelField("Save Meshes To Project Folder", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(outputFolderProp, gc_outputFolder);
|
||||||
|
bool pathIsValid;
|
||||||
|
string errorMessage;
|
||||||
|
{
|
||||||
|
string path = outputFolderProp.stringValue;
|
||||||
|
outputFolderProp.stringValue =
|
||||||
|
MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(path, out errorMessage,
|
||||||
|
out pathIsValid);
|
||||||
|
Debug.Assert(errorMessage != null, "errorMessage should never be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Browse"))
|
||||||
|
{
|
||||||
|
string path = EditorUtility.OpenFolderPanel("Browse For Output Folder", "", "");
|
||||||
|
path = MB_BatchPrefabBakerEditorFunctionsCore.ConvertFullPathToProjectRelativePath(path);
|
||||||
|
outputFolderProp.stringValue = path;
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (!pathIsValid)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Set Output Folder To Output Prefab Folder"))
|
||||||
|
{
|
||||||
|
string path = AssetDatabase.GetAssetPath(bwc.outputPrefab);
|
||||||
|
path = new System.IO.FileInfo(path).Directory.FullName.Replace('\\', '/');
|
||||||
|
path = MB_BatchPrefabBakerEditorFunctionsCore.ConvertFullPathToProjectRelativePath(path);
|
||||||
|
outputFolderProp.stringValue = path;
|
||||||
|
}
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyBoneWeightsFromSeamMeshToOtherMeshes(MB3_BoneWeightCopier bwc)
|
||||||
|
{
|
||||||
|
if (bwc.seamMesh == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("The Seam Mesh cannot be null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bwc.inputGameObject == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("The Input Game Object cannot be null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEngine.Object pr = (UnityEngine.Object) MBVersionEditor.PrefabUtility_FindPrefabRoot(bwc.seamMesh.gameObject);
|
||||||
|
string assetPath = null;
|
||||||
|
if (pr != null)
|
||||||
|
{
|
||||||
|
assetPath = AssetDatabase.GetAssetPath(pr);
|
||||||
|
}
|
||||||
|
if (assetPath != null)
|
||||||
|
{
|
||||||
|
ModelImporter mi = (ModelImporter)AssetImporter.GetAtPath(assetPath);
|
||||||
|
if (mi != null)
|
||||||
|
{
|
||||||
|
if (mi.optimizeGameObjects)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("The seam mesh has 'optimize game objects' checked in the asset importer rig tab. This will result in no bones. Uncheck 'optimize game objects' in the rig tab."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check that inputGameObject contains all the bones;
|
||||||
|
Transform[] bones = bwc.seamMesh.bones;
|
||||||
|
for (int i = 0; i < bones.Length; i++)
|
||||||
|
{
|
||||||
|
Transform b = bones[i];
|
||||||
|
if (b == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("There are null bones on the seam mesh.");
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (!IsChildOf(bwc.inputGameObject.transform, b))
|
||||||
|
{
|
||||||
|
Debug.LogError("All bones used by the seam mesh must be children of the Input Game Object. There were some bones that were not a children of the seam mesh.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bwc.outputPrefab == null)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("The output game object must be assigned and must be a prefab of a game object in the project folder."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MBVersionEditor.PrefabUtility_GetPrefabType(bwc.outputPrefab) != MB_PrefabType.prefabAsset)
|
||||||
|
{
|
||||||
|
Debug.LogError("The output game object must be a prefab. Create a prefab in the project and drag an empty game object to it.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//duplicate the source prefab and the meshes
|
||||||
|
if (copyOfInput != null)
|
||||||
|
{
|
||||||
|
DestroyImmediate(copyOfInput);
|
||||||
|
}
|
||||||
|
copyOfInput = (GameObject)GameObject.Instantiate(bwc.inputGameObject);
|
||||||
|
|
||||||
|
Transform seamMeshCopyTransform = MB_BatchPrefabBakerEditorFunctionsCore.FindCorrespondingTransform(bwc.inputGameObject.transform, bwc.seamMesh.transform, copyOfInput.transform);
|
||||||
|
SkinnedMeshRenderer seamMeshCopy = seamMeshCopyTransform.GetComponent<SkinnedMeshRenderer>();
|
||||||
|
|
||||||
|
Transform[] seamMeshBones = seamMeshCopy.bones;
|
||||||
|
SkinnedMeshRenderer[] targSkinnedMeshes = copyOfInput.GetComponentsInChildren<SkinnedMeshRenderer>();
|
||||||
|
Transform[][] targMeshBones = new Transform[targSkinnedMeshes.Length][];
|
||||||
|
Mesh[] targs = new Mesh[targSkinnedMeshes.Length];
|
||||||
|
for (int i = 0; i < targSkinnedMeshes.Length; i++)
|
||||||
|
{
|
||||||
|
if (targSkinnedMeshes[i].sharedMesh == null)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("Skinned Mesh {0} does not have a mesh", targSkinnedMeshes[i]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MB_PrefabType pt = MBVersionEditor.PrefabUtility_GetPrefabType(targSkinnedMeshes[i].gameObject);
|
||||||
|
if (pt == MB_PrefabType.modelPrefabAsset)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("Target Mesh {0} is an imported model prefab. Can't modify these meshes because changes will be overwritten the next time the model is saved or reimported. Try instantiating the prefab and using skinned meshes from the scene instance.", i));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targMeshBones[i] = targSkinnedMeshes[i].bones;
|
||||||
|
targs[i] = (Mesh)GameObject.Instantiate(targSkinnedMeshes[i].sharedMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform[][] newBonesForSMRs = new Transform[targs.Length][];
|
||||||
|
MB3_CopyBoneWeights.CopyBoneWeightsFromSeamMeshToOtherMeshes(bwc.radius, seamMeshCopy.sharedMesh, targs, newBonesForSMRs, seamMeshBones, targMeshBones);
|
||||||
|
SaveMeshesToOutputFolderAndAssignToSMRs(targs, newBonesForSMRs, targSkinnedMeshes);
|
||||||
|
|
||||||
|
EditorUtility.SetDirty(copyOfInput);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO tried using 2018 replace prefab but there were errors.
|
||||||
|
//MBVersionEditor.ReplacePrefab(copyOfInput, assetPath, MB_ReplacePrefabOption.connectToPrefab | MB_ReplacePrefabOption.nameBased);
|
||||||
|
string prefabPth = AssetDatabase.GetAssetPath(bwc.outputPrefab);
|
||||||
|
MBVersionEditor.PrefabUtility_ReplacePrefab(copyOfInput, prefabPth, MB_ReplacePrefabOption.connectToPrefab | MB_ReplacePrefabOption.nameBased);
|
||||||
|
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
DestroyImmediate(copyOfInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveMeshesToOutputFolderAndAssignToSMRs(Mesh[] targetMeshes, Transform[][] newBonesForSMRs, SkinnedMeshRenderer[] targetSMRs)
|
||||||
|
{
|
||||||
|
Debug.Assert(targetMeshes.Length == newBonesForSMRs.Length);
|
||||||
|
//validate meshes
|
||||||
|
for (int i = 0; i < targetMeshes.Length; i++)
|
||||||
|
{
|
||||||
|
if (targetMeshes[i] == null)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("An error occured processing mesh {0}. Mesh could not be saved.", targetSMRs[i]));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (targetSMRs[i] == null)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("Target SkinnedMesh {0} is null", i));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetSMRs[i].sharedMesh == null)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("Target Mesh {0} does not have a mesh", i));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MB_PrefabType pt = MBVersionEditor.PrefabUtility_GetPrefabType(targetMeshes[i]);
|
||||||
|
if (pt == MB_PrefabType.modelPrefabAsset)
|
||||||
|
{
|
||||||
|
Debug.LogError(string.Format("Target Mesh {0} is an imported model prefab. Can't modify these meshes because changes will be overwritten the next time the model is saved or reimported. Try instantiating the prefab and using skinned meshes from the scene instance.", i));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//validate output folder
|
||||||
|
if (outputFolderProp.stringValue == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Output folder must be set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
{
|
||||||
|
string errorMessage;
|
||||||
|
bool pathIsValid;
|
||||||
|
outputFolderProp.stringValue =
|
||||||
|
MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(
|
||||||
|
outputFolderProp.stringValue, out errorMessage, out pathIsValid);
|
||||||
|
if (!pathIsValid)
|
||||||
|
{
|
||||||
|
Debug.LogError(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < targetMeshes.Length; i++)
|
||||||
|
{
|
||||||
|
Mesh m = targetMeshes[i];
|
||||||
|
if (m == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string pth = outputFolderProp.stringValue + "/" + targetMeshes[i].name + ".Asset";
|
||||||
|
if (pth == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("The output folder must be a folder in the project Assets folder.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debug.Log("Creating mesh " + m + " path " + pth + " numBindPoses: " + m.bindposes.Length + " targSMRs numBones: " + targetSMRs[i].bones.Length);
|
||||||
|
targetSMRs[i].sharedMesh = m;
|
||||||
|
if (newBonesForSMRs[i] != null) targetSMRs[i].bones = newBonesForSMRs[i];
|
||||||
|
AssetDatabase.CreateAsset(m, pth);
|
||||||
|
targetSMRs[i].sharedMesh = m;
|
||||||
|
Debug.Log(string.Format("Created mesh at {0}. Updated Skinned Mesh {1} to use created mesh.", pth, targetSMRs[i].name));
|
||||||
|
}
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsChildOf(Transform parent, Transform child)
|
||||||
|
{
|
||||||
|
if (parent == null) return false;
|
||||||
|
if (child == null) return false;
|
||||||
|
Transform t = child.parent;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (t == parent || t.parent == parent)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
t = t.parent;
|
||||||
|
} while (t != child.root);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0a5f54a19161b7e489e7c1815bb56b79
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_BoneWeightCopierEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,374 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2024 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// MB3_ColorTintTextureGenerator handles all the logic for the MB3_CreateCOlorTintWindow class.
|
||||||
|
///
|
||||||
|
/// Provides functionality for detecting materials which are candidates for color tint texture generation and for performing this generation.
|
||||||
|
///
|
||||||
|
/// Makes use of the ColorTintTextureData structure which is also defined in this file to pass information to the MB3_CreateColorTintWindow class.
|
||||||
|
/// </summary>
|
||||||
|
public class MB3_ColorTintTextureGenerator
|
||||||
|
{
|
||||||
|
public struct ColorTintTextureData
|
||||||
|
{
|
||||||
|
public Material mat;
|
||||||
|
public bool willGenerateColorTexture;
|
||||||
|
public bool hasColorProperty;
|
||||||
|
public bool hasTextureProperty;
|
||||||
|
public Color colorProperty;
|
||||||
|
public Texture textureProperty;
|
||||||
|
public List<string> messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private MB3_TextureBaker textureBaker;
|
||||||
|
private Dictionary<Color, string> color2TexMap;
|
||||||
|
|
||||||
|
public MB3_ColorTintTextureGenerator(MB3_TextureBaker tb)
|
||||||
|
{
|
||||||
|
textureBaker = tb;
|
||||||
|
color2TexMap = new Dictionary<Color, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ColorTintTextureData> GenerateColorTintTextures(MB3_TextureBaker tb, List<ColorTintTextureData> ctData,
|
||||||
|
string path, int texSize,
|
||||||
|
string[] colorProps, string[] albedoProps,
|
||||||
|
bool applyChanges, out List<string> fileNames)
|
||||||
|
{
|
||||||
|
// validate inputs
|
||||||
|
if (textureBaker == null)
|
||||||
|
{
|
||||||
|
string errorMsg = "Texture baker is not set. This operation requires a texture baker reference.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
else if (tb != textureBaker)
|
||||||
|
{
|
||||||
|
string errorMsg = "Selected texture baker has changed since material list was found.\nPlease find color tint textures again before attempting to generate.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
if (applyChanges && (path == null || path == ""))
|
||||||
|
{
|
||||||
|
string errorMsg = "Folder path must be selected before color tint textures can be generated.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
if (applyChanges && ctData == null)
|
||||||
|
{
|
||||||
|
string errorMsg = "Color tint textures must be found before color tint textures can be generated. Please click \'Find Color Tint Textures\' first.\nThis error may occur if texture baker is changed after color tint textures are found.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
if (!MB3_MeshBakerRoot.ValidateTextureBakerGameObjects(textureBaker,
|
||||||
|
textureBaker.GetObjectsToCombine(),
|
||||||
|
MB2_ValidationLevel.quick))
|
||||||
|
{
|
||||||
|
string errorMsg = "Something went wrong when validating the game objects belonging to the texture baker." +
|
||||||
|
"Double check that your texture baker is set up correctly.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
// check if we have at least one colorprop and one albedoprop to search for
|
||||||
|
if (colorProps.Length <= 0)
|
||||||
|
{
|
||||||
|
string errorMsg = "No color properties provided." +
|
||||||
|
"There must be at least one color property present in the array.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < colorProps.Length; i++)
|
||||||
|
{
|
||||||
|
if (colorProps[i] == "")
|
||||||
|
{
|
||||||
|
string errorMsg = "One or more of your color properties is empty." +
|
||||||
|
"Please ensure all properties have an assigned string.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (albedoProps.Length <= 0)
|
||||||
|
{
|
||||||
|
string errorMsg = "No albedo properties provided." +
|
||||||
|
"There must be at least one albedo property present in the array.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < albedoProps.Length; i++)
|
||||||
|
{
|
||||||
|
if (albedoProps[i] == "")
|
||||||
|
{
|
||||||
|
string errorMsg = "One or more of your albedo properties is empty." +
|
||||||
|
"Please ensure all properties have an assigned string.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<GameObject> objsToCombine = textureBaker.GetObjectsToCombine();
|
||||||
|
// check that objects have been added to texture baker
|
||||||
|
if (objsToCombine.Count == 0)
|
||||||
|
{
|
||||||
|
string errorMsg = "No game objects have been added to the selected Texture Baker.";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle initializations
|
||||||
|
List<ColorTintTextureData> dataList = new List<ColorTintTextureData>();
|
||||||
|
fileNames = new List<string>();
|
||||||
|
color2TexMap.Clear();
|
||||||
|
// retrieve materials from ObjectsToCombine
|
||||||
|
List<Material> matsToCombine = new List<Material>();
|
||||||
|
for (int i = 0; i < objsToCombine.Count; i++)
|
||||||
|
{
|
||||||
|
matsToCombine.AddRange(objsToCombine[i].GetComponent<Renderer>().sharedMaterials.ToList());
|
||||||
|
}
|
||||||
|
// ensure our material list does not contain duplicates
|
||||||
|
matsToCombine = matsToCombine.Distinct().ToList();
|
||||||
|
//do validation on materials
|
||||||
|
for (int i = matsToCombine.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
ColorTintTextureData data = new ColorTintTextureData
|
||||||
|
{
|
||||||
|
messages = new List<string>(),
|
||||||
|
willGenerateColorTexture = true,
|
||||||
|
mat = matsToCombine[i]
|
||||||
|
};
|
||||||
|
Material mat = matsToCombine[i];
|
||||||
|
|
||||||
|
// check if material is null
|
||||||
|
if (mat == null)
|
||||||
|
{
|
||||||
|
data.willGenerateColorTexture = false;
|
||||||
|
data.messages.Add("Material was null.");
|
||||||
|
matsToCombine.Remove(mat);
|
||||||
|
}
|
||||||
|
else if (!AssetDatabase.GetAssetPath(mat).Contains("Assets"))
|
||||||
|
{
|
||||||
|
data.willGenerateColorTexture = false;
|
||||||
|
data.messages.Add("Material was not in the \'Assets\' folder: " + mat);
|
||||||
|
matsToCombine.Remove(mat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check if material has no albedo texture or color tint (remove from list)
|
||||||
|
data.hasColorProperty = false;
|
||||||
|
data.hasTextureProperty = false;
|
||||||
|
data.colorProperty = GetColorFromMaterial(mat, colorProps, out data.hasColorProperty);
|
||||||
|
data.textureProperty = GetTextureFromMaterial(mat, albedoProps, out data.hasTextureProperty);
|
||||||
|
|
||||||
|
if (!data.hasColorProperty)
|
||||||
|
{
|
||||||
|
data.willGenerateColorTexture = false;
|
||||||
|
data.messages.Add("Color property could not be detected.");
|
||||||
|
}
|
||||||
|
if (!data.hasTextureProperty)
|
||||||
|
{
|
||||||
|
data.willGenerateColorTexture = false;
|
||||||
|
data.messages.Add("Texture property could not be detected.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if material has texture property field the value of that field must be null or mat will be removed
|
||||||
|
if (data.textureProperty != null)
|
||||||
|
{
|
||||||
|
data.willGenerateColorTexture = false;
|
||||||
|
data.messages.Add("Material " + mat + "already has albedo texture in detected texture property.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data.willGenerateColorTexture)
|
||||||
|
{
|
||||||
|
matsToCombine.Remove(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataList.Add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applyChanges)
|
||||||
|
{
|
||||||
|
// get unique colors
|
||||||
|
List<Color> colorsOnMats = new List<Color>();
|
||||||
|
Undo.RecordObjects(matsToCombine.ToArray(), "Color Tint Texture Generation");
|
||||||
|
for (int i = 0; i < matsToCombine.Count; i++)
|
||||||
|
{
|
||||||
|
Material mat = matsToCombine[i];
|
||||||
|
if (mat != null)
|
||||||
|
{
|
||||||
|
Color tintColor;
|
||||||
|
bool foundColor;
|
||||||
|
tintColor = GetColorFromMaterial(mat, colorProps, out foundColor);
|
||||||
|
// at this point we should be able to assume that the material has a color associated with one of our property names
|
||||||
|
Debug.Assert(foundColor, "Expected material " + mat + " to have a detectable color property but none was found.");
|
||||||
|
colorsOnMats.Add(tintColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colorsOnMats = colorsOnMats.Distinct().ToList();
|
||||||
|
for (int i = 0; i < colorsOnMats.Count; i++)
|
||||||
|
{
|
||||||
|
Color tintColor = colorsOnMats[i];
|
||||||
|
Texture2D tintTexture;
|
||||||
|
if (!color2TexMap.ContainsKey(tintColor))
|
||||||
|
{
|
||||||
|
string filePath = BuildAndSaveColorTintTexture(path, "ColorTintTexture" + i, texSize, tintColor, out tintTexture);
|
||||||
|
fileNames.Add(filePath);
|
||||||
|
color2TexMap.Add(tintColor, filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssignTintTexturesToMaterials(matsToCombine, colorProps, albedoProps);
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildAndSaveColorTintTexture(string path, string fileName, int texSize,
|
||||||
|
Color tintColor, out Texture2D tintTexture)
|
||||||
|
{
|
||||||
|
// create size by size texture filled with 'color' pixels
|
||||||
|
bool linear = false;
|
||||||
|
switch (PlayerSettings.colorSpace)
|
||||||
|
{
|
||||||
|
case ColorSpace.Uninitialized:
|
||||||
|
string errorMsg = "Project color space is not initialized. Could not generate 2D textures";
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
case ColorSpace.Gamma:
|
||||||
|
linear = false;
|
||||||
|
break;
|
||||||
|
case ColorSpace.Linear:
|
||||||
|
linear = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tintTexture = new Texture2D(texSize, texSize, TextureFormat.RGBA32, true, linear);
|
||||||
|
Color[] pixels = new Color[texSize * texSize];
|
||||||
|
for (int i = 0; i < pixels.Length; i++)
|
||||||
|
{
|
||||||
|
pixels[i] = tintColor;
|
||||||
|
}
|
||||||
|
tintTexture.SetPixels(pixels);
|
||||||
|
tintTexture.Apply();
|
||||||
|
|
||||||
|
// save texture as file in 'path' folder
|
||||||
|
string filePath = path + "/" + fileName + ".asset";
|
||||||
|
filePath = AssetDatabase.GenerateUniqueAssetPath(filePath);
|
||||||
|
|
||||||
|
// Write the PNG texture data to a file
|
||||||
|
AssetDatabase.CreateAsset(tintTexture, filePath);
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssignTintTexturesToMaterials(List<Material> mats, string[] colorProps, string[] albedoProps)
|
||||||
|
{
|
||||||
|
// visit each source material
|
||||||
|
for (int i = 0; i < mats.Count; i++)
|
||||||
|
{
|
||||||
|
Material mat = mats[i];
|
||||||
|
if (mat != null)
|
||||||
|
{
|
||||||
|
// get color tint
|
||||||
|
bool foundColor;
|
||||||
|
Color tintColor = GetColorFromMaterial(mat, colorProps, out foundColor);
|
||||||
|
Debug.Assert(foundColor, "Expected material " + mat + " to have a detectable color property but none was found.");
|
||||||
|
// feed color tint into dictionary and assign corresponding texture to material
|
||||||
|
string texturePath = color2TexMap[tintColor];
|
||||||
|
Texture2D textureToAssign = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D));
|
||||||
|
bool foundTexture;
|
||||||
|
SetMaterialTexture(mat, albedoProps, textureToAssign, out foundTexture);
|
||||||
|
Debug.Assert(foundTexture, "Expected material " + mat + " to have detectable texture property but none was found.");
|
||||||
|
SetMaterialColorToDefault(mat, colorProps, out foundColor);
|
||||||
|
Debug.Assert(foundColor, "Material " + mat + " had detectable material property when fetching color but not when setting color.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetColorFromMaterial(Material mat, string[] colorProperties, out bool foundColor)
|
||||||
|
{
|
||||||
|
Color color = new Color();
|
||||||
|
for (int i = 0; i < colorProperties.Length; i++)
|
||||||
|
{
|
||||||
|
string prop = colorProperties[i];
|
||||||
|
if (mat.HasProperty(prop))
|
||||||
|
{
|
||||||
|
color = mat.GetColor(prop);
|
||||||
|
foundColor = true;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundColor = false;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetMaterialColorToDefault(Material mat, string[] colorProps, out bool foundColor)
|
||||||
|
{
|
||||||
|
foundColor = false;
|
||||||
|
for (int i = 0; i < colorProps.Length; i++)
|
||||||
|
{
|
||||||
|
if (mat.HasProperty(colorProps[i]))
|
||||||
|
{
|
||||||
|
Color currentColor = mat.GetColor(colorProps[i]);
|
||||||
|
if (currentColor != Color.white)
|
||||||
|
{
|
||||||
|
mat.SetColor(colorProps[i], Color.white);
|
||||||
|
}
|
||||||
|
foundColor = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetMaterialTexture(Material mat, string[] albedoProps, Texture2D tex, out bool foundTexture)
|
||||||
|
{
|
||||||
|
foundTexture = false;
|
||||||
|
for (int i = 0; i < albedoProps.Length; i++)
|
||||||
|
{
|
||||||
|
if (mat.HasProperty(albedoProps[i]))
|
||||||
|
{
|
||||||
|
mat.SetTexture(albedoProps[i], tex);
|
||||||
|
foundTexture = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Texture GetTextureFromMaterial(Material mat, string[] texProperties, out bool foundTex)
|
||||||
|
{
|
||||||
|
Texture tex = null;
|
||||||
|
for (int i = 0; i < texProperties.Length; i++)
|
||||||
|
{
|
||||||
|
string prop = texProperties[i];
|
||||||
|
if (mat.HasProperty(prop))
|
||||||
|
{
|
||||||
|
tex = mat.GetTexture(prop);
|
||||||
|
foundTex = true;
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundTex = false;
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string BrowseOutputFolder()
|
||||||
|
{
|
||||||
|
string errorMsg;
|
||||||
|
bool success;
|
||||||
|
string path = EditorUtility.OpenFolderPanel("Browse for Output Folder", "", "");
|
||||||
|
path = MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(path, out errorMsg, out success);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError(errorMsg);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ddcca7684ef63bf4e99a0ecddc7a86ea
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_ColorTintTextureGenerator.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,274 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2024 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Component that handles the UI for generating color tint textures for all materials in meshRenderers that belong to the texture baker.
|
||||||
|
///
|
||||||
|
/// The user is able to set a folder for textures to be generated to, set generated texture size, and add or remove color and albedo texture property names
|
||||||
|
/// that will be used when searching for materials that are candidates for color tint texture generation.
|
||||||
|
///
|
||||||
|
/// The user can see a list of all available materials under the texture baker and whether color tint textures will be generated for them or not.
|
||||||
|
/// Once the user is satisfied with this list they can generate color tint textures which will automatically be assigned to the relevant materials.
|
||||||
|
///
|
||||||
|
/// All the logic for this window is handled in the MB3_ColorTintTextureGenerator class.
|
||||||
|
/// </summary>
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB3_CreateColorTintWindow : EditorWindow
|
||||||
|
{
|
||||||
|
public MB3_TextureBaker textureBaker;
|
||||||
|
public MB3_TextureBaker newTextureBaker;
|
||||||
|
public string folderPath = "";
|
||||||
|
|
||||||
|
public int texSize = 16;
|
||||||
|
[SerializeField]
|
||||||
|
public string[] colorTintList = {
|
||||||
|
"_Color", //Built-in RP
|
||||||
|
"_BaseColor", //URP and HDRP
|
||||||
|
"_ColorTint", //Commonly Used
|
||||||
|
};
|
||||||
|
public SerializedObject colorTintWindowObject;
|
||||||
|
public SerializedProperty colorTintProperty;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
public string[] albedoMapList = {
|
||||||
|
"_MainTex", //Built-in RP
|
||||||
|
"_BaseMap", // URP
|
||||||
|
"_BaseColorMap", //HDRP
|
||||||
|
};
|
||||||
|
|
||||||
|
public SerializedProperty albedoMapProperty;
|
||||||
|
|
||||||
|
private MB3_ColorTintTextureGenerator ctGen;
|
||||||
|
private bool doneGeneration = false;
|
||||||
|
private bool errorState;
|
||||||
|
private string errorMsg;
|
||||||
|
private List<MB3_ColorTintTextureGenerator.ColorTintTextureData> ctData;
|
||||||
|
private List<string> generatedFiles;
|
||||||
|
private Vector2 scrollPos;
|
||||||
|
private static GUIContent
|
||||||
|
gc_textureBakerSelect = new GUIContent("Texture Baker", "Choose texture baker. Solid color textures will be added to materials used by the \'Objects To Be Combined\'."),
|
||||||
|
gc_folderSelectHeader = new GUIContent("Select Folder for Saving Textures:", "Must be a valid folder in the Assets folder."),
|
||||||
|
gc_folderSelectButton = new GUIContent("Browse for Output Folder", "Must be a valid folder in the Assets folder."),
|
||||||
|
gc_colorPropertyNames = new GUIContent("Color Tint Property names",
|
||||||
|
"List of color tint property names that will be seached for in the source object materials."),
|
||||||
|
gc_albedoPropertyNames = new GUIContent("Albedo Map Property names",
|
||||||
|
"This is the list of texture property names that searched for in the source object materials. If this property is empty, it will be assigned a generated solid color texture."),
|
||||||
|
gc_texSizeField = new GUIContent("Set Texture Size in Pixels (must be power of two):", "The height/width size in pixels of the color tint textures that will be generated. This field must be a power of two."),
|
||||||
|
gc_findButton = new GUIContent("Find Color Tint Textures", "Search all materials used by 'Objects To Be Combined' for empty albedo texture properties and color tint properties. No assets will be modified. Results will be reported."),
|
||||||
|
gc_generateButton = new GUIContent("Generate Color Tint Textures", "Create new solid color textures and assign them to source materials. This will modify source material assets.");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[MenuItem("Window/Mesh Baker/Generate Color Tint Textures")]
|
||||||
|
public static void Open()
|
||||||
|
{
|
||||||
|
// open window
|
||||||
|
MB3_CreateColorTintWindow ctWin = (MB3_CreateColorTintWindow)EditorWindow.GetWindow(typeof(MB3_CreateColorTintWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
colorTintWindowObject = new SerializedObject(this);
|
||||||
|
colorTintProperty = colorTintWindowObject.FindProperty("colorTintList");
|
||||||
|
albedoMapProperty = colorTintWindowObject.FindProperty("albedoMapList");
|
||||||
|
scrollPos = Vector2.zero;
|
||||||
|
errorState = false;
|
||||||
|
errorMsg = "";
|
||||||
|
ctData = null;
|
||||||
|
ctGen = null;
|
||||||
|
generatedFiles = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
//update serialized object
|
||||||
|
colorTintWindowObject.Update();
|
||||||
|
|
||||||
|
EditorGUILayout.HelpBox("This window finds materials used by the texture baker list of objects to be combined which have a color tint and no albedo texture. " +
|
||||||
|
"It will create solid color textures matching the color tint and assign them to the source material's albedo texture. \n\n" +
|
||||||
|
"Instructions:\n\n" +
|
||||||
|
"1. Select Texture Baker.\n\n" +
|
||||||
|
"2. Select folder where color tint textures will be saved.\n\n" +
|
||||||
|
"3. Add color tint property names or albedo map property names used by source materials.\n\n" +
|
||||||
|
"4. Set the output texture size. This must be a power of 2. The resulting texture will have height and width equal to \'size\'.\n\n" +
|
||||||
|
"5. Click \'Find Color Tint Textures\' to generate a dry-run report of affected materials and generated textures.\n\n" +
|
||||||
|
"6. Click \'Generate Color Tint Textures\' to generate solid color textures and assign them to source materials.", UnityEditor.MessageType.None);
|
||||||
|
newTextureBaker = (MB3_TextureBaker)EditorGUILayout.ObjectField(gc_textureBakerSelect, textureBaker, typeof(MB3_TextureBaker), true);
|
||||||
|
|
||||||
|
if (newTextureBaker != null &&
|
||||||
|
(newTextureBaker != textureBaker ||
|
||||||
|
ctGen == null))
|
||||||
|
{
|
||||||
|
textureBaker = newTextureBaker;
|
||||||
|
ctGen = new MB3_ColorTintTextureGenerator(textureBaker);
|
||||||
|
ctData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get folder to save textures in
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.Label(gc_folderSelectHeader, EditorStyles.boldLabel);
|
||||||
|
if (GUILayout.Button(gc_folderSelectButton))
|
||||||
|
{
|
||||||
|
errorState = false;
|
||||||
|
folderPath = MB3_ColorTintTextureGenerator.BrowseOutputFolder();
|
||||||
|
if (folderPath == null)
|
||||||
|
{
|
||||||
|
errorState = true;
|
||||||
|
errorMsg = "Selected folder could not be found. Please select a different folder.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUILayout.LabelField("Folder: " + folderPath);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
// modifiable arrays for color and albedo property names
|
||||||
|
EditorGUILayout.PropertyField(colorTintProperty, gc_colorPropertyNames, true);
|
||||||
|
EditorGUILayout.PropertyField(albedoMapProperty, gc_albedoPropertyNames, true);
|
||||||
|
|
||||||
|
// set texture size field
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
texSize = Mathf.ClosestPowerOfTwo(EditorGUILayout.IntField(gc_texSizeField, texSize));
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
if (texSize < 2)
|
||||||
|
{
|
||||||
|
texSize = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// button for enumerating materials and whether or not they will be updated
|
||||||
|
if (GUILayout.Button(gc_findButton))
|
||||||
|
{
|
||||||
|
errorState = false;
|
||||||
|
if (ctGen == null)
|
||||||
|
{
|
||||||
|
errorState = true;
|
||||||
|
errorMsg = "Texture baker is not assigned. This operation requires a texture baker reference.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
generatedFiles.Clear();
|
||||||
|
ctData = ctGen.GenerateColorTintTextures(textureBaker, ctData, folderPath, texSize, colorTintList, albedoMapList, false, out generatedFiles);
|
||||||
|
doneGeneration = false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
errorState = true;
|
||||||
|
Debug.LogError(e.Message);
|
||||||
|
errorMsg = e.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// button to generate new color tint textures and update corresponding materials
|
||||||
|
if (GUILayout.Button(gc_generateButton))
|
||||||
|
{
|
||||||
|
errorState = false;
|
||||||
|
if (ctGen == null)
|
||||||
|
{
|
||||||
|
errorState = true;
|
||||||
|
errorMsg = "Texture baker is not set. This operation requires a texture baker reference.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool response = EditorUtility.DisplayDialog("Confirm Color Texture Generation",
|
||||||
|
"Are you sure you want to generate color tint textures?\nThis will modify materials used by the Objects To Be Combined.",
|
||||||
|
"Yes", "No");
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayProgressBar("Generate Color Tint Textures...", "", 0.5f);
|
||||||
|
ctGen.GenerateColorTintTextures(textureBaker, ctData, folderPath, texSize, colorTintList, albedoMapList, true, out generatedFiles);
|
||||||
|
doneGeneration = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
errorState = true;
|
||||||
|
Debug.LogError(e.Message);
|
||||||
|
errorMsg = e.Message;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, true);
|
||||||
|
{
|
||||||
|
if (errorState)
|
||||||
|
{
|
||||||
|
// if an error occurred during find or generate display it
|
||||||
|
GUIStyle errorStyle = new GUIStyle();
|
||||||
|
errorStyle.normal.textColor = Color.red;
|
||||||
|
EditorGUILayout.LabelField("Error: " + errorMsg, errorStyle);
|
||||||
|
}
|
||||||
|
else if (doneGeneration && generatedFiles != null && generatedFiles.Count > 0)
|
||||||
|
{
|
||||||
|
// display which new files were created
|
||||||
|
EditorGUILayout.LabelField("The following textures were generated in folder", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.LabelField(folderPath, EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
for (int i = 0; i < generatedFiles.Count; i++)
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField(generatedFiles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (doneGeneration && (generatedFiles == null || generatedFiles.Count == 0))
|
||||||
|
{
|
||||||
|
// notify that no new textures were generated
|
||||||
|
EditorGUILayout.LabelField("No new texture files were generated.", EditorStyles.boldLabel);
|
||||||
|
}
|
||||||
|
else if (ctData != null && ctData.Count > 0)
|
||||||
|
{
|
||||||
|
// display data for each material detected our first pass through GenerateColorTintTextures
|
||||||
|
EditorGUILayout.LabelField("Detected Materials With Color Tints & Empty Albedo Properties:", EditorStyles.boldLabel);
|
||||||
|
for (int i = 0; i < ctData.Count; i++)
|
||||||
|
{
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
DisplayColorTintData(ctData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
colorTintWindowObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisplayColorTintData(MB3_ColorTintTextureGenerator.ColorTintTextureData ctData)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (ctData.willGenerateColorTexture)
|
||||||
|
{
|
||||||
|
// display information about color texture
|
||||||
|
sb.AppendLine("Material: " + ctData.mat + " Found color tint " + ctData.colorProperty + " Color tint texture will be generated.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// explain why color tint texture will not be generated
|
||||||
|
if (ctData.mat != null)
|
||||||
|
{
|
||||||
|
sb.AppendLine("Material " + ctData.mat + " had the following issues:");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ctData.messages.Count; i++)
|
||||||
|
{
|
||||||
|
sb.AppendLine(ctData.messages[i]);
|
||||||
|
}
|
||||||
|
sb.AppendLine("Color tint texture will not be generated for this material.");
|
||||||
|
}
|
||||||
|
EditorGUILayout.LabelField(sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: df558a29358f3c947920e07c881549c0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_CreateColorTintWindow.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(MB3_DisableHiddenAnimations))]
|
||||||
|
public class MB3_DisableHiddenAnimationsEditor : Editor
|
||||||
|
{
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(
|
||||||
|
"HOW TO USE \n\nPlace this component on the same game object that has the combined SkinMeshRenderer " +
|
||||||
|
"\n\n Drag game objects with Animator and/or Animation components that were baked into the combined SkinnedMeshRenderer into the lists below", MessageType.Info);
|
||||||
|
DrawDefaultInspector();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e1435b73816486941b0ea827c7645cf6
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_DisableHiddenAnimationsEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,567 @@
|
|||||||
|
/**
|
||||||
|
* \brief Hax! DLLs cannot interpret preprocessor directives, so this class acts as a "bridge"
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.Core
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MBVersionEditorConcrete : MBVersionEditorInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to map the activeBuildTarget to a string argument needed by TextureImporter.GetPlatformTextureSettings
|
||||||
|
/// The allowed values for GetPlatformTextureSettings are "Web", "Standalone", "iPhone", "Android" and "FlashPlayer".
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string GetPlatformString()
|
||||||
|
{
|
||||||
|
#if (UNITY_4_6 || UNITY_4_7 || UNITY_4_5 || UNITY_4_3 || UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5)
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iPhone){
|
||||||
|
return "iPhone";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS)
|
||||||
|
{
|
||||||
|
return "iPhone";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WSAPlayer)
|
||||||
|
{
|
||||||
|
return "Windows Store Apps";
|
||||||
|
}
|
||||||
|
#if (!UNITY_2018_3_OR_NEWER)
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.PSP2)
|
||||||
|
{
|
||||||
|
return "PSP2";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.PS4)
|
||||||
|
{
|
||||||
|
return "PS4";
|
||||||
|
}
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.XboxOne)
|
||||||
|
{
|
||||||
|
return "XboxOne";
|
||||||
|
}
|
||||||
|
#if (UNITY_2017_3_OR_NEWER)
|
||||||
|
#else
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.SamsungTV)
|
||||||
|
{
|
||||||
|
return "Samsung TV";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if (UNITY_5_5_OR_NEWER && !UNITY_2018_1_OR_NEWER)
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.N3DS)
|
||||||
|
{
|
||||||
|
return "Nintendo 3DS";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if (UNITY_5_3 || UNITY_5_2 || UNITY_5_3_OR_NEWER)
|
||||||
|
#if (UNITY_2018_1_OR_NEWER)
|
||||||
|
// wiiu support was removed in 2018.1
|
||||||
|
#else
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WiiU)
|
||||||
|
{
|
||||||
|
return "WiiU";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (UNITY_5_3 || UNITY_5_3_OR_NEWER)
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.tvOS)
|
||||||
|
{
|
||||||
|
return "tvOS";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if (UNITY_2018_2_OR_NEWER)
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Tizen)
|
||||||
|
{
|
||||||
|
return "Tizen";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
|
||||||
|
{
|
||||||
|
return "Android";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLinuxStandalone = false;
|
||||||
|
#if UNITY_2019_2_OR_NEWER
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneLinux64)
|
||||||
|
{
|
||||||
|
isLinuxStandalone = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneLinux ||
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneLinuxUniversal)
|
||||||
|
{
|
||||||
|
isLinuxStandalone = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (isLinuxStandalone ||
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows ||
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows64 ||
|
||||||
|
#if UNITY_2017_3_OR_NEWER
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneOSX
|
||||||
|
#else
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneOSXIntel ||
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneOSXIntel64 ||
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneOSXUniversal
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return "Standalone";
|
||||||
|
}
|
||||||
|
#if !UNITY_5_4_OR_NEWER
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebPlayer ||
|
||||||
|
EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebPlayerStreamed
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return "Web";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebGL)
|
||||||
|
{
|
||||||
|
return "WebGL";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterUndo(UnityEngine.Object o, string s)
|
||||||
|
{
|
||||||
|
#if (UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5)
|
||||||
|
Undo.RegisterUndo(o, s);
|
||||||
|
#else
|
||||||
|
Undo.RecordObject(o, s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetScriptingDefineSymbolsFromTg(BuildTargetGroup tg)
|
||||||
|
{
|
||||||
|
#if UNITY_2021_2_OR_NEWER
|
||||||
|
NamedBuildTarget namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(tg);
|
||||||
|
return PlayerSettings.GetScriptingDefineSymbols(namedBuildTarget);
|
||||||
|
#else
|
||||||
|
return PlayerSettings.GetScriptingDefineSymbolsForGroup(tg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInspectorLabelWidth(float width)
|
||||||
|
{
|
||||||
|
#if (UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5)
|
||||||
|
EditorGUIUtility.LookLikeControls(width);
|
||||||
|
#else
|
||||||
|
EditorGUIUtility.labelWidth = width;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateIfDirtyOrScript(SerializedObject so)
|
||||||
|
{
|
||||||
|
#if UNITY_5_6_OR_NEWER
|
||||||
|
so.UpdateIfRequiredOrScript();
|
||||||
|
#else
|
||||||
|
so.UpdateIfDirtyOrScript();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GenerateSecondaryUVSetForUnwrapping(Mesh src, UnwrapParam settings)
|
||||||
|
{
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
bool unwrappingSuccessful = Unwrapping.GenerateSecondaryUVSet(src, settings);
|
||||||
|
return unwrappingSuccessful;
|
||||||
|
#else
|
||||||
|
Unwrapping.GenerateSecondaryUVSet(src, settings);
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object PrefabUtility_GetCorrespondingObjectFromSource(GameObject go)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_2_OR_NEWER
|
||||||
|
return PrefabUtility.GetCorrespondingObjectFromSource(go);
|
||||||
|
#else
|
||||||
|
return PrefabUtility.GetPrefabParent(go);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAutoPVRTC(TextureImporterFormat platformFormat, TextureImporterFormat platformDefaultFormat)
|
||||||
|
{
|
||||||
|
if ((
|
||||||
|
#if UNITY_2017_1_OR_NEWER
|
||||||
|
platformFormat == TextureImporterFormat.Automatic
|
||||||
|
#elif UNITY_5_5_OR_NEWER
|
||||||
|
platformFormat == TextureImporterFormat.Automatic ||
|
||||||
|
platformFormat == TextureImporterFormat.Automatic16bit ||
|
||||||
|
platformFormat == TextureImporterFormat.AutomaticCompressed ||
|
||||||
|
platformFormat == TextureImporterFormat.AutomaticCompressedHDR ||
|
||||||
|
platformFormat == TextureImporterFormat.AutomaticCrunched ||
|
||||||
|
platformFormat == TextureImporterFormat.AutomaticHDR
|
||||||
|
#else
|
||||||
|
platformFormat == TextureImporterFormat.Automatic16bit ||
|
||||||
|
platformFormat == TextureImporterFormat.AutomaticCompressed ||
|
||||||
|
platformFormat == TextureImporterFormat.AutomaticCrunched
|
||||||
|
#endif
|
||||||
|
) && (
|
||||||
|
platformDefaultFormat == TextureImporterFormat.PVRTC_RGB2 ||
|
||||||
|
platformDefaultFormat == TextureImporterFormat.PVRTC_RGB4 ||
|
||||||
|
platformDefaultFormat == TextureImporterFormat.PVRTC_RGBA2 ||
|
||||||
|
platformDefaultFormat == TextureImporterFormat.PVRTC_RGBA4
|
||||||
|
))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MB_PrefabType PrefabUtility_GetPrefabType(UnityEngine.Object obj)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
if (PrefabUtility.IsPartOfNonAssetPrefabInstance(obj))
|
||||||
|
{
|
||||||
|
return MB_PrefabType.scenePefabInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PrefabUtility.IsPartOfAnyPrefab(obj))
|
||||||
|
{
|
||||||
|
return MB_PrefabType.isInstanceAndNotAPartOfAnyPrefab;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefabAssetType assetType = PrefabUtility.GetPrefabAssetType(obj);
|
||||||
|
if (assetType == PrefabAssetType.NotAPrefab)
|
||||||
|
{
|
||||||
|
if (PrefabUtility.GetPrefabInstanceStatus(obj) != PrefabInstanceStatus.NotAPrefab)
|
||||||
|
{
|
||||||
|
return MB_PrefabType.isInstanceAndNotAPartOfAnyPrefab;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MB_PrefabType.scenePefabInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (assetType == PrefabAssetType.Model)
|
||||||
|
{
|
||||||
|
return MB_PrefabType.modelPrefabAsset;
|
||||||
|
}
|
||||||
|
else if (assetType == PrefabAssetType.Regular ||
|
||||||
|
assetType == PrefabAssetType.Variant ||
|
||||||
|
assetType == PrefabAssetType.MissingAsset)
|
||||||
|
{
|
||||||
|
return MB_PrefabType.prefabAsset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(false, "Should never get here. Unknown prefab asset type.");
|
||||||
|
return MB_PrefabType.isInstanceAndNotAPartOfAnyPrefab;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
PrefabType prefabType = PrefabUtility.GetPrefabType(obj);
|
||||||
|
if (prefabType == PrefabType.ModelPrefab)
|
||||||
|
{
|
||||||
|
return MB_PrefabType.modelPrefabAsset;
|
||||||
|
} else if (prefabType == PrefabType.Prefab)
|
||||||
|
{
|
||||||
|
return MB_PrefabType.prefabAsset;
|
||||||
|
} else if (prefabType == PrefabType.PrefabInstance || prefabType == PrefabType.ModelPrefabInstance)
|
||||||
|
{
|
||||||
|
return MB_PrefabType.scenePefabInstance;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return MB_PrefabType.isInstanceAndNotAPartOfAnyPrefab;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrefabUtility_UnpackPrefabInstance(UnityEngine.GameObject go, ref SerializedObject so)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
UnityEngine.Object targetObj = null;
|
||||||
|
if (so != null) targetObj = so.targetObject;
|
||||||
|
PrefabUtility.UnpackPrefabInstance(go, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
|
||||||
|
|
||||||
|
// This is a workaround for a nasty Unity bug. The call to UnpackPrefabInstance
|
||||||
|
// corrupts the serialized object, Recreate a clean reference here.
|
||||||
|
if (so != null) so = new SerializedObject(targetObj);
|
||||||
|
#else
|
||||||
|
// Do nothing.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrefabUtility_ReplacePrefab(GameObject gameObject, string assetPath, MB_ReplacePrefabOption replacePrefabOptions)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
PrefabUtility.SaveAsPrefabAssetAndConnect(gameObject, assetPath, InteractionMode.AutomatedAction);
|
||||||
|
#else
|
||||||
|
GameObject obj = (GameObject) AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject));
|
||||||
|
PrefabUtility.ReplacePrefab(gameObject, obj, (ReplacePrefabOptions) replacePrefabOptions);
|
||||||
|
obj = (GameObject)AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject));
|
||||||
|
if (replacePrefabOptions == MB_ReplacePrefabOption.nameBased)
|
||||||
|
{
|
||||||
|
PrefabUtility.ConnectGameObjectToPrefab(gameObject, obj);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObject PrefabUtility_GetPrefabInstanceRoot(GameObject sceneInstance)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
return PrefabUtility.GetOutermostPrefabInstanceRoot(sceneInstance);
|
||||||
|
#else
|
||||||
|
return PrefabUtility.FindRootGameObjectWithSameParentPrefab(sceneInstance);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureImporterFormat Map_TextureFormat_2_TextureImporterFormat(TextureFormat texFormat, out bool success)
|
||||||
|
{
|
||||||
|
TextureImporterFormat texImporterFormat;
|
||||||
|
success = true;
|
||||||
|
switch (texFormat)
|
||||||
|
{
|
||||||
|
case TextureFormat.ARGB32:
|
||||||
|
texImporterFormat = TextureImporterFormat.ARGB32;
|
||||||
|
break;
|
||||||
|
case TextureFormat.RGBA32:
|
||||||
|
texImporterFormat = TextureImporterFormat.RGBA32;
|
||||||
|
break;
|
||||||
|
case TextureFormat.RGB24:
|
||||||
|
texImporterFormat = TextureImporterFormat.RGB24;
|
||||||
|
break;
|
||||||
|
case TextureFormat.Alpha8:
|
||||||
|
texImporterFormat = TextureImporterFormat.Alpha8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
case TextureFormat.ASTC_10x10:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_10x10;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_12x12:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_12x12;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_4x4:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_4x4;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_5x5:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_5x5;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_6x6:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_6x6;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_8x8:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_8x8;
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case TextureFormat.ASTC_RGBA_10x10:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGBA_10x10;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGBA_12x12:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGBA_12x12;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGBA_4x4:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGBA_4x4;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGBA_5x5:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGBA_5x5;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGBA_6x6:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGBA_6x6;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGBA_8x8:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGBA_8x8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TextureFormat.ASTC_RGB_10x10:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGB_10x10;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGB_12x12:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGB_12x12;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGB_4x4:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGB_4x4;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGB_5x5:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGB_5x5;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGB_6x6:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGB_6x6;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ASTC_RGB_8x8:
|
||||||
|
texImporterFormat = TextureImporterFormat.ASTC_RGB_8x8;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case TextureFormat.BC4:
|
||||||
|
texImporterFormat = TextureImporterFormat.BC4;
|
||||||
|
break;
|
||||||
|
case TextureFormat.BC5:
|
||||||
|
texImporterFormat = TextureImporterFormat.BC5;
|
||||||
|
break;
|
||||||
|
case TextureFormat.BC6H:
|
||||||
|
texImporterFormat = TextureImporterFormat.BC6H;
|
||||||
|
break;
|
||||||
|
case TextureFormat.BC7:
|
||||||
|
texImporterFormat = TextureImporterFormat.BC7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TextureFormat.DXT1:
|
||||||
|
texImporterFormat = TextureImporterFormat.DXT1;
|
||||||
|
break;
|
||||||
|
case TextureFormat.DXT1Crunched:
|
||||||
|
texImporterFormat = TextureImporterFormat.DXT1Crunched;
|
||||||
|
break;
|
||||||
|
case TextureFormat.DXT5:
|
||||||
|
texImporterFormat = TextureImporterFormat.DXT5;
|
||||||
|
break;
|
||||||
|
case TextureFormat.DXT5Crunched:
|
||||||
|
texImporterFormat = TextureImporterFormat.DXT5Crunched;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TextureFormat.EAC_R:
|
||||||
|
texImporterFormat = TextureImporterFormat.EAC_R;
|
||||||
|
break;
|
||||||
|
case TextureFormat.EAC_RG:
|
||||||
|
texImporterFormat = TextureImporterFormat.EAC_RG;
|
||||||
|
break;
|
||||||
|
case TextureFormat.EAC_RG_SIGNED:
|
||||||
|
texImporterFormat = TextureImporterFormat.EAC_RG_SIGNED;
|
||||||
|
break;
|
||||||
|
case TextureFormat.EAC_R_SIGNED:
|
||||||
|
texImporterFormat = TextureImporterFormat.EAC_R_SIGNED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TextureFormat.ETC_RGB4:
|
||||||
|
texImporterFormat = TextureImporterFormat.ETC_RGB4;
|
||||||
|
break;
|
||||||
|
#if UNITY_2017_3_OR_NEWER
|
||||||
|
case TextureFormat.ETC_RGB4Crunched:
|
||||||
|
texImporterFormat = TextureImporterFormat.ETC_RGB4Crunched;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case TextureFormat.ETC2_RGB:
|
||||||
|
texImporterFormat = TextureImporterFormat.ETC2_RGB4;
|
||||||
|
break;
|
||||||
|
case TextureFormat.ETC2_RGBA8:
|
||||||
|
texImporterFormat = TextureImporterFormat.ETC2_RGBA8;
|
||||||
|
break;
|
||||||
|
#if UNITY_2017_3_OR_NEWER
|
||||||
|
case TextureFormat.ETC2_RGBA8Crunched:
|
||||||
|
texImporterFormat = TextureImporterFormat.ETC2_RGBA8Crunched;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case TextureFormat.PVRTC_RGB2:
|
||||||
|
texImporterFormat = TextureImporterFormat.PVRTC_RGB2;
|
||||||
|
break;
|
||||||
|
case TextureFormat.PVRTC_RGB4:
|
||||||
|
texImporterFormat = TextureImporterFormat.PVRTC_RGB4;
|
||||||
|
break;
|
||||||
|
case TextureFormat.PVRTC_RGBA2:
|
||||||
|
texImporterFormat = TextureImporterFormat.PVRTC_RGBA2;
|
||||||
|
break;
|
||||||
|
case TextureFormat.PVRTC_RGBA4:
|
||||||
|
texImporterFormat = TextureImporterFormat.PVRTC_RGBA4;
|
||||||
|
break;
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.R16:
|
||||||
|
texImporterFormat = TextureImporterFormat.R16;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_2_OR_NEWER
|
||||||
|
case TextureFormat.R8:
|
||||||
|
texImporterFormat = TextureImporterFormat.R8;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.RFloat:
|
||||||
|
texImporterFormat = TextureImporterFormat.RFloat;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.RG16:
|
||||||
|
texImporterFormat = TextureImporterFormat.RG16;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.RGB9e5Float:
|
||||||
|
texImporterFormat = TextureImporterFormat.RGB9E5;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.RGHalf:
|
||||||
|
texImporterFormat = TextureImporterFormat.RGHalf;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.RGFloat:
|
||||||
|
texImporterFormat = TextureImporterFormat.RGFloat;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
case TextureFormat.RHalf:
|
||||||
|
texImporterFormat = TextureImporterFormat.RHalf;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
texImporterFormat = TextureImporterFormat.ARGB32;
|
||||||
|
success = false;
|
||||||
|
Debug.LogError("No mapping for TextureFormat: " + texFormat + " to a TextureImporterFormat. ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return texImporterFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrefabUtility_SavePrefabAsset(GameObject prefabAsset)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
PrefabUtility.SavePrefabAsset(prefabAsset);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrefabUtility_ApplyPrefabInstance(GameObject instance)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
PrefabUtility.ApplyPrefabInstance(instance, InteractionMode.AutomatedAction);
|
||||||
|
#else
|
||||||
|
PropertyModification[] mods = PrefabUtility.GetPropertyModifications(instance);
|
||||||
|
PrefabUtility.SetPropertyModifications(instance, mods);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObject PrefabUtility_CreatePrefab(string path, GameObject go)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
return PrefabUtility.SaveAsPrefabAsset(go, path);
|
||||||
|
#else
|
||||||
|
return PrefabUtility.CreatePrefab(path, go);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObject PrefabUtility_FindPrefabRoot(GameObject sourceObj)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
if (sourceObj == null) return null;
|
||||||
|
if (MB_Utility.IsSceneInstance(sourceObj))
|
||||||
|
{
|
||||||
|
return PrefabUtility.GetOutermostPrefabInstanceRoot(sourceObj);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return sourceObj.transform.root.gameObject;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return PrefabUtility.FindPrefabRoot(sourceObj);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObject GetCorrespondingObjectFromSource(GameObject sourceObj)
|
||||||
|
{
|
||||||
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
return PrefabUtility.GetCorrespondingObjectFromSource(sourceObj);
|
||||||
|
#else
|
||||||
|
return (GameObject) PrefabUtility.GetPrefabParent(sourceObj);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 86e7cea5d902c1647b14db77b02f967e
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MBVersionConcreteEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(MB3_MeshBaker))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class MB3_MeshBakerEditor : Editor
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorInternal mbe = new MB3_MeshBakerEditorInternal();
|
||||||
|
|
||||||
|
[MenuItem("GameObject/Create Other/Mesh Baker/TextureBaker and MeshBaker", false, 100)]
|
||||||
|
public static GameObject CreateNewMeshBaker()
|
||||||
|
{
|
||||||
|
MB3_TextureBaker[] mbs = (MB3_TextureBaker[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_TextureBaker));
|
||||||
|
Regex regex = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
int largest = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mbs.Length; i++)
|
||||||
|
{
|
||||||
|
Match match = regex.Match(mbs[i].name);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
int val = Convert.ToInt32(match.Groups[1].Value);
|
||||||
|
if (val >= largest)
|
||||||
|
largest = val + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e == null) e = null; //Do nothing supress compiler warning
|
||||||
|
}
|
||||||
|
GameObject nmb = new GameObject("TextureBaker (" + largest + ")");
|
||||||
|
nmb.transform.position = Vector3.zero;
|
||||||
|
MB3_TextureBaker tb = nmb.AddComponent<MB3_TextureBaker>();
|
||||||
|
tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
|
||||||
|
MB3_MeshBakerGrouper mbg = nmb.AddComponent<MB3_MeshBakerGrouper>();
|
||||||
|
GameObject meshBaker = new GameObject("MeshBaker");
|
||||||
|
MB3_MeshBaker mb = meshBaker.AddComponent<MB3_MeshBaker>();
|
||||||
|
meshBaker.transform.parent = nmb.transform;
|
||||||
|
mb.meshCombiner.settingsHolder = mbg;
|
||||||
|
return nmb.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("GameObject/Create Other/Mesh Baker/MeshBaker", false, 100)]
|
||||||
|
public static GameObject CreateNewMeshBakerOnly()
|
||||||
|
{
|
||||||
|
MB3_MeshBaker[] mbs = (MB3_MeshBaker[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_MeshBaker));
|
||||||
|
Regex regex = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
int largest = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mbs.Length; i++)
|
||||||
|
{
|
||||||
|
Match match = regex.Match(mbs[i].name);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
int val = Convert.ToInt32(match.Groups[1].Value);
|
||||||
|
if (val >= largest)
|
||||||
|
largest = val + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e == null) e = null; //Do nothing supress compiler warning
|
||||||
|
}
|
||||||
|
GameObject meshBaker = new GameObject("MeshBaker (" + largest + ")");
|
||||||
|
meshBaker.AddComponent<MB3_MeshBaker>();
|
||||||
|
return meshBaker.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
mbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable()
|
||||||
|
{
|
||||||
|
mbe.OnDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
mbe.OnInspectorGUI(serializedObject, (MB3_MeshBakerCommon)target, targets, typeof(MB3_MeshBakerEditorWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d0de7b6551ddaeb4091cb0d096f8963b
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,370 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.MBEditor;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public static class MB3_MeshBakerEditorFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Used by UnityEditorInspectors for background colors
|
||||||
|
/// </summary>
|
||||||
|
public static Texture2D MakeTex(int width, int height, Color col)
|
||||||
|
{
|
||||||
|
Color[] pix = new Color[width * height];
|
||||||
|
|
||||||
|
for (int i = 0; i < pix.Length; i++)
|
||||||
|
pix[i] = col;
|
||||||
|
|
||||||
|
Texture2D result = new Texture2D(width, height);
|
||||||
|
result.SetPixels(pix);
|
||||||
|
result.Apply();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool BakeIntoCombined(MB3_MeshBakerCommon mom, out bool createdDummyTextureBakeResults)
|
||||||
|
{
|
||||||
|
SerializedObject so = null;
|
||||||
|
return BakeIntoCombined(mom, out createdDummyTextureBakeResults, ref so);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bakes a combined mesh.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="so">If this is being called from Inspector code then pass in the SerializedObject for the component.
|
||||||
|
/// This is necessary for "bake into prefab" which can corrupt the SerializedObject.</param>
|
||||||
|
public static bool BakeIntoCombined(MB3_MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so)
|
||||||
|
{
|
||||||
|
MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;
|
||||||
|
createdDummyTextureBakeResults = false;
|
||||||
|
|
||||||
|
// Initial Validate
|
||||||
|
{
|
||||||
|
if (mom.meshCombiner.resultSceneObject != null &&
|
||||||
|
(MBVersionEditor.PrefabUtility_GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.modelPrefabAsset ||
|
||||||
|
MBVersionEditor.PrefabUtility_GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.prefabAsset))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field.");
|
||||||
|
mom.meshCombiner.resultSceneObject = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefabOrSceneObject != MB2_OutputOptions.bakeIntoPrefab && prefabOrSceneObject != MB2_OutputOptions.bakeIntoSceneObject)
|
||||||
|
{
|
||||||
|
Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
|
||||||
|
{
|
||||||
|
if (MB3_MeshCombiner.EVAL_VERSION)
|
||||||
|
{
|
||||||
|
Debug.LogError("Cannot BakeIntoPrefab with evaluation version.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mom.resultPrefab == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Need to set the Combined Mesh Prefab field. Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
|
||||||
|
if (prefabPth == null || prefabPth.Length == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("Could not save result to prefab. Result Prefab value is not a project asset. Is it an instance in the scene?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Find or create texture bake results
|
||||||
|
MB3_TextureBaker tb = mom.GetComponentInParent<MB3_TextureBaker>();
|
||||||
|
if (mom.textureBakeResults == null && tb != null)
|
||||||
|
{
|
||||||
|
mom.textureBakeResults = tb.textureBakeResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mom.textureBakeResults == null)
|
||||||
|
{
|
||||||
|
if (_OkToCreateDummyTextureBakeResult(mom))
|
||||||
|
{
|
||||||
|
createdDummyTextureBakeResults = true;
|
||||||
|
List<GameObject> gos = mom.GetObjectsToCombine();
|
||||||
|
if (mom.GetNumObjectsInCombined() > 0)
|
||||||
|
{
|
||||||
|
if (mom.meshCombiner.clearBuffersAfterBake) { mom.ClearMesh(); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("'Texture Bake Result' must be set to add more objects to a combined mesh that already contains objects. Try enabling 'clear buffers after bake'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mom.textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(gos.ToArray(), mom.meshCombiner.GetMaterialsOnTargetRenderer());
|
||||||
|
if (mom.meshCombiner.LOG_LEVEL >= MB2_LogLevel.debug) { Debug.Log("'Texture Bake Result' was not set. Creating a temporary one. Each material will be mapped to a separate submesh."); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second level of validation now that TextureBakeResults exists.
|
||||||
|
MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;
|
||||||
|
if (!MB3_MeshBakerRoot.DoCombinedValidate(mom, MB_ObjsToCombineTypes.sceneObjOnly, new MB3_EditorMethods(), vl))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Delete Game Objects
|
||||||
|
bool success;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoSceneObject)
|
||||||
|
{
|
||||||
|
success = _BakeIntoCombinedSceneObject(mom, createdDummyTextureBakeResults, ref so);
|
||||||
|
}
|
||||||
|
else if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
|
||||||
|
{
|
||||||
|
success = _BakeIntoCombinedPrefab(mom, createdDummyTextureBakeResults, ref so);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Should be impossible.");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mom.meshCombiner.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdDummyTextureBakeResults) MB_Utility.Destroy(mom.textureBakeResults);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool _BakeIntoCombinedSceneObject(MB3_MeshBakerCommon mom, bool createdDummyTextureBakeResults, ref SerializedObject so)
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
mom.ClearMesh();
|
||||||
|
if (mom.AddDeleteGameObjects(mom.GetObjectsToCombine().ToArray(), null, false) &&
|
||||||
|
mom.Apply(MB3_MeshBakerEditorFunctionsCore.UnwrapUV2))
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
if (createdDummyTextureBakeResults)
|
||||||
|
{
|
||||||
|
Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.", mom.GetObjectsToCombine().Count));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool _BakeIntoCombinedPrefab(MB3_MeshBakerCommon mom, bool createdDummyTextureBakeResults, ref SerializedObject so)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
List<Transform> tempPrefabInstanceRoots = null;
|
||||||
|
GameObject[] objsToCombine = mom.GetObjectsToCombine().ToArray();
|
||||||
|
if (mom.meshCombiner.settings.renderType == MB_RenderType.skinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
tempPrefabInstanceRoots = new List<Transform>();
|
||||||
|
// We are going to move bones of source objs and transforms into our combined mesh prefab so make some duplicates
|
||||||
|
// so that we don't destroy a setup.
|
||||||
|
MB3_MeshBakerEditorFunctionsCore._DuplicateSrcObjectInstancesAndUnpack(mom.meshCombiner.settings.renderType, objsToCombine, tempPrefabInstanceRoots);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MB3_EditorMethods editorMethods = new MB3_EditorMethods();
|
||||||
|
mom.ClearMesh(editorMethods);
|
||||||
|
if (mom.AddDeleteGameObjects(objsToCombine, null, false))
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
mom.Apply(MB3_MeshBakerEditorFunctionsCore.UnwrapUV2);
|
||||||
|
|
||||||
|
|
||||||
|
if (createdDummyTextureBakeResults)
|
||||||
|
{
|
||||||
|
Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.", mom.GetObjectsToCombine().Count));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
|
||||||
|
}
|
||||||
|
|
||||||
|
string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
|
||||||
|
if (prefabPth == null || prefabPth.Length == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("Could not save result to prefab. Result Prefab value is not an Asset.");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(prefabPth);
|
||||||
|
string folderPath = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7);
|
||||||
|
string newFilename = folderPath + baseName + "-mesh";
|
||||||
|
SaveMeshsToAssetDatabase(mom, folderPath, newFilename);
|
||||||
|
RebuildPrefab(mom, ref so, mom.resultPrefabLeaveInstanceInSceneAfterBake, tempPrefabInstanceRoots, objsToCombine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Clean up temporary created instances. If success was true then they should have been added to a prefab
|
||||||
|
// and cleaned up for us.
|
||||||
|
if (success == false)
|
||||||
|
{
|
||||||
|
if (tempPrefabInstanceRoots != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < tempPrefabInstanceRoots.Count; i++)
|
||||||
|
{
|
||||||
|
MB_Utility.Destroy(tempPrefabInstanceRoots[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool _OkToCreateDummyTextureBakeResult(MB3_MeshBakerCommon mom)
|
||||||
|
{
|
||||||
|
List<GameObject> objsToMesh = mom.GetObjectsToCombine();
|
||||||
|
if (objsToMesh.Count == 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SaveMeshsToAssetDatabase(MB3_MeshBakerCommon mom, string folderPath, string newFileNameBase)
|
||||||
|
{
|
||||||
|
if (MB3_MeshCombiner.EVAL_VERSION) return;
|
||||||
|
if (mom is MB3_MeshBaker)
|
||||||
|
{
|
||||||
|
MB3_MeshBaker mb = (MB3_MeshBaker)mom;
|
||||||
|
string newFilename = newFileNameBase + ".asset";
|
||||||
|
string ap = AssetDatabase.GetAssetPath(((MB3_MeshCombinerSingle)mb.meshCombiner).GetMesh());
|
||||||
|
if (ap == null || ap.Equals(""))
|
||||||
|
{
|
||||||
|
Debug.Log("Saving mesh asset to " + newFilename);
|
||||||
|
AssetDatabase.CreateAsset(((MB3_MeshCombinerSingle)mb.meshCombiner).GetMesh(), newFilename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Mesh is an existing asset at " + ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mom is MB3_MultiMeshBaker)
|
||||||
|
{
|
||||||
|
MB3_MultiMeshBaker mmb = (MB3_MultiMeshBaker)mom;
|
||||||
|
List<MB3_MultiMeshCombiner.CombinedMesh> combiners = ((MB3_MultiMeshCombiner)mmb.meshCombiner).meshCombiners;
|
||||||
|
for (int i = 0; i < combiners.Count; i++)
|
||||||
|
{
|
||||||
|
string newFilename = newFileNameBase + i + ".asset";
|
||||||
|
Mesh mesh = combiners[i].combinedMesh.GetMesh();
|
||||||
|
string ap = AssetDatabase.GetAssetPath(mesh);
|
||||||
|
if (ap == null || ap.Equals(""))
|
||||||
|
{
|
||||||
|
Debug.Log("Saving mesh asset to " + newFilename);
|
||||||
|
AssetDatabase.CreateAsset(mesh, newFilename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Mesh is an asset at " + ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Argument was not a MB3_MeshBaker or an MB3_MultiMeshBaker.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The serialized object reference is necessary to work around a nasty unity bug.
|
||||||
|
public static GameObject RebuildPrefab(MB3_MeshBakerCommon mom, ref SerializedObject so, bool leaveInstanceInSceneAfterBake, List<Transform> tempPrefabInstanceRoots, GameObject[] objsToCombine)
|
||||||
|
{
|
||||||
|
if (MB3_MeshCombiner.EVAL_VERSION) return null;
|
||||||
|
|
||||||
|
if (mom.meshCombiner.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Rebuilding Prefab: " + mom.resultPrefab);
|
||||||
|
GameObject prefabRoot = mom.resultPrefab;
|
||||||
|
GameObject instanceRootGO = mom.meshCombiner.resultSceneObject;
|
||||||
|
/*
|
||||||
|
GameObject instanceRootGO = (GameObject)PrefabUtility.InstantiatePrefab(prefabRoot);
|
||||||
|
instanceRootGO.transform.position = Vector3.zero;
|
||||||
|
instanceRootGO.transform.rotation = Quaternion.identity;
|
||||||
|
instanceRootGO.transform.localScale = Vector3.one;
|
||||||
|
|
||||||
|
//remove everything in the prefab.
|
||||||
|
|
||||||
|
MBVersionEditor.UnpackPrefabInstance(instanceRootGO, ref so);
|
||||||
|
int numChildren = instanceRootGO.transform.childCount;
|
||||||
|
for (int i = numChildren - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
MB_Utility.Destroy(instanceRootGO.transform.GetChild(i).gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mom is MB3_MeshBaker)
|
||||||
|
{
|
||||||
|
MB3_MeshBaker mb = (MB3_MeshBaker)mom;
|
||||||
|
MB3_MeshCombinerSingle mbs = (MB3_MeshCombinerSingle)mb.meshCombiner;
|
||||||
|
MB3_MeshCombinerSingle.BuildPrefabHierarchy(mbs, instanceRootGO, mbs.GetMesh());
|
||||||
|
}
|
||||||
|
else if (mom is MB3_MultiMeshBaker)
|
||||||
|
{
|
||||||
|
MB3_MultiMeshBaker mmb = (MB3_MultiMeshBaker)mom;
|
||||||
|
MB3_MultiMeshCombiner mbs = (MB3_MultiMeshCombiner)mmb.meshCombiner;
|
||||||
|
for (int i = 0; i < mbs.meshCombiners.Count; i++)
|
||||||
|
{
|
||||||
|
MB3_MeshCombinerSingle.BuildPrefabHierarchy(mbs.meshCombiners[i].combinedMesh, instanceRootGO, mbs.meshCombiners[i].combinedMesh.GetMesh(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Argument was not a MB3_MeshBaker or an MB3_MultiMeshBaker.");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (mom.meshCombiner.settings.renderType == MB_RenderType.skinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorFunctionsCore._MoveBonesToCombinedMeshPrefabAndDeleteRenderers(instanceRootGO.transform, tempPrefabInstanceRoots, objsToCombine);
|
||||||
|
}
|
||||||
|
|
||||||
|
string prefabPth = AssetDatabase.GetAssetPath(prefabRoot);
|
||||||
|
MBVersionEditor.PrefabUtility_ReplacePrefab(instanceRootGO, prefabPth, MB_ReplacePrefabOption.connectToPrefab);
|
||||||
|
mom.resultPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPth);
|
||||||
|
if (!leaveInstanceInSceneAfterBake)
|
||||||
|
{
|
||||||
|
Editor.DestroyImmediate(instanceRootGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instanceRootGO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d79478bd8098cb741ba334439ac504b5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerEditorFunctions.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,712 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public interface MB3_MeshBakerEditorWindowInterface
|
||||||
|
{
|
||||||
|
MonoBehaviour target
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MB_EditorStyles
|
||||||
|
{
|
||||||
|
|
||||||
|
public GUIStyle multipleMaterialBackgroundStyle = new GUIStyle();
|
||||||
|
public GUIStyle multipleMaterialBackgroundStyleDarker = new GUIStyle();
|
||||||
|
public GUIStyle editorBoxBackgroundStyle = new GUIStyle();
|
||||||
|
|
||||||
|
Texture2D multipleMaterialBackgroundColor;
|
||||||
|
Texture2D multipleMaterialBackgroundColorDarker;
|
||||||
|
Texture2D editorBoxBackgroundColor;
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
bool isPro = EditorGUIUtility.isProSkin;
|
||||||
|
Color backgroundColor = isPro
|
||||||
|
? new Color32(35, 35, 35, 255)
|
||||||
|
: new Color32(174, 174, 174, 255);
|
||||||
|
if (multipleMaterialBackgroundColor == null)
|
||||||
|
{
|
||||||
|
multipleMaterialBackgroundColor = MB3_MeshBakerEditorFunctions.MakeTex(8, 8, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
backgroundColor = isPro
|
||||||
|
? new Color32(50, 50, 50, 255)
|
||||||
|
: new Color32(160, 160, 160, 255);
|
||||||
|
if (multipleMaterialBackgroundColorDarker == null)
|
||||||
|
{
|
||||||
|
multipleMaterialBackgroundColorDarker = MB3_MeshBakerEditorFunctions.MakeTex(8, 8, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
backgroundColor = isPro
|
||||||
|
? new Color32(35, 35, 35, 255)
|
||||||
|
: new Color32(174, 174, 174, 255);
|
||||||
|
|
||||||
|
multipleMaterialBackgroundStyle.normal.background = multipleMaterialBackgroundColor;
|
||||||
|
multipleMaterialBackgroundStyleDarker.normal.background = multipleMaterialBackgroundColorDarker;
|
||||||
|
|
||||||
|
if (editorBoxBackgroundColor == null)
|
||||||
|
{
|
||||||
|
editorBoxBackgroundColor = MB3_MeshBakerEditorFunctions.MakeTex(8, 8, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
editorBoxBackgroundStyle.normal.background = editorBoxBackgroundColor;
|
||||||
|
editorBoxBackgroundStyle.border = new RectOffset(0, 0, 0, 0);
|
||||||
|
editorBoxBackgroundStyle.margin = new RectOffset(5, 5, 5, 5);
|
||||||
|
editorBoxBackgroundStyle.padding = new RectOffset(10, 10, 10, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DestroyTextures()
|
||||||
|
{
|
||||||
|
if (multipleMaterialBackgroundColor != null) GameObject.DestroyImmediate(multipleMaterialBackgroundColor);
|
||||||
|
if (multipleMaterialBackgroundColorDarker != null) GameObject.DestroyImmediate(multipleMaterialBackgroundColorDarker);
|
||||||
|
if (editorBoxBackgroundColor != null) GameObject.DestroyImmediate(editorBoxBackgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MB3_MeshBakerEditorInternal
|
||||||
|
{
|
||||||
|
//add option to exclude skinned mesh renderer and mesh renderer in filter
|
||||||
|
//example scenes for multi material
|
||||||
|
private static GUIContent
|
||||||
|
gc_outputOptoinsGUIContent = new GUIContent("Output"),
|
||||||
|
gc_logLevelContent = new GUIContent("Log Level"),
|
||||||
|
gc_openToolsWindowLabelContent = new GUIContent("Open Tools For Adding Objects", "Use these tools to find out what can be combined, discover problems with meshes, and quickly add objects."),
|
||||||
|
gc_parentSceneObject = new GUIContent("Parent Scene Object (Optional)", "Must be a scene object. If set, then combined meshes will be added as children of this GameObject in the hierarchy."),
|
||||||
|
gc_resultPrefabLeaveInstanceInSceneAfterBake = new GUIContent("Leave Instance In Scene After Bake", "If checked, then an instance will be left in the scene after baking. Otherwise scene instance will be deleted after prefab is baked."),
|
||||||
|
gc_objectsToCombineGUIContent = new GUIContent("Custom List Of Objects To Be Combined", "You can add objects here that were not on the list in the MB3_TextureBaker as long as they use a material that is in the Texture Bake Results"),
|
||||||
|
gc_textureBakeResultsGUIContent = new GUIContent("Texture Bake Result", "When materials are combined a MB2_TextureBakeResult Asset is generated. Drag that Asset to this field to use the combined material."),
|
||||||
|
gc_useTextureBakerObjsGUIContent = new GUIContent("Same As Texture Baker", "Build a combined mesh using the same list of objects that generated the Combined Material"),
|
||||||
|
gc_combinedMeshPrefabGUIContent = new GUIContent("Combined Mesh Prefab", "Create a new prefab asset and drag an empty game object to it. Drag the prefab asset here."),
|
||||||
|
gc_SortAlongAxis = new GUIContent("SortAlongAxis", "Transparent materials often require that triangles be rendered in a certain order. This will sort Game Objects along the specified axis. Triangles will be added to the combined mesh in this order."),
|
||||||
|
gc_combinedMesh = new GUIContent("Mesh", "This is the Mesh used by this MeshBaker and assigned to the combined Renderer.\n\n" +
|
||||||
|
"If it is null, then a new Mesh will be created for the next bake.\n\n" +
|
||||||
|
"If it is a project folder asset, then that asset will be overwitten (changes may be reverted if the scene is not saved).\n\n" +
|
||||||
|
"If you are re-using the same MeshBaker to bake different combined meshes, set this to null before each new bake. If you don't, then each bake will overwrite the previous bake's mesh."),
|
||||||
|
gc_saveMeshAsAsset = new GUIContent("Save Mesh", "Saves the mesh as an asset in the Project folder. " +
|
||||||
|
"If this button is enabled, then the mesh only exists in this scene. " +
|
||||||
|
"It cannot be used in other scenes. "),
|
||||||
|
gc_Settings = new GUIContent("Use Shared Settings", "Different MeshBakers can share the same settings. If this field is None, then the settings below will be used. " +
|
||||||
|
"Assign one of the following:\n" +
|
||||||
|
" - Mesh Baker Settings project asset \n" +
|
||||||
|
" - Mesh Baker Grouper scene instance \n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private SerializedObject meshBaker;
|
||||||
|
private SerializedProperty logLevel, combiner, outputOptions, textureBakeResults, useObjsToMeshFromTexBaker, objsToMesh, mesh, sortOrderAxis, parentSceneObject, resultPrefabLeaveInstanceInSceneAfterBake;
|
||||||
|
|
||||||
|
private SerializedProperty settingsHolder;
|
||||||
|
|
||||||
|
private MB_MeshBakerSettingsEditor meshBakerSettingsThis;
|
||||||
|
private MB_MeshBakerSettingsEditor meshBakerSettingsExternal;
|
||||||
|
|
||||||
|
bool showInstructions = false;
|
||||||
|
bool showContainsReport = true;
|
||||||
|
|
||||||
|
private int objsToBeCombined_CurrentPage = 1;
|
||||||
|
private int objsToBecombined_NumPerPage = 50;
|
||||||
|
|
||||||
|
MB_EditorStyles editorStyles = new MB_EditorStyles();
|
||||||
|
|
||||||
|
Color buttonColor = new Color(.8f, .8f, 1f, 1f);
|
||||||
|
void _init(SerializedObject mb)
|
||||||
|
{
|
||||||
|
this.meshBaker = mb;
|
||||||
|
objsToMesh = meshBaker.FindProperty("objsToMesh");
|
||||||
|
combiner = meshBaker.FindProperty("_meshCombiner");
|
||||||
|
parentSceneObject = meshBaker.FindProperty("parentSceneObject");
|
||||||
|
resultPrefabLeaveInstanceInSceneAfterBake = meshBaker.FindProperty("resultPrefabLeaveInstanceInSceneAfterBake");
|
||||||
|
logLevel = combiner.FindPropertyRelative("_LOG_LEVEL");
|
||||||
|
outputOptions = combiner.FindPropertyRelative("_outputOption");
|
||||||
|
useObjsToMeshFromTexBaker = meshBaker.FindProperty("useObjsToMeshFromTexBaker");
|
||||||
|
textureBakeResults = combiner.FindPropertyRelative("_textureBakeResults");
|
||||||
|
mesh = combiner.FindPropertyRelative("_mesh");
|
||||||
|
sortOrderAxis = meshBaker.FindProperty("sortAxis");
|
||||||
|
settingsHolder = combiner.FindPropertyRelative("_settingsHolder");
|
||||||
|
|
||||||
|
meshBakerSettingsThis = new MB_MeshBakerSettingsEditor();
|
||||||
|
meshBakerSettingsThis.OnEnable(combiner);
|
||||||
|
editorStyles.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnEnable(SerializedObject meshBaker)
|
||||||
|
{
|
||||||
|
_init(meshBaker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
editorStyles.DestroyTextures();
|
||||||
|
if (meshBakerSettingsThis != null) meshBakerSettingsThis.OnDisable();
|
||||||
|
if (meshBakerSettingsExternal != null) meshBakerSettingsExternal.OnDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnInspectorGUI(SerializedObject meshBaker, MB3_MeshBakerCommon target, UnityEngine.Object[] targets, System.Type editorWindowType)
|
||||||
|
{
|
||||||
|
target.UpgradeToCurrentVersionIfNecessary();
|
||||||
|
DrawGUI(meshBaker, target, targets, editorWindowType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawGUI(SerializedObject meshBaker, MB3_MeshBakerCommon target, UnityEngine.Object[] targets, System.Type editorWindowType)
|
||||||
|
{
|
||||||
|
if (meshBaker == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshBaker.Update();
|
||||||
|
|
||||||
|
showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
|
||||||
|
if (showInstructions)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" +
|
||||||
|
"2. If necessary set the 'Texture Bake Results' field.\n\n" +
|
||||||
|
"3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" +
|
||||||
|
"4. Select options and 'Bake'.\n\n" +
|
||||||
|
"5. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
|
||||||
|
"6. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None);
|
||||||
|
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_MeshBakerCommon momm = (MB3_MeshBakerCommon)target;
|
||||||
|
EditorGUILayout.PropertyField(logLevel, gc_logLevelContent);
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(textureBakeResults, gc_textureBakeResultsGUIContent);
|
||||||
|
bool doingTextureArray = false;
|
||||||
|
if (textureBakeResults.objectReferenceValue != null)
|
||||||
|
{
|
||||||
|
doingTextureArray = ((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).resultType == MB2_TextureBakeResults.ResultType.textureArray;
|
||||||
|
showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
|
||||||
|
if (showContainsReport)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
|
||||||
|
EditorGUILayout.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
|
||||||
|
if (momm.GetTextureBaker() != null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
useObjsToMeshFromTexBaker.boolValue = false;
|
||||||
|
momm.useObjsToMeshFromTexBaker = false;
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!momm.useObjsToMeshFromTexBaker)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button(gc_openToolsWindowLabelContent))
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorWindow mmWin = (MB3_MeshBakerEditorWindow) EditorWindow.GetWindow(editorWindowType);
|
||||||
|
mmWin.SetTarget((MB3_MeshBakerRoot)momm);
|
||||||
|
}
|
||||||
|
|
||||||
|
object[] objs = MB3_EditorMethods.DropZone("Drag & Drop Renderers or Parents\n" + "HERE\n" +
|
||||||
|
"to add objects to be combined", 300, 50);
|
||||||
|
MB3_EditorMethods.AddDroppedObjects(objs, momm.GetObjectsToCombine());
|
||||||
|
MB_PaginatedList.GenerateObjectsToBeCombinedList(objsToMesh, ref objsToBeCombined_CurrentPage, ref objsToBecombined_NumPerPage);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Select Objects In Scene"))
|
||||||
|
{
|
||||||
|
List<MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
List<GameObject> obsToCombine = new List<GameObject>();
|
||||||
|
|
||||||
|
foreach(MB3_MeshBakerCommon baker in selectedBakers) obsToCombine.AddRange(baker.GetObjectsToCombine());
|
||||||
|
Selection.objects = obsToCombine.ToArray();
|
||||||
|
if (momm.GetObjectsToCombine().Count > 0)
|
||||||
|
{
|
||||||
|
SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(gc_SortAlongAxis))
|
||||||
|
{
|
||||||
|
MB3_MeshBakerRoot.ZSortObjects sorter = new MB3_MeshBakerRoot.ZSortObjects();
|
||||||
|
sorter.sortAxis = sortOrderAxis.vector3Value;
|
||||||
|
sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.PropertyField(outputOptions, gc_outputOptoinsGUIContent);
|
||||||
|
if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject)
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
Transform pgo = (Transform)EditorGUILayout.ObjectField(gc_parentSceneObject, parentSceneObject.objectReferenceValue, typeof(Transform), true);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
if (pgo != null && MB_Utility.IsSceneInstance(pgo.gameObject))
|
||||||
|
{
|
||||||
|
parentSceneObject.objectReferenceValue = pgo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentSceneObject.objectReferenceValue = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo switch to renderer
|
||||||
|
momm.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("Combined Mesh Object", momm.meshCombiner.resultSceneObject, typeof(GameObject), true);
|
||||||
|
if (momm is MB3_MeshBaker)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
string l = "Mesh";
|
||||||
|
Mesh m = (Mesh)mesh.objectReferenceValue;
|
||||||
|
if (m != null)
|
||||||
|
{
|
||||||
|
l += " (" + m.GetInstanceID() + ")";
|
||||||
|
}
|
||||||
|
Mesh nm = (Mesh)EditorGUILayout.ObjectField(gc_combinedMesh, m, typeof(Mesh), true);
|
||||||
|
if (nm != m)
|
||||||
|
{
|
||||||
|
Undo.RecordObject(momm, "Assign Mesh");
|
||||||
|
MB3_MeshCombinerSingle.MeshCreationConditions meshBirthType = ((MB3_MeshCombinerSingle)momm.meshCombiner).SetMesh(nm);
|
||||||
|
SerializedProperty meshBirth = combiner.FindPropertyRelative("_meshBirth"); // SetMesh sets the _meshBirth field but it doesn't get remembered unless we do this.
|
||||||
|
meshBirth.enumValueIndex = (int)meshBirthType;
|
||||||
|
mesh.objectReferenceValue = nm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MB3_MeshCombinerSingle.EVAL_VERSION)
|
||||||
|
{
|
||||||
|
bool enableSaveMeshButton = _ShouldWeEnableSaveAsAsset(target);
|
||||||
|
{
|
||||||
|
EditorGUI.BeginDisabledGroup(!enableSaveMeshButton);
|
||||||
|
if (GUILayout.Button(gc_saveMeshAsAsset))
|
||||||
|
{
|
||||||
|
_SaveMeshAsAsset(target);
|
||||||
|
}
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
|
||||||
|
{
|
||||||
|
if (momm.meshCombiner.settings.renderType == MB_RenderType.skinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("The workflow for baking Skinned Meshes into prefabs has changed as of version 29.1. " +
|
||||||
|
"It is no longer necessary to manually copy bones to the target prefab after baking. This should happen automatically.", MessageType.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
Transform pgo = (Transform)EditorGUILayout.ObjectField(gc_parentSceneObject, parentSceneObject.objectReferenceValue, typeof(Transform), true);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
if (pgo != null && MB_Utility.IsSceneInstance(pgo.gameObject))
|
||||||
|
{
|
||||||
|
parentSceneObject.objectReferenceValue = pgo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentSceneObject.objectReferenceValue = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
momm.resultPrefab = (GameObject)EditorGUILayout.ObjectField(gc_combinedMeshPrefabGUIContent, momm.resultPrefab, typeof(GameObject), true);
|
||||||
|
if (momm.resultPrefab != null)
|
||||||
|
{
|
||||||
|
string assetPath = AssetDatabase.GetAssetPath(momm.resultPrefab);
|
||||||
|
if (assetPath == null || assetPath.Length == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("The " + gc_combinedMeshPrefabGUIContent.text + " must be a prefab asset, not a scene GameObject");
|
||||||
|
momm.resultPrefab = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MB_PrefabType pt = MBVersionEditor.PrefabUtility_GetPrefabType(momm.resultPrefab);
|
||||||
|
if (pt != MB_PrefabType.prefabAsset)
|
||||||
|
{
|
||||||
|
Debug.LogError("The " + gc_combinedMeshPrefabGUIContent.text + " must be a prefab asset, the prefab type was '" + pt + "'");
|
||||||
|
momm.resultPrefab = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Create Empty Prefab"))
|
||||||
|
{
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
{
|
||||||
|
string path = EditorUtility.SaveFilePanelInProject("Create Empty Prefab", "MyPrefab", "prefab", "Create a prefab containing an empty GameObject");
|
||||||
|
string pathNoFolder = Path.GetDirectoryName(path);
|
||||||
|
string fileNameNoExt = Path.GetFileNameWithoutExtension(path);
|
||||||
|
List<MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
if (selectedBakers.Count > 1) Debug.Log("About to create prefabs for " + selectedBakers.Count);
|
||||||
|
int idx = 0;
|
||||||
|
foreach (MB3_MeshBakerCommon baker in selectedBakers)
|
||||||
|
{
|
||||||
|
createEmptyPrefab(baker, pathNoFolder, fileNameNoExt, idx);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(resultPrefabLeaveInstanceInSceneAfterBake, gc_resultPrefabLeaveInstanceInSceneAfterBake);
|
||||||
|
if (momm is MB3_MeshBaker)
|
||||||
|
{
|
||||||
|
string l = "Mesh";
|
||||||
|
Mesh m = (Mesh)mesh.objectReferenceValue;
|
||||||
|
if (m != null)
|
||||||
|
{
|
||||||
|
l += " (" + m.GetInstanceID() + ")";
|
||||||
|
}
|
||||||
|
Mesh nm = (Mesh)EditorGUILayout.ObjectField(gc_combinedMesh, m, typeof(Mesh), true);
|
||||||
|
if (nm != m)
|
||||||
|
{
|
||||||
|
Undo.RecordObject(momm, "Assign Mesh");
|
||||||
|
((MB3_MeshCombinerSingle)momm.meshCombiner).SetMesh(nm);
|
||||||
|
mesh.objectReferenceValue = nm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Try the BatchPrefabBaker component! It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info);
|
||||||
|
if (GUILayout.Button("Choose Folder For Bake In Place Meshes"))
|
||||||
|
{
|
||||||
|
string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, "");
|
||||||
|
if (!newFolder.Contains(Application.dataPath)) Debug.LogWarning("The chosen folder must be in your assets folder.");
|
||||||
|
string folder = "Assets" + newFolder.Replace(Application.dataPath, "");
|
||||||
|
List<MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
Undo.RecordObjects(targets, "Undo Set Folder");
|
||||||
|
foreach (MB3_MeshBakerCommon baker in selectedBakers)
|
||||||
|
{
|
||||||
|
baker.bakeAssetsInPlaceFolderPath = folder;
|
||||||
|
EditorUtility.SetDirty(baker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Folder For Meshes: " + momm.bakeAssetsInPlaceFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (momm is MB3_MultiMeshBaker)
|
||||||
|
{
|
||||||
|
MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)momm.meshCombiner;
|
||||||
|
mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
||||||
|
bool settingsEnabled = true;
|
||||||
|
|
||||||
|
//------------- Mesh Baker Settings is a bit tricky because it is an interface.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
UnityEngine.Object obj = settingsHolder.objectReferenceValue;
|
||||||
|
|
||||||
|
// Don't use a PropertyField because we may not be able to use the assigned object. It may not implement requried interface.
|
||||||
|
obj = EditorGUILayout.ObjectField(gc_Settings, obj, typeof(UnityEngine.Object), true);
|
||||||
|
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
settingsEnabled = true;
|
||||||
|
settingsHolder.objectReferenceValue = null;
|
||||||
|
if (meshBakerSettingsExternal != null)
|
||||||
|
{
|
||||||
|
meshBakerSettingsExternal.OnDisable();
|
||||||
|
meshBakerSettingsExternal = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (obj is GameObject)
|
||||||
|
{
|
||||||
|
// Check to see if there is a component on this game object that implements MB_IMeshBakerSettingsHolder
|
||||||
|
MB_IMeshBakerSettingsHolder itf = (MB_IMeshBakerSettingsHolder)((GameObject)obj).GetComponent(typeof(MB_IMeshBakerSettingsHolder));
|
||||||
|
if (itf != null)
|
||||||
|
{
|
||||||
|
settingsEnabled = false;
|
||||||
|
Component settingsHolderComponent = (Component)itf;
|
||||||
|
if (settingsHolder.objectReferenceValue != settingsHolderComponent)
|
||||||
|
{
|
||||||
|
settingsHolder.objectReferenceValue = settingsHolderComponent;
|
||||||
|
meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
|
||||||
|
UnityEngine.Object targetObj;
|
||||||
|
string propertyName;
|
||||||
|
itf.GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
|
||||||
|
SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
|
||||||
|
meshBakerSettingsExternal.OnEnable(meshBakerSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("You must drag a MeshBakerGrouper or a MeshCombinerSetting asset to this field.");
|
||||||
|
settingsEnabled = true;
|
||||||
|
settingsHolder.objectReferenceValue = null;
|
||||||
|
if (meshBakerSettingsExternal != null)
|
||||||
|
{
|
||||||
|
meshBakerSettingsExternal.OnDisable();
|
||||||
|
meshBakerSettingsExternal = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (obj is MB_IMeshBakerSettingsHolder)
|
||||||
|
{
|
||||||
|
settingsEnabled = false;
|
||||||
|
if (settingsHolder.objectReferenceValue != obj)
|
||||||
|
{
|
||||||
|
settingsHolder.objectReferenceValue = obj;
|
||||||
|
meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
|
||||||
|
UnityEngine.Object targetObj;
|
||||||
|
string propertyName;
|
||||||
|
((MB_IMeshBakerSettingsHolder)obj).GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
|
||||||
|
SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
|
||||||
|
meshBakerSettingsExternal.OnEnable(meshBakerSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("You must drag a MeshBakerGrouper or a MeshCombinerSetting asset to this field.");
|
||||||
|
}
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
if (settingsHolder.objectReferenceValue == null)
|
||||||
|
{
|
||||||
|
// Use the meshCombiner settings
|
||||||
|
meshBakerSettingsThis.DrawGUI(momm.meshCombiner, settingsEnabled, doingTextureArray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (meshBakerSettingsExternal == null)
|
||||||
|
{
|
||||||
|
meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
|
||||||
|
UnityEngine.Object targetObj;
|
||||||
|
string propertyName;
|
||||||
|
((MB_IMeshBakerSettingsHolder)obj).GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
|
||||||
|
SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
|
||||||
|
meshBakerSettingsExternal.OnEnable(meshBakerSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
meshBakerSettingsExternal.DrawGUI(((MB_IMeshBakerSettingsHolder)settingsHolder.objectReferenceValue).GetMeshBakerSettings(), settingsEnabled, doingTextureArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color oldColor = GUI.backgroundColor;
|
||||||
|
GUI.backgroundColor = buttonColor;
|
||||||
|
if (GUILayout.Button("Bake"))
|
||||||
|
{
|
||||||
|
List<MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
if (selectedBakers.Count > 1) Debug.Log("About to bake " + selectedBakers.Count);
|
||||||
|
foreach(MB3_MeshBakerCommon baker in selectedBakers)
|
||||||
|
{
|
||||||
|
// Why are we caching and recreating the SerializedObject? Because "bakeIntoPrefab" corrupts the serialized object
|
||||||
|
// and the meshBaker SerializedObject throws an NRE the next time it gets used.
|
||||||
|
MB3_MeshBakerCommon mbr = (MB3_MeshBakerCommon) meshBaker.targetObject;
|
||||||
|
bake(baker);
|
||||||
|
meshBaker = new SerializedObject(mbr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUI.backgroundColor = oldColor;
|
||||||
|
|
||||||
|
string enableRenderersLabel;
|
||||||
|
bool disableRendererInSource = false;
|
||||||
|
if (momm.GetObjectsToCombine().Count > 0)
|
||||||
|
{
|
||||||
|
Renderer r = MB_Utility.GetRenderer(momm.GetObjectsToCombine()[0]);
|
||||||
|
if (r != null && r.enabled) disableRendererInSource = true;
|
||||||
|
}
|
||||||
|
if (disableRendererInSource)
|
||||||
|
{
|
||||||
|
enableRenderersLabel = "Disable Renderers On Source Objects";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enableRenderersLabel = "Enable Renderers On Source Objects";
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(enableRenderersLabel))
|
||||||
|
{
|
||||||
|
List<MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
foreach (MB3_MeshBakerCommon baker in selectedBakers)
|
||||||
|
{
|
||||||
|
baker.EnableDisableSourceObjectRenderers(!disableRendererInSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meshBaker.ApplyModifiedProperties();
|
||||||
|
meshBaker.SetIsDifferentCacheDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateProgressBar(string msg, float progress)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayProgressBar("Combining Meshes", msg, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool bake(MB3_MeshBakerCommon mom)
|
||||||
|
{
|
||||||
|
SerializedObject so = null;
|
||||||
|
return bake(mom, ref so);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MB3_MeshBakerCommon> _getBakersFromTargets(UnityEngine.Object[] targs)
|
||||||
|
{
|
||||||
|
List<MB3_MeshBakerCommon> outList = new List<MB3_MeshBakerCommon>(targs.Length);
|
||||||
|
for (int i = 0; i < targs.Length; i++)
|
||||||
|
{
|
||||||
|
outList.Add((MB3_MeshBakerCommon) targs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _ShouldWeEnableSaveAsAsset(MB3_MeshBakerCommon target)
|
||||||
|
{
|
||||||
|
if (!(target is MB3_MeshBaker))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_MeshBaker mb = (MB3_MeshBaker) target;
|
||||||
|
Mesh bakedMesh = ((MB3_MeshCombinerSingle)mb.meshCombiner).GetMesh();
|
||||||
|
|
||||||
|
bool meshIsNull = bakedMesh == null;
|
||||||
|
bool meshHasNoVertices = bakedMesh.vertexCount == 0;
|
||||||
|
bool meshIsAlreadyAnAsset = !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(bakedMesh));
|
||||||
|
bool disableSaveMeshButton = meshIsNull || meshHasNoVertices || meshIsAlreadyAnAsset;
|
||||||
|
return !disableSaveMeshButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _SaveMeshAsAsset(MB3_MeshBakerCommon target)
|
||||||
|
{
|
||||||
|
if (!(target is MB3_MeshBaker))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_MeshBaker mb = (MB3_MeshBaker)target;
|
||||||
|
Mesh bakedMesh = ((MB3_MeshCombinerSingle)mb.meshCombiner).GetMesh();
|
||||||
|
|
||||||
|
string path = EditorUtility.SaveFilePanel("Save Mesh", "Assets", "myMesh", "asset");
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
Debug.Log("No path selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string projectPath = Application.dataPath;
|
||||||
|
if (path.StartsWith(projectPath) == false)
|
||||||
|
{
|
||||||
|
Debug.Log("Path must be inside of the Assets folder.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh meshAsset = MB3_MeshBakerEditorFunctionsCore.SaveMeshAsAsset(bakedMesh, path);
|
||||||
|
|
||||||
|
((MB3_MeshCombinerSingle)mb.meshCombiner).SetMesh(meshAsset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createEmptyPrefab(MB3_MeshBakerCommon mom, string folder, string prefabNameNoExtension, int idx)
|
||||||
|
{
|
||||||
|
if (prefabNameNoExtension != null && prefabNameNoExtension.Length > 0)
|
||||||
|
{
|
||||||
|
string prefabName = prefabNameNoExtension + idx;
|
||||||
|
GameObject go = new GameObject(prefabName);
|
||||||
|
string fullName = folder + "/" + prefabName + ".prefab";
|
||||||
|
fullName = AssetDatabase.GenerateUniqueAssetPath(fullName);
|
||||||
|
Debug.Log(fullName);
|
||||||
|
MBVersionEditor.PrefabUtility_CreatePrefab(fullName, go);
|
||||||
|
GameObject.DestroyImmediate(go);
|
||||||
|
SerializedObject so = new SerializedObject(mom);
|
||||||
|
so.FindProperty("resultPrefab").objectReferenceValue = (GameObject)AssetDatabase.LoadAssetAtPath(fullName, typeof(GameObject));
|
||||||
|
so.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bakes a combined mesh.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mom"></param>
|
||||||
|
/// <param name="so">This is needed to work around a Unity bug where UnpackPrefabInstance corrupts
|
||||||
|
/// a SerializedObject. Only needed for bake into prefab.</param>
|
||||||
|
public static bool bake(MB3_MeshBakerCommon mom, ref SerializedObject so)
|
||||||
|
{
|
||||||
|
bool createdDummyTextureBakeResults = false;
|
||||||
|
bool success = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (mom.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject ||
|
||||||
|
mom.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
|
||||||
|
{
|
||||||
|
success = MB3_MeshBakerEditorFunctions.BakeIntoCombined(mom, out createdDummyTextureBakeResults, ref so);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//bake meshes in place
|
||||||
|
if (mom is MB3_MeshBaker)
|
||||||
|
{
|
||||||
|
if (MB3_MeshCombiner.EVAL_VERSION)
|
||||||
|
{
|
||||||
|
Debug.LogError("Bake Mesh Assets In Place is disabled in the evaluation version.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;
|
||||||
|
if (!MB3_MeshBakerRoot.DoCombinedValidate(mom, MB_ObjsToCombineTypes.prefabOnly, new MB3_EditorMethods(), vl)) return false;
|
||||||
|
|
||||||
|
List<GameObject> objsToMesh = mom.GetObjectsToCombine();
|
||||||
|
success = MB3_BakeInPlace.BakeMeshesInPlace((MB3_MeshCombinerSingle)((MB3_MeshBaker)mom).meshCombiner, objsToMesh, mom.bakeAssetsInPlaceFolderPath, mom.meshCombiner.clearBuffersAfterBake, updateProgressBar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Multi Mesh Baker components cannot be used for Bake Mesh Assets In Place. Use an ordinary MeshBaker object instead.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mom.meshCombiner.CheckIntegrity();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (createdDummyTextureBakeResults && mom.textureBakeResults != null)
|
||||||
|
{
|
||||||
|
MB_Utility.Destroy(mom.textureBakeResults);
|
||||||
|
mom.textureBakeResults = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
mom.meshCombiner.Dispose();
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6187499e1f9c67c4b8f295a0d54cb7ba
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerEditorInternal.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB3_MeshBakerEditorWindow : EditorWindow
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorWindowAddObjectsTab addObjectsTab;
|
||||||
|
MB3_MeshBakerEditorWindowAnalyseSceneTab analyseSceneTab;
|
||||||
|
Vector2 scrollPos = Vector2.zero;
|
||||||
|
int selectedTab = 0;
|
||||||
|
GUIContent[] tabs = new GUIContent[] { new GUIContent("Analyse Scene & Generate Bakers"), new GUIContent("Search For Meshes To Add") };
|
||||||
|
|
||||||
|
[MenuItem("Window/Mesh Baker/Mesh Baker")]
|
||||||
|
static void Init()
|
||||||
|
{
|
||||||
|
EditorWindow.GetWindow(typeof(MB3_MeshBakerEditorWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTarget(MB3_MeshBakerRoot targ)
|
||||||
|
{
|
||||||
|
if (addObjectsTab == null) addObjectsTab = new MB3_MeshBakerEditorWindowAddObjectsTab();
|
||||||
|
addObjectsTab.target = targ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnGUI()
|
||||||
|
{
|
||||||
|
selectedTab = GUILayout.Toolbar(selectedTab, tabs);
|
||||||
|
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Width(position.width), GUILayout.Height(position.height));
|
||||||
|
|
||||||
|
if (selectedTab == 0)
|
||||||
|
{
|
||||||
|
analyseSceneTab.drawTabAnalyseScene(position);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addObjectsTab.drawTabAddObjectsToBakers();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
if (addObjectsTab == null) addObjectsTab = new MB3_MeshBakerEditorWindowAddObjectsTab();
|
||||||
|
if (analyseSceneTab == null) analyseSceneTab = new MB3_MeshBakerEditorWindowAnalyseSceneTab();
|
||||||
|
addObjectsTab.OnEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable()
|
||||||
|
{
|
||||||
|
addObjectsTab.OnDisable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 08905a0f08b77054d9ee3ee91b6a3804
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerEditorWindow.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,836 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEngine.Rendering;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB3_MeshBakerEditorWindowAddObjectsTab : MB3_MeshBakerEditorWindowInterface
|
||||||
|
{
|
||||||
|
public enum OpacityType
|
||||||
|
{
|
||||||
|
unknown = -1,
|
||||||
|
opaque = 0,
|
||||||
|
transparent = 1,
|
||||||
|
alpha_clip = 2,
|
||||||
|
mixed = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
static string[] LODLevelLabels = new string[]
|
||||||
|
{
|
||||||
|
"All LOD Levels", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int[] LODLevelValues = new int[]
|
||||||
|
{
|
||||||
|
-1,0,1,2,3,4,5,6,7,8,9
|
||||||
|
};
|
||||||
|
|
||||||
|
static string[] transpOrOpaqueLabels = new string[]
|
||||||
|
{
|
||||||
|
"Any", "Opaque Only", "Transparent Only", "AlphaClipped Only", "Mixed Transp And Opaque Mats Only"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int[] transpOrOpaqueValues = new int[]
|
||||||
|
{
|
||||||
|
(int) OpacityType.unknown, (int) OpacityType.opaque, (int) OpacityType.transparent, (int) OpacityType.alpha_clip, (int) OpacityType.mixed
|
||||||
|
};
|
||||||
|
|
||||||
|
public MB3_MeshBakerRoot _target = null;
|
||||||
|
public MonoBehaviour target
|
||||||
|
{
|
||||||
|
get { return _target; }
|
||||||
|
set { _target = (MB3_MeshBakerRoot)value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject targetGO = null;
|
||||||
|
GameObject oldTargetGO = null;
|
||||||
|
MB3_TextureBaker textureBaker;
|
||||||
|
MB3_MeshBaker meshBaker;
|
||||||
|
UnityEngine.Object[] targs = new UnityEngine.Object[1];
|
||||||
|
SerializedObject serializedObject;
|
||||||
|
|
||||||
|
GUIContent GUIContentRegExpression = new GUIContent("Matches Regular Expression", @"A valid # regular express. Examples:" + "\n\n" +
|
||||||
|
@" ([A-Za-z0-9\-]+)(LOD1) matches one or more chars,numbers and hyphen ending with LOD1." + "\n\n" +
|
||||||
|
@" (Grass)([A-Za-z0-9\-\(\) ]+) matches the string 'Grass' followed by characters, numbers, hyphen, brackets or space." + "\n\n");
|
||||||
|
|
||||||
|
string helpBoxString = "";
|
||||||
|
string regExParseError = "";
|
||||||
|
bool onlyStaticObjects = false;
|
||||||
|
bool onlyEnabledObjects = false;
|
||||||
|
bool excludeMeshesWithOBuvs = true;
|
||||||
|
bool excludeMeshesAlreadyAddedToBakers = true;
|
||||||
|
int lodLevelToInclude = -1;
|
||||||
|
OpacityType transpOrOpaque = OpacityType.unknown;
|
||||||
|
int lightmapIndex = -2;
|
||||||
|
int[] lightmapValues = new int[64];
|
||||||
|
string[] lightmapDisplayValues = new string[64];
|
||||||
|
LayerMask layerMask = ~0;
|
||||||
|
int[] layerIntValues = new int[32];
|
||||||
|
string[] layerDisplayValues = new string[32];
|
||||||
|
string searchRegEx = "";
|
||||||
|
Material shaderMat = null;
|
||||||
|
Material mat = null;
|
||||||
|
|
||||||
|
bool tbFoldout = false;
|
||||||
|
bool mbFoldout = false;
|
||||||
|
|
||||||
|
MB3_MeshBakerEditorInternal mbe = new MB3_MeshBakerEditorInternal();
|
||||||
|
MB3_TextureBakerEditorInternal tbe = new MB3_TextureBakerEditorInternal();
|
||||||
|
|
||||||
|
public void SetLightmapValuesAndDisplayValues()
|
||||||
|
{
|
||||||
|
lightmapValues = new int[64];
|
||||||
|
lightmapDisplayValues = new string[64];
|
||||||
|
lightmapValues[0] = -2;
|
||||||
|
lightmapValues[1] = -1;
|
||||||
|
lightmapDisplayValues[0] = "don't filter on lightmapping";
|
||||||
|
lightmapDisplayValues[1] = "not lightmapped";
|
||||||
|
for (int i = 2; i < lightmapDisplayValues.Length; i++)
|
||||||
|
{
|
||||||
|
lightmapDisplayValues[i] = "" + (i - 2);
|
||||||
|
lightmapValues[i] = i - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLayerValuesAndDisplayValues()
|
||||||
|
{
|
||||||
|
layerIntValues = new int[32];
|
||||||
|
layerDisplayValues = new string[32];
|
||||||
|
for (int i = 0; i < layerDisplayValues.Length; i++)
|
||||||
|
{
|
||||||
|
if (GetLayerName(i) != "")
|
||||||
|
{
|
||||||
|
layerDisplayValues[i] = "" + (i) + ": " + GetLayerName(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
layerDisplayValues[i] = "" + (i);
|
||||||
|
}
|
||||||
|
layerIntValues[i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void OnEnable()
|
||||||
|
{
|
||||||
|
SetLightmapValuesAndDisplayValues();
|
||||||
|
SetLayerValuesAndDisplayValues();
|
||||||
|
|
||||||
|
if (textureBaker != null)
|
||||||
|
{
|
||||||
|
serializedObject = new SerializedObject(textureBaker);
|
||||||
|
tbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
else if (meshBaker != null)
|
||||||
|
{
|
||||||
|
serializedObject = new SerializedObject(meshBaker);
|
||||||
|
mbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
tbe.OnDisable();
|
||||||
|
mbe.OnDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawTabAddObjectsToBakers()
|
||||||
|
{
|
||||||
|
if (helpBoxString == null) helpBoxString = "";
|
||||||
|
EditorGUILayout.HelpBox("To add, select one or more objects in the hierarchy view. Child Game Objects with MeshRender or SkinnedMeshRenderer will be added. Use the fields below to filter what is added." +
|
||||||
|
"To remove, use the fields below to filter what is removed.\n" + helpBoxString, UnityEditor.MessageType.None);
|
||||||
|
target = (MB3_MeshBakerRoot)EditorGUILayout.ObjectField("Target to add objects to", target, typeof(MB3_MeshBakerRoot), true);
|
||||||
|
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
targetGO = target.gameObject;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetGO = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetGO != oldTargetGO && targetGO != null)
|
||||||
|
{
|
||||||
|
textureBaker = targetGO.GetComponent<MB3_TextureBaker>();
|
||||||
|
meshBaker = targetGO.GetComponent<MB3_MeshBaker>();
|
||||||
|
tbe = new MB3_TextureBakerEditorInternal();
|
||||||
|
mbe = new MB3_MeshBakerEditorInternal();
|
||||||
|
oldTargetGO = targetGO;
|
||||||
|
if (textureBaker != null)
|
||||||
|
{
|
||||||
|
serializedObject = new SerializedObject(textureBaker);
|
||||||
|
tbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
else if (meshBaker != null)
|
||||||
|
{
|
||||||
|
serializedObject = new SerializedObject(meshBaker);
|
||||||
|
mbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUIUtility.labelWidth = 300;
|
||||||
|
onlyStaticObjects = EditorGUILayout.Toggle("Only Static Objects", onlyStaticObjects);
|
||||||
|
|
||||||
|
onlyEnabledObjects = EditorGUILayout.Toggle("Only Enabled Objects", onlyEnabledObjects);
|
||||||
|
|
||||||
|
excludeMeshesWithOBuvs = EditorGUILayout.Toggle("Exclude meshes with out-of-bounds UVs", excludeMeshesWithOBuvs);
|
||||||
|
|
||||||
|
excludeMeshesAlreadyAddedToBakers = EditorGUILayout.Toggle("Exclude GameObjects already added to bakers", excludeMeshesAlreadyAddedToBakers);
|
||||||
|
|
||||||
|
lodLevelToInclude = EditorGUILayout.IntPopup("Only include objects on LOD Level", lodLevelToInclude, LODLevelLabels, LODLevelValues);
|
||||||
|
|
||||||
|
mat = (Material)EditorGUILayout.ObjectField("Using Material", mat, typeof(Material), true);
|
||||||
|
shaderMat = (Material)EditorGUILayout.ObjectField("Using Shader", shaderMat, typeof(Material), true);
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("Using Lightmap Index ");
|
||||||
|
lightmapIndex = EditorGUILayout.IntPopup(lightmapIndex,
|
||||||
|
lightmapDisplayValues,
|
||||||
|
lightmapValues);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("Using Layers");
|
||||||
|
layerMask.value = EditorGUILayout.MaskField(layerMask.value, layerDisplayValues);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
transpOrOpaque = (OpacityType) EditorGUILayout.IntPopup("Only Include Transparent Or Opaque", (int) transpOrOpaque, transpOrOpaqueLabels, transpOrOpaqueValues);
|
||||||
|
|
||||||
|
|
||||||
|
if (regExParseError != null && regExParseError.Length > 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Error In Regular Expression:\n" + regExParseError, MessageType.Error);
|
||||||
|
}
|
||||||
|
searchRegEx = EditorGUILayout.TextField(GUIContentRegExpression, searchRegEx);
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Add Selected Meshes To Target"))
|
||||||
|
{
|
||||||
|
addSelectedObjects();
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("Remove Matching Meshes From Target"))
|
||||||
|
{
|
||||||
|
removeSelectedObjects();
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (textureBaker != null)
|
||||||
|
{
|
||||||
|
MB_EditorUtil.DrawSeparator();
|
||||||
|
tbFoldout = EditorGUILayout.Foldout(tbFoldout, "Texture Baker");
|
||||||
|
if (tbFoldout)
|
||||||
|
{
|
||||||
|
if (targs == null) targs = new UnityEngine.Object[1];
|
||||||
|
targs[0] = textureBaker;
|
||||||
|
tbe.DrawGUI(serializedObject, textureBaker, targs, typeof(MB3_MeshBakerEditorWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (meshBaker != null)
|
||||||
|
{
|
||||||
|
MB_EditorUtil.DrawSeparator();
|
||||||
|
mbFoldout = EditorGUILayout.Foldout(mbFoldout, "Mesh Baker");
|
||||||
|
if (mbFoldout)
|
||||||
|
{
|
||||||
|
if (targs == null) targs = new UnityEngine.Object[1];
|
||||||
|
targs[0] = meshBaker;
|
||||||
|
mbe.DrawGUI(serializedObject, (MB3_MeshBaker)meshBaker, targs, typeof(MB3_MeshBakerEditorWindow));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObject> GetFilteredList(bool addingObjects)
|
||||||
|
{
|
||||||
|
List<GameObject> newMomObjs = new List<GameObject>();
|
||||||
|
MB3_MeshBakerRoot mom = (MB3_MeshBakerRoot)target;
|
||||||
|
if (mom == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Must select a target MeshBaker");
|
||||||
|
return newMomObjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject dontAddMe = null;
|
||||||
|
Renderer r = MB_Utility.GetRenderer(mom.gameObject);
|
||||||
|
if (r != null)
|
||||||
|
{ //make sure that this MeshBaker object is not in list
|
||||||
|
dontAddMe = r.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_MeshBakerRoot[] allBakers = (MB3_MeshBakerRoot[])MBVersion.FindSceneObjectsOfType(typeof(MB3_MeshBakerRoot));
|
||||||
|
HashSet<GameObject> objectsAlreadyIncludedInBakers = new HashSet<GameObject>();
|
||||||
|
|
||||||
|
if (addingObjects)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < allBakers.Length; i++)
|
||||||
|
{
|
||||||
|
List<GameObject> objsToCombine = allBakers[i].GetObjectsToCombine();
|
||||||
|
for (int j = 0; j < objsToCombine.Count; j++)
|
||||||
|
{
|
||||||
|
if (objsToCombine[j] != null) objectsAlreadyIncludedInBakers.Add(objsToCombine[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject[] gos = Selection.gameObjects;
|
||||||
|
if (gos.Length == 0)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("No objects selected in hierarchy view. Nothing added. Try selecting some objects.");
|
||||||
|
return newMomObjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObject> mrs = new List<GameObject>();
|
||||||
|
for (int i = 0; i < gos.Length; i++)
|
||||||
|
{
|
||||||
|
GameObject go = gos[i];
|
||||||
|
Renderer[] rs = go.GetComponentsInChildren<Renderer>(true);
|
||||||
|
for (int j = 0; j < rs.Length; j++)
|
||||||
|
{
|
||||||
|
if (rs[j] is MeshRenderer || rs[j] is SkinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
mrs.Add(rs[j].gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newMomObjs = FilterList(mrs, objectsAlreadyIncludedInBakers, dontAddMe, addingObjects);
|
||||||
|
return newMomObjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetLODLevelForRenderer(Renderer r)
|
||||||
|
{
|
||||||
|
if (r != null)
|
||||||
|
{
|
||||||
|
LODGroup lodGroup = r.GetComponentInParent<LODGroup>();
|
||||||
|
if (lodGroup != null)
|
||||||
|
{
|
||||||
|
LOD[] lods = lodGroup.GetLODs();
|
||||||
|
for (int lodIdx = 0; lodIdx < lods.Length; lodIdx++)
|
||||||
|
{
|
||||||
|
Renderer[] rs = lods[lodIdx].renderers;
|
||||||
|
for (int j = 0; j < rs.Length; j++)
|
||||||
|
{
|
||||||
|
if (rs[j] == r)
|
||||||
|
{
|
||||||
|
return lodIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetLayerValue(GameObject go)
|
||||||
|
{
|
||||||
|
return go.layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetLayerName(int layerNum)
|
||||||
|
{
|
||||||
|
string layerName = LayerMask.LayerToName(layerNum);
|
||||||
|
return "" + layerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObject> FilterList(List<GameObject> mrss,
|
||||||
|
HashSet<GameObject> objectsAlreadyIncludedInBakers,
|
||||||
|
GameObject dontAddMe,
|
||||||
|
bool addingObjects)
|
||||||
|
{
|
||||||
|
int numInSelection = 0;
|
||||||
|
int numStaticExcluded = 0;
|
||||||
|
int numEnabledExcluded = 0;
|
||||||
|
int numLightmapExcluded = 0;
|
||||||
|
int numLayerExcluded = 0;
|
||||||
|
int numLodLevelExcluded = 0;
|
||||||
|
int numOBuvExcluded = 0;
|
||||||
|
int numMatExcluded = 0;
|
||||||
|
int numShaderExcluded = 0;
|
||||||
|
int numRegExExcluded = 0;
|
||||||
|
int numAlreadyIncludedExcluded = 0;
|
||||||
|
int numTranspOrOpaqueExluded = 0;
|
||||||
|
System.Text.RegularExpressions.Regex regex = null;
|
||||||
|
if (searchRegEx != null && searchRegEx.Length > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
regex = new System.Text.RegularExpressions.Regex(searchRegEx);
|
||||||
|
regExParseError = "";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
regExParseError = ex.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<int, MB_Utility.MeshAnalysisResult> meshAnalysisResultsCache = new Dictionary<int, MB_Utility.MeshAnalysisResult>(); //cache results
|
||||||
|
List<GameObject> newMomObjs = new List<GameObject>();
|
||||||
|
for (int j = 0; j < mrss.Count; j++)
|
||||||
|
{
|
||||||
|
if (mrss[j] == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Renderer mrs = mrss[j].GetComponent<Renderer>();
|
||||||
|
int layerValue = GetLayerValue(mrss[j]);
|
||||||
|
|
||||||
|
if (mrs is MeshRenderer || mrs is SkinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
if (mrs.GetComponent<TextMesh>() != null)
|
||||||
|
{
|
||||||
|
continue; //don't add TextMeshes
|
||||||
|
}
|
||||||
|
|
||||||
|
numInSelection++;
|
||||||
|
if (!newMomObjs.Contains(mrs.gameObject))
|
||||||
|
{
|
||||||
|
bool addMe = true;
|
||||||
|
if (!mrs.gameObject.isStatic && onlyStaticObjects)
|
||||||
|
{
|
||||||
|
numStaticExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!mrs.enabled || !mrs.gameObject.activeInHierarchy) && onlyEnabledObjects)
|
||||||
|
{
|
||||||
|
numEnabledExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lightmapIndex != -2)
|
||||||
|
{
|
||||||
|
if (mrs.lightmapIndex != lightmapIndex)
|
||||||
|
{
|
||||||
|
numLightmapExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerMask != 0)
|
||||||
|
{
|
||||||
|
int layerBit = 1 << layerValue;
|
||||||
|
//Debug.Log("LayerBit: " + layerBit);
|
||||||
|
if ((layerMask & layerBit) == 0)
|
||||||
|
{
|
||||||
|
numLayerExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numLayerExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lodLevelToInclude == -1)
|
||||||
|
{
|
||||||
|
// not filtering on LODLevel
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetLODLevelForRenderer(mrs) != lodLevelToInclude)
|
||||||
|
{
|
||||||
|
numLodLevelExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transpOrOpaque == OpacityType.unknown)
|
||||||
|
{
|
||||||
|
// not filtering on transp or opaque
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!RendererTransparentOrOpaqueMatches(mrs, transpOrOpaque))
|
||||||
|
{
|
||||||
|
numTranspOrOpaqueExluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only do this check when adding objects. If removing objects shouldn't do it
|
||||||
|
if (addingObjects &&
|
||||||
|
excludeMeshesAlreadyAddedToBakers &&
|
||||||
|
objectsAlreadyIncludedInBakers.Contains(mrs.gameObject))
|
||||||
|
{
|
||||||
|
numAlreadyIncludedExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh mm = MB_Utility.GetMesh(mrs.gameObject);
|
||||||
|
if (mm != null)
|
||||||
|
{
|
||||||
|
MB_Utility.MeshAnalysisResult mar;
|
||||||
|
if (!meshAnalysisResultsCache.TryGetValue(mm.GetInstanceID(), out mar))
|
||||||
|
{
|
||||||
|
MB_Utility.hasOutOfBoundsUVs(mm, ref mar);
|
||||||
|
meshAnalysisResultsCache.Add(mm.GetInstanceID(), mar);
|
||||||
|
}
|
||||||
|
if (mar.hasOutOfBoundsUVs && excludeMeshesWithOBuvs)
|
||||||
|
{
|
||||||
|
numOBuvExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shaderMat != null)
|
||||||
|
{
|
||||||
|
Material[] nMats = mrs.sharedMaterials;
|
||||||
|
bool usesShader = false;
|
||||||
|
foreach (Material nMat in nMats)
|
||||||
|
{
|
||||||
|
if (nMat != null && nMat.shader == shaderMat.shader)
|
||||||
|
{
|
||||||
|
usesShader = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!usesShader)
|
||||||
|
{
|
||||||
|
numShaderExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mat != null)
|
||||||
|
{
|
||||||
|
Material[] nMats = mrs.sharedMaterials;
|
||||||
|
bool usesMat = false;
|
||||||
|
foreach (Material nMat in nMats)
|
||||||
|
{
|
||||||
|
if (nMat == mat)
|
||||||
|
{
|
||||||
|
usesMat = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!usesMat)
|
||||||
|
{
|
||||||
|
numMatExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regex != null)
|
||||||
|
{
|
||||||
|
if (!regex.IsMatch(mrs.gameObject.name))
|
||||||
|
{
|
||||||
|
numRegExExcluded++;
|
||||||
|
addMe = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addMe && mrs.gameObject != dontAddMe)
|
||||||
|
{
|
||||||
|
if (!newMomObjs.Contains(mrs.gameObject))
|
||||||
|
{
|
||||||
|
newMomObjs.Add(mrs.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
|
//sb.AppendFormat("Total objects in selection {0}\n", numInSelection);
|
||||||
|
//Debug.Log( "Total objects in selection " + numInSelection);
|
||||||
|
if (numStaticExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they were not static\n", numStaticExcluded);
|
||||||
|
Debug.Log(numStaticExcluded + " objects were excluded because they were not static\n");
|
||||||
|
}
|
||||||
|
if (numEnabledExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they were disabled\n", numEnabledExcluded);
|
||||||
|
Debug.Log(numEnabledExcluded + " objects were excluded because they were disabled\n");
|
||||||
|
}
|
||||||
|
if (numOBuvExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they had out of bounds uvs\n", numOBuvExcluded);
|
||||||
|
Debug.Log(numOBuvExcluded + " objects were excluded because they had out of bounds uvs\n");
|
||||||
|
}
|
||||||
|
if (numLightmapExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did not match lightmap filter.\n", numLightmapExcluded);
|
||||||
|
Debug.Log(numLightmapExcluded + " objects did not match lightmap filter.\n");
|
||||||
|
}
|
||||||
|
if (numLayerExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did not use the selected layers. \n",
|
||||||
|
numLayerExcluded);
|
||||||
|
Debug.Log(numLayerExcluded + " objects were excluded because they did not use the selected layers");
|
||||||
|
}
|
||||||
|
if (numLodLevelExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did not match the selected LOD level filter.\n", numLodLevelExcluded);
|
||||||
|
Debug.Log(numLodLevelExcluded + " objects did not match LOD level filter.\n");
|
||||||
|
}
|
||||||
|
if (numShaderExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did not use the selected shader.\n", numShaderExcluded);
|
||||||
|
Debug.Log(numShaderExcluded + " objects were excluded because they did not use the selected shader.\n");
|
||||||
|
}
|
||||||
|
if (numMatExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did not use the selected material.\n", numMatExcluded);
|
||||||
|
Debug.Log(numMatExcluded + " objects were excluded because they did not use the selected material.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numTranspOrOpaqueExluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they the didn't match transparent or opaque filter.\n", numTranspOrOpaqueExluded);
|
||||||
|
Debug.LogFormat(" {0} objects were excluded because they the didn't match transparent or opaque filter.\n", numTranspOrOpaqueExluded);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numRegExExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did not match the regular expression.\n", numRegExExcluded);
|
||||||
|
Debug.Log(numRegExExcluded + " objects were excluded because they did not match the regular expression.\n");
|
||||||
|
}
|
||||||
|
if (numAlreadyIncludedExcluded > 0)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(" {0} objects were excluded because they did were already included in other bakers.\n", numAlreadyIncludedExcluded);
|
||||||
|
Debug.Log(numAlreadyIncludedExcluded + " objects were excluded because they did were already included in other bakers.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
helpBoxString = sb.ToString();
|
||||||
|
return newMomObjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private bool RendererTransparentOrOpaqueMatches(Renderer mrs, OpacityType transpOrOpaque)
|
||||||
|
{
|
||||||
|
MBVersion.PipelineType currentRenderPipeline = MBVersion.DetectPipeline();
|
||||||
|
OpacityType isMatTranspOrOpaque = OpacityType.unknown;
|
||||||
|
|
||||||
|
if (mrs == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mrs.sharedMaterials.Length; i++)
|
||||||
|
{
|
||||||
|
Material m = mrs.sharedMaterials[i];
|
||||||
|
if (m == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpacityType isCurMatTranspOrOpaque;
|
||||||
|
if (currentRenderPipeline == MBVersion.PipelineType.URP)
|
||||||
|
{
|
||||||
|
isCurMatTranspOrOpaque = _GetOpaqueOrTransparentURP(m);
|
||||||
|
}
|
||||||
|
else if (currentRenderPipeline == MBVersion.PipelineType.HDRP)
|
||||||
|
{
|
||||||
|
isCurMatTranspOrOpaque = _GetOpaqueOrTransparentHDRP(m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Defualt or unknown pipeline
|
||||||
|
isCurMatTranspOrOpaque = _GetOpaqueOrTransparentBuiltInOrUnknownRP(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMatTranspOrOpaque == OpacityType.unknown)
|
||||||
|
{
|
||||||
|
isMatTranspOrOpaque = isCurMatTranspOrOpaque;
|
||||||
|
}
|
||||||
|
else if (isMatTranspOrOpaque != isCurMatTranspOrOpaque)
|
||||||
|
{
|
||||||
|
// was previously set to something different. Renderer has mixed materials.
|
||||||
|
isMatTranspOrOpaque = OpacityType.mixed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMatTranspOrOpaque == OpacityType.unknown)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return isMatTranspOrOpaque == transpOrOpaque;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpacityType _GetOpaqueOrTransparentBuiltInOrUnknownRP(Material m)
|
||||||
|
{
|
||||||
|
bool isTransparent = m.renderQueue >= (int)RenderQueue.Transparent;
|
||||||
|
bool isAlphaClipped = m.renderQueue == (int)RenderQueue.AlphaTest;
|
||||||
|
|
||||||
|
if (isAlphaClipped)
|
||||||
|
{
|
||||||
|
return OpacityType.alpha_clip;
|
||||||
|
}
|
||||||
|
else if (isTransparent)
|
||||||
|
{
|
||||||
|
return OpacityType.transparent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return OpacityType.opaque;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpacityType _GetOpaqueOrTransparentHDRP(Material m)
|
||||||
|
{
|
||||||
|
if (m.HasProperty("_SurfaceType"))
|
||||||
|
{
|
||||||
|
float surfaceType = m.GetFloat("_SurfaceType");
|
||||||
|
if (surfaceType == 0)
|
||||||
|
{
|
||||||
|
if (m.HasProperty("_AlphaCutoffEnable") && m.GetFloat("_AlphaCutoffEnable") == 1)
|
||||||
|
{
|
||||||
|
return OpacityType.alpha_clip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return OpacityType.opaque;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (surfaceType == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
return OpacityType.transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _GetOpaqueOrTransparentBuiltInOrUnknownRP(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpacityType _GetOpaqueOrTransparentURP(Material m)
|
||||||
|
{
|
||||||
|
if (m.HasProperty("_Surface"))
|
||||||
|
{
|
||||||
|
float surfaceType = m.GetFloat("_Surface");
|
||||||
|
if (surfaceType == 0)
|
||||||
|
{
|
||||||
|
if (m.HasProperty("_AlphaClip") && m.GetFloat("_AlphaClip") == 1)
|
||||||
|
{
|
||||||
|
return OpacityType.alpha_clip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return OpacityType.opaque;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (surfaceType == 1)
|
||||||
|
{
|
||||||
|
return OpacityType.transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _GetOpaqueOrTransparentBuiltInOrUnknownRP(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeSelectedObjects()
|
||||||
|
{
|
||||||
|
MB3_MeshBakerRoot mom = (MB3_MeshBakerRoot)target;
|
||||||
|
if (mom == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Must select a target MeshBaker");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<GameObject> objsToCombine = mom.GetObjectsToCombine();
|
||||||
|
GameObject dontAddMe = null;
|
||||||
|
Renderer r = MB_Utility.GetRenderer(mom.gameObject);
|
||||||
|
if (r != null)
|
||||||
|
{ //make sure that this MeshBaker object is not in list
|
||||||
|
dontAddMe = r.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObject> objsSelectedMatchingFilter = GetFilteredList(addingObjects: false);
|
||||||
|
Debug.Log("Matching filter " + objsSelectedMatchingFilter.Count);
|
||||||
|
List<GameObject> objsToRemove = new List<GameObject>();
|
||||||
|
for (int i = 0; i < objsSelectedMatchingFilter.Count; i++)
|
||||||
|
{
|
||||||
|
if (objsToCombine.Contains(objsSelectedMatchingFilter[i]))
|
||||||
|
{
|
||||||
|
objsToRemove.Add(objsSelectedMatchingFilter[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MBVersionEditor.RegisterUndo(mom, "Remove Objects");
|
||||||
|
for (int i = 0; i < objsToRemove.Count; i++)
|
||||||
|
{
|
||||||
|
objsToCombine.Remove(objsToRemove[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedObject so = new SerializedObject(mom);
|
||||||
|
so.SetIsDifferentCacheDirty();
|
||||||
|
Debug.Log("Removed " + objsToRemove.Count + " objects from " + mom.name);
|
||||||
|
helpBoxString += String.Format("\nRemoved {0} objects from {1}", objsToRemove.Count, mom.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSelectedObjects()
|
||||||
|
{
|
||||||
|
MB3_MeshBakerRoot mom = (MB3_MeshBakerRoot)target;
|
||||||
|
if (mom == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Must select a target MeshBaker or TextureBaker to add objects to");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObject> newMomObjs = GetFilteredList(addingObjects: true);
|
||||||
|
MBVersionEditor.RegisterUndo(mom, "Add Objects");
|
||||||
|
List<GameObject> momObjs = mom.GetObjectsToCombine();
|
||||||
|
int numAdded = 0;
|
||||||
|
int numAlreadyInList = 0;
|
||||||
|
for (int i = 0; i < newMomObjs.Count; i++)
|
||||||
|
{
|
||||||
|
if (!momObjs.Contains(newMomObjs[i]))
|
||||||
|
{
|
||||||
|
momObjs.Add(newMomObjs[i]);
|
||||||
|
numAdded++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numAlreadyInList++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedObject so = new SerializedObject(mom);
|
||||||
|
so.SetIsDifferentCacheDirty();
|
||||||
|
if (numAlreadyInList > 0)
|
||||||
|
{
|
||||||
|
Debug.Log(String.Format("Skipped adding {0} objects to Target because these objects had already been added to this Target. ", numAlreadyInList));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numAdded == 0)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Added 0 objects. Make sure some or all objects are selected in the hierarchy view. Also check the 'Only Static Objects', 'Using Material' and 'Using Shader' settings");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log(string.Format("Added {0} objects to {1}. ", numAdded, mom.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
helpBoxString += String.Format("\nAdded {0} objects to {1}", numAdded, mom.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4caf9fbf2fe59bf479dc70cb752462a6
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerEditorWindowAddObjectsTab.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,875 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB3_MeshBakerEditorWindowAnalyseSceneTab
|
||||||
|
{
|
||||||
|
public struct ResultPagination
|
||||||
|
{
|
||||||
|
public string nameOfNumToShowControl;
|
||||||
|
public bool foldoutIsOpen;
|
||||||
|
public int firstIdxToShow;
|
||||||
|
public int numToShow;
|
||||||
|
public int numToShow_whenEditing;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int NUM_FILTERS = 5;
|
||||||
|
const int DEFAULT_NUM_TO_SHOW = 10;
|
||||||
|
bool writeReportFile = false;
|
||||||
|
bool splitAtlasesSoMeshesFit = false;
|
||||||
|
int atlasSize = MB2_TexturePacker.MAX_ATLAS_SIZE;
|
||||||
|
string generate_AssetsFolder = "";
|
||||||
|
List<List<GameObjectFilterInfo>> sceneAnalysisResults = new List<List<GameObjectFilterInfo>>();
|
||||||
|
ResultPagination[] sceneAnalysisResultsFoldouts = new ResultPagination[0];
|
||||||
|
int[] groupByFilterIdxs = new int[NUM_FILTERS];
|
||||||
|
string[] groupByOptionNames;
|
||||||
|
IGroupByFilter[] groupByOptionFilters;
|
||||||
|
IGroupByFilter[] filters;
|
||||||
|
Vector2 scrollPos2 = Vector2.zero;
|
||||||
|
|
||||||
|
string _controlThatHadFocusLastFrame = "";
|
||||||
|
|
||||||
|
GUIContent gc_atlasSize = new GUIContent("Max Atlas Size", "");
|
||||||
|
GUIContent gc_splitAtlasesSoMeshesFit = new GUIContent("Split Groups If Textures Would Exceed Atlas Size (beta)", "If combining the textures into a single atlas would exceed the maximum atlas size then create multiple atlases. Othersize texture sizes are reduced.");
|
||||||
|
|
||||||
|
public static bool InterfaceFilter(Type typeObj, System.Object criteriaObj)
|
||||||
|
{
|
||||||
|
return typeObj.ToString() == criteriaObj.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void populateGroupByFilters()
|
||||||
|
{
|
||||||
|
string qualifiedInterfaceName = "DigitalOpus.MB.MBEditor.IGroupByFilter";
|
||||||
|
var interfaceFilter = new TypeFilter(InterfaceFilter);
|
||||||
|
List<Type> types = new List<Type>();
|
||||||
|
foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
System.Collections.IEnumerable typesIterator = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
typesIterator = ass.GetTypes();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//Debug.Log("The assembly that I could not read types for was: " + ass.GetName());
|
||||||
|
//suppress error
|
||||||
|
e.Equals(null);
|
||||||
|
}
|
||||||
|
if (typesIterator != null)
|
||||||
|
{
|
||||||
|
foreach (Type ty in ass.GetTypes())
|
||||||
|
{
|
||||||
|
var myInterfaces = ty.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
|
||||||
|
if (myInterfaces.Length > 0)
|
||||||
|
{
|
||||||
|
types.Add(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> filterNames = new List<string>();
|
||||||
|
List<IGroupByFilter> filters = new List<IGroupByFilter>();
|
||||||
|
filterNames.Add("None");
|
||||||
|
filters.Add(null);
|
||||||
|
foreach (Type tt in types)
|
||||||
|
{
|
||||||
|
if (!tt.IsAbstract && !tt.IsInterface)
|
||||||
|
{
|
||||||
|
IGroupByFilter instance = (IGroupByFilter)System.Activator.CreateInstance(tt);
|
||||||
|
filterNames.Add(instance.GetName());
|
||||||
|
filters.Add(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupByOptionNames = filterNames.ToArray();
|
||||||
|
groupByOptionFilters = filters.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawTabAnalyseScene(Rect position)
|
||||||
|
{
|
||||||
|
|
||||||
|
//first time we are displaying collect the filters
|
||||||
|
if (groupByOptionNames == null || groupByOptionNames.Length == 0)
|
||||||
|
{
|
||||||
|
//var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
// .SelectMany(s => s.GetTypes())
|
||||||
|
// .Where(p => type.IsAssignableFrom(p));
|
||||||
|
populateGroupByFilters();
|
||||||
|
|
||||||
|
//set filter initial values
|
||||||
|
for (int i = 0; i < groupByOptionFilters.Length; i++)
|
||||||
|
{
|
||||||
|
if (groupByOptionFilters[i] is GroupByShader)
|
||||||
|
{
|
||||||
|
groupByFilterIdxs[0] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < groupByOptionFilters.Length; i++)
|
||||||
|
{
|
||||||
|
if (groupByOptionFilters[i] is GroupByStatic)
|
||||||
|
{
|
||||||
|
groupByFilterIdxs[1] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < groupByOptionFilters.Length; i++)
|
||||||
|
{
|
||||||
|
if (groupByOptionFilters[i] is GroupByRenderType)
|
||||||
|
{
|
||||||
|
groupByFilterIdxs[2] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < groupByOptionFilters.Length; i++)
|
||||||
|
{
|
||||||
|
if (groupByOptionFilters[i] is GroupByOutOfBoundsUVs)
|
||||||
|
{
|
||||||
|
groupByFilterIdxs[3] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupByFilterIdxs[4] = 0; //none
|
||||||
|
}
|
||||||
|
if (groupByFilterIdxs == null || groupByFilterIdxs.Length < NUM_FILTERS)
|
||||||
|
{
|
||||||
|
groupByFilterIdxs = new int[]{
|
||||||
|
0,0,0,0,0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EditorGUILayout.HelpBox("List shaders in scene prints a report to the console of shaders and which objects use them. This is useful for planning which objects to combine.", UnityEditor.MessageType.None);
|
||||||
|
|
||||||
|
groupByFilterIdxs[0] = EditorGUILayout.Popup("Group By:", groupByFilterIdxs[0], groupByOptionNames);
|
||||||
|
for (int i = 1; i < NUM_FILTERS; i++)
|
||||||
|
{
|
||||||
|
groupByFilterIdxs[i] = EditorGUILayout.Popup("Then Group By:", groupByFilterIdxs[i], groupByOptionNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
float oldLabelWidth = EditorGUIUtility.labelWidth;
|
||||||
|
EditorGUIUtility.labelWidth = 300;
|
||||||
|
splitAtlasesSoMeshesFit = EditorGUILayout.Toggle(gc_splitAtlasesSoMeshesFit, splitAtlasesSoMeshesFit);
|
||||||
|
EditorGUIUtility.labelWidth = oldLabelWidth;
|
||||||
|
bool enableAtlasField = true;
|
||||||
|
if (splitAtlasesSoMeshesFit)
|
||||||
|
{
|
||||||
|
enableAtlasField = false;
|
||||||
|
}
|
||||||
|
EditorGUI.BeginDisabledGroup(enableAtlasField);
|
||||||
|
atlasSize = EditorGUILayout.IntField(gc_atlasSize, atlasSize);
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Select Folder For Combined Material Assets"))
|
||||||
|
{
|
||||||
|
generate_AssetsFolder = EditorUtility.SaveFolderPanel("Create Combined Material Assets In Folder", "", "");
|
||||||
|
generate_AssetsFolder = "Assets" + generate_AssetsFolder.Replace(Application.dataPath, "") + "/";
|
||||||
|
}
|
||||||
|
EditorGUILayout.LabelField("Folder: " + generate_AssetsFolder);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("List Shaders In Scene"))
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", "", .05f);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
listMaterialsInScene();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Bake Every MeshBaker In Scene"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MB3_TextureBaker[] texBakers = (MB3_TextureBaker[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_TextureBaker));
|
||||||
|
for (int i = 0; i < texBakers.Length; i++)
|
||||||
|
{
|
||||||
|
texBakers[i].CreateAtlases(updateProgressBar, true, new MB3_EditorMethods());
|
||||||
|
}
|
||||||
|
MB3_MeshBakerCommon[] mBakers = (MB3_MeshBakerCommon[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_MeshBakerCommon));
|
||||||
|
bool createTempMaterialBakeResult;
|
||||||
|
for (int i = 0; i < mBakers.Length; i++)
|
||||||
|
{
|
||||||
|
if (mBakers[i].textureBakeResults != null)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createTempMaterialBakeResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (sceneAnalysisResults.Count > 0)
|
||||||
|
{
|
||||||
|
float height = position.height - 150f;
|
||||||
|
if (height < 500f) height = 500f;
|
||||||
|
MB_EditorUtil.DrawSeparator();
|
||||||
|
scrollPos2 = EditorGUILayout.BeginScrollView(scrollPos2, false, true); //(scrollPos2,, GUILayout.Width(position.width - 20f), GUILayout.Height(height));
|
||||||
|
EditorGUILayout.LabelField("Shaders In Scene", EditorStyles.boldLabel);
|
||||||
|
GUILayout.Space(15);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
for (int i = 0; i < sceneAnalysisResults.Count; i++)
|
||||||
|
{
|
||||||
|
DrawGroupOfSimilarRenderers(sceneAnalysisResults[i], ref sceneAnalysisResultsFoldouts[i]);
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
MB_EditorUtil.DrawSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Detect if we just finished editing one of the pagination numToShow boxes.
|
||||||
|
int idxThatHadControlLastFrame = -1;
|
||||||
|
int idxThatHasControlThisFrame = -1;
|
||||||
|
for (int i = 0; i < sceneAnalysisResultsFoldouts.Length; i++)
|
||||||
|
{
|
||||||
|
if (sceneAnalysisResultsFoldouts[i].nameOfNumToShowControl.Equals(_controlThatHadFocusLastFrame))
|
||||||
|
{
|
||||||
|
idxThatHadControlLastFrame = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sceneAnalysisResultsFoldouts[i].nameOfNumToShowControl.Equals(GUI.GetNameOfFocusedControl()))
|
||||||
|
{
|
||||||
|
idxThatHasControlThisFrame = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idxThatHadControlLastFrame != -1 &&
|
||||||
|
idxThatHadControlLastFrame != idxThatHasControlThisFrame)
|
||||||
|
{
|
||||||
|
// We just lost focus on a numToShow text box. Update the value.
|
||||||
|
sceneAnalysisResultsFoldouts[idxThatHadControlLastFrame].numToShow_whenEditing = Mathf.Clamp(sceneAnalysisResultsFoldouts[idxThatHadControlLastFrame].numToShow_whenEditing, 1, 300);
|
||||||
|
sceneAnalysisResultsFoldouts[idxThatHadControlLastFrame].numToShow = sceneAnalysisResultsFoldouts[idxThatHadControlLastFrame].numToShow_whenEditing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_controlThatHadFocusLastFrame = GUI.GetNameOfFocusedControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawGroupOfSimilarRenderers(List<GameObjectFilterInfo> gows, ref ResultPagination paginationInfo)
|
||||||
|
{
|
||||||
|
|
||||||
|
string descr = String.Format("Objs={0} AtlasIndex={1} {2}", gows.Count, gows[0].atlasIndex, gows[0].GetDescription(filters, gows[0]));
|
||||||
|
GUI.color = new Color(.5f, 1f, .5f);
|
||||||
|
EditorGUILayout.LabelField(descr, EditorStyles.boldLabel);
|
||||||
|
GUI.color = Color.white;
|
||||||
|
EditorGUI.indentLevel += 1;
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Generate Baker", GUILayout.Width(200)))
|
||||||
|
{
|
||||||
|
createAndSetupBaker(gows, generate_AssetsFolder);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("Select All", GUILayout.Width(200)))
|
||||||
|
{
|
||||||
|
UnityEngine.Object[] selected = new UnityEngine.Object[gows.Count];
|
||||||
|
for (int j = 0; j < gows.Count; j++)
|
||||||
|
{
|
||||||
|
selected[j] = gows[j].go;
|
||||||
|
}
|
||||||
|
Selection.objects = selected;
|
||||||
|
SceneView.lastActiveSceneView.FrameSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
string filterDescription = "Unknown";
|
||||||
|
if (gows.Count > 0)
|
||||||
|
{
|
||||||
|
filterDescription = gows[0].GetDescription(filters, gows[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationInfo.foldoutIsOpen = EditorGUILayout.Foldout(paginationInfo.foldoutIsOpen, filterDescription);
|
||||||
|
if (paginationInfo.foldoutIsOpen)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel += 1;
|
||||||
|
int numPerPage = paginationInfo.numToShow;
|
||||||
|
if (numPerPage < 1) numPerPage = 1;
|
||||||
|
if (numPerPage > 256) numPerPage = 256;
|
||||||
|
|
||||||
|
int firstToDisplay = paginationInfo.firstIdxToShow;
|
||||||
|
if (firstToDisplay >= gows.Count) firstToDisplay = gows.Count - 1;
|
||||||
|
if (firstToDisplay < 0) firstToDisplay = 0;
|
||||||
|
int lastToDisplay = firstToDisplay + numPerPage;
|
||||||
|
if (lastToDisplay > gows.Count) lastToDisplay = gows.Count;
|
||||||
|
|
||||||
|
for (int resIdx = firstToDisplay; resIdx < lastToDisplay; resIdx++)
|
||||||
|
{
|
||||||
|
if (gows[resIdx].go != null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Select", new GUILayoutOption[] { GUILayout.MaxWidth(100) }))
|
||||||
|
{
|
||||||
|
Selection.activeGameObject = gows[resIdx].go;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(gows[resIdx].go.name);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.Label(new GUIContent("Displaying " + (firstToDisplay + 1) + " to " + lastToDisplay + " of " + gows.Count + " num to show:"), GUILayout.ExpandWidth(false));
|
||||||
|
|
||||||
|
GUI.SetNextControlName(paginationInfo.nameOfNumToShowControl);
|
||||||
|
|
||||||
|
if (GUI.GetNameOfFocusedControl().Equals(paginationInfo.nameOfNumToShowControl))
|
||||||
|
{
|
||||||
|
// Use a temporary variable for storing what the user is typing when they are editing a numToShow box
|
||||||
|
// We don't want to change the number of rows we are displaying for every keystroke. Only when they
|
||||||
|
// Leave the text box.
|
||||||
|
paginationInfo.numToShow_whenEditing = EditorGUILayout.IntField(paginationInfo.numToShow_whenEditing, new GUILayoutOption[] { GUILayout.MaxWidth(100) });
|
||||||
|
paginationInfo.numToShow_whenEditing = Mathf.Clamp(paginationInfo.numToShow_whenEditing, 1, 300);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
paginationInfo.numToShow = EditorGUILayout.IntField(paginationInfo.numToShow, new GUILayoutOption[] { GUILayout.MaxWidth(100) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gows.Count > numPerPage)
|
||||||
|
{
|
||||||
|
if (firstToDisplay > 0)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button(" Previous ", GUILayout.MaxWidth(200)))
|
||||||
|
{
|
||||||
|
paginationInfo.firstIdxToShow -= numPerPage;
|
||||||
|
if (paginationInfo.firstIdxToShow < 0) paginationInfo.firstIdxToShow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastToDisplay < gows.Count)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button(" Next ", GUILayout.MaxWidth(200)))
|
||||||
|
{
|
||||||
|
paginationInfo.firstIdxToShow += numPerPage;
|
||||||
|
if (paginationInfo.firstIdxToShow >= gows.Count) paginationInfo.firstIdxToShow = gows.Count - 1;
|
||||||
|
if (paginationInfo.firstIdxToShow < 0) paginationInfo.firstIdxToShow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUI.indentLevel -= 1;
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel -= 1;
|
||||||
|
GUILayout.Space(15);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetLODLevelForRenderer(Renderer r)
|
||||||
|
{
|
||||||
|
if (r != null)
|
||||||
|
{
|
||||||
|
LODGroup lodGroup = r.GetComponentInParent<LODGroup>();
|
||||||
|
if (lodGroup != null)
|
||||||
|
{
|
||||||
|
LOD[] lods = lodGroup.GetLODs();
|
||||||
|
for (int lodIdx = 0; lodIdx < lods.Length; lodIdx++)
|
||||||
|
{
|
||||||
|
Renderer[] rs = lods[lodIdx].renderers;
|
||||||
|
for (int j = 0; j < rs.Length; j++)
|
||||||
|
{
|
||||||
|
if (rs[j] == r)
|
||||||
|
{
|
||||||
|
return lodIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void listMaterialsInScene()
|
||||||
|
{
|
||||||
|
if (!ValidateGroupByFields()) return;
|
||||||
|
if (groupByOptionFilters == null)
|
||||||
|
{
|
||||||
|
populateGroupByFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IGroupByFilter> gbfs = new List<IGroupByFilter>();
|
||||||
|
for (int i = 0; i < groupByFilterIdxs.Length; i++)
|
||||||
|
{
|
||||||
|
if (groupByFilterIdxs[i] != 0)
|
||||||
|
{
|
||||||
|
gbfs.Add(groupByOptionFilters[groupByFilterIdxs[i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filters = gbfs.ToArray();
|
||||||
|
|
||||||
|
//Get All Objects Already In a list of objects to be combined
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", "Finding Existing MeshBakers In Scene", .1f);
|
||||||
|
MB3_MeshBakerRoot[] allBakers = (MB3_MeshBakerRoot[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_MeshBakerRoot));
|
||||||
|
HashSet<GameObject> objectsAlreadyIncludedInBakers = new HashSet<GameObject>();
|
||||||
|
for (int i = 0; i < allBakers.Length; i++)
|
||||||
|
{
|
||||||
|
List<GameObject> objsToCombine = allBakers[i].GetObjectsToCombine();
|
||||||
|
for (int j = 0; j < objsToCombine.Count; j++)
|
||||||
|
{
|
||||||
|
if (objsToCombine[j] != null) objectsAlreadyIncludedInBakers.Add(objsToCombine[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//collect all renderers in scene
|
||||||
|
List<GameObjectFilterInfo> gameObjects = new List<GameObjectFilterInfo>();
|
||||||
|
Renderer[] rs = (Renderer[]) MBVersion.FindSceneObjectsOfType(typeof(Renderer));
|
||||||
|
// Profile.StartProfile("listMaterialsInScene1");
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", "Collecting Renderers", .25f);
|
||||||
|
for (int i = 0; i < rs.Length; i++)
|
||||||
|
{
|
||||||
|
Renderer r = rs[i];
|
||||||
|
if (r is MeshRenderer || r is SkinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
if (r.GetComponent<TextMesh>() != null)
|
||||||
|
{
|
||||||
|
continue; //don't add TextMeshes
|
||||||
|
}
|
||||||
|
GameObjectFilterInfo goaw = new GameObjectFilterInfo(r.gameObject, objectsAlreadyIncludedInBakers, filters);
|
||||||
|
if (goaw.materials.Length > 0) //don't consider renderers with no materials
|
||||||
|
{
|
||||||
|
gameObjects.Add(goaw);
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", "Collecting Renderer For " + r.name, .1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//analyse meshes
|
||||||
|
Dictionary<int, MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = new Dictionary<int, MB_Utility.MeshAnalysisResult>();
|
||||||
|
int totalVerts = 0;
|
||||||
|
for (int i = 0; i < gameObjects.Count; i++)
|
||||||
|
{
|
||||||
|
string rpt = String.Format("Processing {0} [{1} of {2}]", gameObjects[i].go.name, i, gameObjects.Count);
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " A", .6f);
|
||||||
|
Mesh mm = MB_Utility.GetMesh(gameObjects[i].go);
|
||||||
|
int nVerts = 0;
|
||||||
|
if (mm != null)
|
||||||
|
{
|
||||||
|
nVerts += mm.vertexCount;
|
||||||
|
MB_Utility.MeshAnalysisResult mar;
|
||||||
|
if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar))
|
||||||
|
{
|
||||||
|
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f);
|
||||||
|
MB_Utility.hasOutOfBoundsUVs(mm, ref mar);
|
||||||
|
//Rect dummy = mar.uvRect;
|
||||||
|
MB_Utility.doSubmeshesShareVertsOrTris(mm, ref mar);
|
||||||
|
meshAnalysisResultCache.Add(mm.GetInstanceID(), mar);
|
||||||
|
}
|
||||||
|
if (mar.hasOutOfBoundsUVs)
|
||||||
|
{
|
||||||
|
int w = (int)mar.uvRect.width;
|
||||||
|
int h = (int)mar.uvRect.height;
|
||||||
|
gameObjects[i].outOfBoundsUVs = true;
|
||||||
|
gameObjects[i].warning.AppendLine(" [WARNING: has uvs outside the range (0,1) tex is tiled " + w + "x" + h + " times]");
|
||||||
|
}
|
||||||
|
if (mar.hasOverlappingSubmeshVerts)
|
||||||
|
{
|
||||||
|
gameObjects[i].submeshesOverlap = true;
|
||||||
|
gameObjects[i].warning.AppendLine(" [WARNING: Submeshes share verts or triangles. 'Multiple Combined Materials' feature may not work.]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalVerts += nVerts;
|
||||||
|
EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Validate OBuvs Multi Material", .6f);
|
||||||
|
Renderer mr = gameObjects[i].go.GetComponent<Renderer>();
|
||||||
|
if (!MB_Utility.AreAllSharedMaterialsDistinct(mr.sharedMaterials))
|
||||||
|
{
|
||||||
|
gameObjects[i].warning.AppendLine(" [WARNING: Object uses same material on multiple submeshes. This may produce poor results when used with multiple materials or Consider Mesh UVs.]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObjectFilterInfo> objsNotAddedToBaker = new List<GameObjectFilterInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>> gs2bakeGroupMap = sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, splitAtlasesSoMeshesFit, atlasSize);
|
||||||
|
|
||||||
|
sceneAnalysisResults = new List<List<GameObjectFilterInfo>>();
|
||||||
|
foreach (GameObjectFilterInfo gow in gs2bakeGroupMap.Keys)
|
||||||
|
{
|
||||||
|
List<List<GameObjectFilterInfo>> gows = gs2bakeGroupMap[gow];
|
||||||
|
for (int i = 0; i < gows.Count; i++) //if split atlases by what fits in atlas
|
||||||
|
{
|
||||||
|
sceneAnalysisResults.Add(gows[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sceneAnalysisResultsFoldouts = new ResultPagination[sceneAnalysisResults.Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < sceneAnalysisResults.Count; i++)
|
||||||
|
{
|
||||||
|
sceneAnalysisResultsFoldouts[i].nameOfNumToShowControl = "numToShow_" + i;
|
||||||
|
sceneAnalysisResultsFoldouts[i].foldoutIsOpen = true;
|
||||||
|
sceneAnalysisResultsFoldouts[i].numToShow = DEFAULT_NUM_TO_SHOW;
|
||||||
|
sceneAnalysisResultsFoldouts[i].numToShow_whenEditing = DEFAULT_NUM_TO_SHOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeReportFile)
|
||||||
|
{
|
||||||
|
string fileName = Application.dataPath + "/MeshBakerSceneAnalysisReport.txt";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.IO.File.WriteAllText(fileName, generateSceneAnalysisReport(gs2bakeGroupMap, objsNotAddedToBaker));
|
||||||
|
Debug.Log(String.Format("Wrote scene analysis file to '{0}'. This file contains a list of all renderers and the materials/shaders that they use. It is designed to be opened with a spreadsheet.", fileName));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.GetHashCode(); //supress compiler warning
|
||||||
|
Debug.Log("Failed to write file: " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string generateSceneAnalysisReport(Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>> gs2bakeGroupMap, List<GameObjectFilterInfo> objsNotAddedToBaker)
|
||||||
|
{
|
||||||
|
string outStr = "(Click me, if I am too big copy and paste me into a spreadsheet or text editor)\n";// Materials in scene " + shader2GameObjects.Keys.Count + " and the objects that use them:\n";
|
||||||
|
outStr += "\t\tOBJECT NAME\tLIGHTMAP INDEX\tSTATIC\tOVERLAPPING SUBMESHES\tOUT-OF-BOUNDS UVs\tNUM MATS\tMATERIAL\tWARNINGS\n";
|
||||||
|
|
||||||
|
int totalVerts = 0;
|
||||||
|
string outStr2 = "";
|
||||||
|
foreach (List<List<GameObjectFilterInfo>> goss in gs2bakeGroupMap.Values)
|
||||||
|
{
|
||||||
|
for (int atlasIdx = 0; atlasIdx < goss.Count; atlasIdx++)
|
||||||
|
{
|
||||||
|
List<GameObjectFilterInfo> gos = goss[atlasIdx];
|
||||||
|
outStr2 = "";
|
||||||
|
totalVerts = 0;
|
||||||
|
gos.Sort();
|
||||||
|
for (int i = 0; i < gos.Count; i++)
|
||||||
|
{
|
||||||
|
totalVerts += gos[i].numVerts;
|
||||||
|
string matStr = "";
|
||||||
|
Renderer mr = gos[i].go.GetComponent<Renderer>();
|
||||||
|
foreach (Material mmm in mr.sharedMaterials)
|
||||||
|
{
|
||||||
|
matStr += "[" + mmm + "] ";
|
||||||
|
}
|
||||||
|
outStr2 += "\t\t" + gos[i].go.name + " (" + gos[i].numVerts + " verts)\t" + gos[i].lightmapIndex + "\t" + gos[i].isStatic + "\t" + gos[i].submeshesOverlap + "\t" + gos[i].outOfBoundsUVs + "\t" + gos[i].numMaterials + "\t" + matStr + "\t" + gos[i].warning + "\n";
|
||||||
|
}
|
||||||
|
outStr2 = "\t" + gos[0].shaderName + " (" + totalVerts + " verts): \n" + outStr2;
|
||||||
|
outStr += outStr2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (objsNotAddedToBaker.Count > 0)
|
||||||
|
{
|
||||||
|
outStr += "Other objects\n";
|
||||||
|
string shaderName = "";
|
||||||
|
totalVerts = 0;
|
||||||
|
List<GameObjectFilterInfo> gos1 = objsNotAddedToBaker;
|
||||||
|
gos1.Sort();
|
||||||
|
outStr2 = "";
|
||||||
|
for (int i = 0; i < gos1.Count; i++)
|
||||||
|
{
|
||||||
|
if (!shaderName.Equals(objsNotAddedToBaker[i].shaderName))
|
||||||
|
{
|
||||||
|
outStr2 += "\t" + gos1[0].shaderName + "\n";
|
||||||
|
shaderName = objsNotAddedToBaker[i].shaderName;
|
||||||
|
}
|
||||||
|
totalVerts += gos1[i].numVerts;
|
||||||
|
string matStr = "";
|
||||||
|
Renderer mr = gos1[i].go.GetComponent<Renderer>();
|
||||||
|
foreach (Material mmm in mr.sharedMaterials)
|
||||||
|
{
|
||||||
|
matStr += "[" + mmm + "] ";
|
||||||
|
}
|
||||||
|
outStr2 += "\t\t" + gos1[i].go.name + " (" + gos1[i].numVerts + " verts)\t" + gos1[i].lightmapIndex + "\t" + gos1[i].isStatic + "\t" + gos1[i].submeshesOverlap + "\t" + gos1[i].outOfBoundsUVs + "\t" + gos1[i].numMaterials + "\t" + matStr + "\t" + gos1[i].warning + "\n";
|
||||||
|
}
|
||||||
|
outStr += outStr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MaterialsAreTheSame(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
HashSet<Material> aMats = new HashSet<Material>();
|
||||||
|
for (int i = 0; i < a.materials.Length; i++) aMats.Add(a.materials[i]);
|
||||||
|
HashSet<Material> bMats = new HashSet<Material>();
|
||||||
|
for (int i = 0; i < b.materials.Length; i++) bMats.Add(b.materials[i]);
|
||||||
|
return aMats.SetEquals(bMats);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShadersAreTheSame(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
HashSet<Shader> aMats = new HashSet<Shader>();
|
||||||
|
for (int i = 0; i < a.shaders.Length; i++) aMats.Add(a.shaders[i]);
|
||||||
|
HashSet<Shader> bMats = new HashSet<Shader>();
|
||||||
|
for (int i = 0; i < b.shaders.Length; i++) bMats.Add(b.shaders[i]);
|
||||||
|
return aMats.SetEquals(bMats);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>> sortIntoBakeGroups3(List<GameObjectFilterInfo> gameObjects, List<GameObjectFilterInfo> objsNotAddedToBaker, IGroupByFilter[] filters, bool splitAtlasesSoMeshesFit, int atlasSize)
|
||||||
|
{
|
||||||
|
|
||||||
|
Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>> gs2bakeGroupMap = new Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>>();
|
||||||
|
|
||||||
|
List<GameObjectFilterInfo> gos = gameObjects;
|
||||||
|
if (gos.Count < 1) return gs2bakeGroupMap;
|
||||||
|
|
||||||
|
gos.Sort();
|
||||||
|
List<List<GameObjectFilterInfo>> l = null;
|
||||||
|
GameObjectFilterInfo key = gos[0];
|
||||||
|
for (int i = 0; i < gos.Count; i++)
|
||||||
|
{
|
||||||
|
GameObjectFilterInfo goaw = gos[i];
|
||||||
|
//compare with key and decide if we need a new list
|
||||||
|
for (int j = 0; j < filters.Length; j++)
|
||||||
|
{
|
||||||
|
if (filters[j] != null && filters[j].Compare(key, goaw) != 0) l = null;
|
||||||
|
}
|
||||||
|
if (l == null)
|
||||||
|
{
|
||||||
|
l = new List<List<GameObjectFilterInfo>>();
|
||||||
|
l.Add(new List<GameObjectFilterInfo>());
|
||||||
|
gs2bakeGroupMap.Add(gos[i], l);
|
||||||
|
key = gos[i];
|
||||||
|
}
|
||||||
|
l[0].Add(gos[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//now that objects have been grouped by the sort criteria we can see how many atlases are needed
|
||||||
|
Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>> gs2bakeGroupMap2 = new Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>>();
|
||||||
|
if (splitAtlasesSoMeshesFit)
|
||||||
|
{
|
||||||
|
foreach (GameObjectFilterInfo k in gs2bakeGroupMap.Keys)
|
||||||
|
{
|
||||||
|
List<GameObjectFilterInfo> vs = gs2bakeGroupMap[k][0];
|
||||||
|
List<GameObject> objsInGroup = new List<GameObject>();
|
||||||
|
for (int i = 0; i < vs.Count; i++)
|
||||||
|
{
|
||||||
|
objsInGroup.Add(vs[i].go);
|
||||||
|
}
|
||||||
|
MB3_TextureCombiner tc = new MB3_TextureCombiner();
|
||||||
|
tc.maxAtlasSize = atlasSize;
|
||||||
|
tc.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
|
||||||
|
tc.LOG_LEVEL = MB2_LogLevel.warn;
|
||||||
|
List<AtlasPackingResult> packingResults = new List<AtlasPackingResult>();
|
||||||
|
Material tempResMat = k.materials[0]; //we don't write to the materials so can use this as the result material
|
||||||
|
MB_AtlasesAndRects tempAtlasesAndRects = new MB_AtlasesAndRects();
|
||||||
|
if (tc.CombineTexturesIntoAtlases(null, tempAtlasesAndRects, tempResMat, objsInGroup, null, new List<string>(), null, packingResults,
|
||||||
|
onlyPackRects:true, splitAtlasWhenPackingIfTooBig:false))
|
||||||
|
{
|
||||||
|
List<List<GameObjectFilterInfo>> atlasGroups = new List<List<GameObjectFilterInfo>>();
|
||||||
|
for (int i = 0; i < packingResults.Count; i++)
|
||||||
|
{
|
||||||
|
List<GameObjectFilterInfo> ngos = new List<GameObjectFilterInfo>();
|
||||||
|
List<MB_MaterialAndUVRect> matsData = (List<MB_MaterialAndUVRect>)packingResults[i].data;
|
||||||
|
for (int j = 0; j < matsData.Count; j++)
|
||||||
|
{
|
||||||
|
for (int kk = 0; kk < matsData[j].objectsThatUse.Count; kk++)
|
||||||
|
{
|
||||||
|
GameObjectFilterInfo gofi = vs.Find(x => x.go == matsData[j].objectsThatUse[kk]);
|
||||||
|
//Debug.Assert(gofi != null);
|
||||||
|
ngos.Add(gofi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ngos[0].atlasIndex = (short)i;
|
||||||
|
atlasGroups.Add(ngos);
|
||||||
|
}
|
||||||
|
gs2bakeGroupMap2.Add(k, atlasGroups);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gs2bakeGroupMap2.Add(k, gs2bakeGroupMap[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gs2bakeGroupMap2 = gs2bakeGroupMap;
|
||||||
|
}
|
||||||
|
return gs2bakeGroupMap2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createBakers(Dictionary<GameObjectFilterInfo, List<GameObjectFilterInfo>> gs2bakeGroupMap, List<GameObjectFilterInfo> objsNotAddedToBaker)
|
||||||
|
{
|
||||||
|
string s = "";
|
||||||
|
int numBakers = 0;
|
||||||
|
int numObjsAdded = 0;
|
||||||
|
|
||||||
|
if (generate_AssetsFolder == null || generate_AssetsFolder == "")
|
||||||
|
{
|
||||||
|
Debug.LogError("Need to choose a folder for saving the combined material assets.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObjectFilterInfo> singletonObjsNotAddedToBaker = new List<GameObjectFilterInfo>();
|
||||||
|
foreach (List<GameObjectFilterInfo> gaw in gs2bakeGroupMap.Values)
|
||||||
|
{
|
||||||
|
if (gaw.Count > 1)
|
||||||
|
{
|
||||||
|
numBakers++;
|
||||||
|
numObjsAdded += gaw.Count;
|
||||||
|
createAndSetupBaker(gaw, generate_AssetsFolder);
|
||||||
|
s += " Created meshbaker for shader=" + gaw[0].shaderName + " lightmap=" + gaw[0].lightmapIndex + " OBuvs=" + gaw[0].outOfBoundsUVs + "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
singletonObjsNotAddedToBaker.Add(gaw[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = "Created " + numBakers + " bakers. Added " + numObjsAdded + " objects\n" + s;
|
||||||
|
Debug.Log(s);
|
||||||
|
s = "Objects not added=" + objsNotAddedToBaker.Count + " objects that have unique material=" + singletonObjsNotAddedToBaker.Count + "\n";
|
||||||
|
for (int i = 0; i < objsNotAddedToBaker.Count; i++)
|
||||||
|
{
|
||||||
|
s += " " + objsNotAddedToBaker[i].go.name +
|
||||||
|
" isStatic=" + objsNotAddedToBaker[i].isStatic +
|
||||||
|
" submeshesOverlap" + objsNotAddedToBaker[i].submeshesOverlap +
|
||||||
|
" numMats=" + objsNotAddedToBaker[i].numMaterials + "\n";
|
||||||
|
}
|
||||||
|
for (int i = 0; i < singletonObjsNotAddedToBaker.Count; i++)
|
||||||
|
{
|
||||||
|
s += " " + singletonObjsNotAddedToBaker[i].go.name + " single\n";
|
||||||
|
}
|
||||||
|
Debug.Log(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createAndSetupBaker(List<GameObjectFilterInfo> gaws, string pthRoot)
|
||||||
|
{
|
||||||
|
for (int i = gaws.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (gaws[i].go == null) gaws.RemoveAt(i);
|
||||||
|
}
|
||||||
|
if (gaws.Count < 1)
|
||||||
|
{
|
||||||
|
Debug.LogError("No game objects.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthRoot == null || pthRoot == "")
|
||||||
|
{
|
||||||
|
Debug.LogError("Folder for saving created assets was not set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numVerts = 0;
|
||||||
|
for (int i = 0; i < gaws.Count; i++)
|
||||||
|
{
|
||||||
|
if (gaws[i].go != null)
|
||||||
|
{
|
||||||
|
numVerts = gaws[i].numVerts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject newMeshBaker = null;
|
||||||
|
if (numVerts >= 65535)
|
||||||
|
{
|
||||||
|
newMeshBaker = MB3_MultiMeshBakerEditor.CreateNewMeshBaker();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newMeshBaker = MB3_MeshBakerEditor.CreateNewMeshBaker();
|
||||||
|
}
|
||||||
|
|
||||||
|
newMeshBaker.name = ("MeshBaker-" + gaws[0].shaderName + "-LM" + gaws[0].lightmapIndex).ToString().Replace("/", "-");
|
||||||
|
|
||||||
|
MB3_TextureBaker tb = newMeshBaker.GetComponent<MB3_TextureBaker>();
|
||||||
|
MB3_MeshBakerCommon mb = tb.GetComponentInChildren<MB3_MeshBakerCommon>();
|
||||||
|
|
||||||
|
tb.GetObjectsToCombine().Clear();
|
||||||
|
for (int i = 0; i < gaws.Count; i++)
|
||||||
|
{
|
||||||
|
if (gaws[i].go != null && !tb.GetObjectsToCombine().Contains(gaws[i].go))
|
||||||
|
{
|
||||||
|
tb.GetObjectsToCombine().Add(gaws[i].go);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitAtlasesSoMeshesFit)
|
||||||
|
{
|
||||||
|
tb.maxAtlasSize = atlasSize;
|
||||||
|
}
|
||||||
|
if (gaws[0].numMaterials > 1)
|
||||||
|
{
|
||||||
|
string pthMat = AssetDatabase.GenerateUniqueAssetPath(pthRoot + newMeshBaker.name + ".asset");
|
||||||
|
MB3_TextureBakerEditorInternal.CreateCombinedMaterialAssets(tb, pthMat);
|
||||||
|
tb.doMultiMaterial = true;
|
||||||
|
SerializedObject tbr = new SerializedObject(tb);
|
||||||
|
SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials");
|
||||||
|
MB_TextureBakerEditorConfigureMultiMaterials.ConfigureMutiMaterialsFromObjsToCombine2(tb, resultMaterials, tbr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string pthMat = AssetDatabase.GenerateUniqueAssetPath(pthRoot + newMeshBaker.name + ".asset");
|
||||||
|
MB3_TextureBakerEditorInternal.CreateCombinedMaterialAssets(tb, pthMat);
|
||||||
|
}
|
||||||
|
if (gaws[0].isMeshRenderer)
|
||||||
|
{
|
||||||
|
mb.meshCombiner.settings.renderType = MB_RenderType.meshRenderer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mb.meshCombiner.settings.renderType = MB_RenderType.skinnedMeshRenderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bakeAllBakersInScene()
|
||||||
|
{
|
||||||
|
MB3_MeshBakerRoot[] bakers = (MB3_MeshBakerRoot[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_MeshBakerRoot));
|
||||||
|
for (int i = 0; i < bakers.Length; i++)
|
||||||
|
{
|
||||||
|
if (bakers[i] is MB3_TextureBaker)
|
||||||
|
{
|
||||||
|
MB3_TextureBaker tb = (MB3_TextureBaker)bakers[i];
|
||||||
|
tb.CreateAtlases(updateProgressBar, true, new MB3_EditorMethods());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateProgressBar(string msg, float progress)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayProgressBar("Combining Meshes", msg, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValidateGroupByFields()
|
||||||
|
{
|
||||||
|
bool foundNone = false;
|
||||||
|
for (int i = 0; i < groupByFilterIdxs.Length; i++)
|
||||||
|
{
|
||||||
|
if (groupByFilterIdxs[i] == 0) foundNone = true; //zero is the none selection
|
||||||
|
if (foundNone && groupByFilterIdxs[i] != 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("All non-none values must be at the top of the group by list");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < groupByFilterIdxs.Length; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < groupByFilterIdxs.Length; j++)
|
||||||
|
{
|
||||||
|
if (groupByFilterIdxs[i] == groupByFilterIdxs[j] && groupByFilterIdxs[i] != 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("Two of the group by options are the same.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b4dede5205ae9b44dbe7a898ae2d1e53
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerEditorWindowAnalyseSceneTab.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,553 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
[CustomEditor(typeof(MB3_MeshBakerGrouper))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class MB3_MeshBakerGrouperEditor : Editor
|
||||||
|
{
|
||||||
|
|
||||||
|
long lastBoundsCheckRefreshTime = 0;
|
||||||
|
|
||||||
|
static GUIContent gc_ClusterType = new GUIContent("Cluster Type", "The scene will be divided into cells. Meshes in each cell will be grouped into a single mesh baker");
|
||||||
|
static GUIContent gc_GridOrigin = new GUIContent("Origin", "The scene will be divided into cells. Meshes in each cell will be grouped into a single baker. This sets the origin for the clustering.");
|
||||||
|
static GUIContent gc_CellSize = new GUIContent("Cell Size", "The scene will be divided into a grid of cells. Meshes in each cell will be grouped into a single baker. This sets the size of the cells.");
|
||||||
|
static GUIContent gc_ClusterOnLMIndex = new GUIContent("Group By Lightmap Index", "Meshes sharing a lightmap index will be grouped together.");
|
||||||
|
static GUIContent gc_NumSegements = new GUIContent("Num Pie Segments", "Number of segments/slices in the pie.");
|
||||||
|
static GUIContent gc_PieAxis = new GUIContent("Pie Axis", "Scene will be divided into segments about this axis.");
|
||||||
|
static GUIContent gc_ClusterByLODLevel = new GUIContent("Cluster By LOD Level", "A baker will be created for each LOD level.");
|
||||||
|
static GUIContent gc_ClusterDistance = new GUIContent("Max Distance", "Source meshes closer than this value will be grouped into clusters.");
|
||||||
|
static GUIContent gc_IncludeCellsWithOnlyOneRenderer = new GUIContent("Include Cells With Only One Renderer", "There is no benefit in combining meshes with only one mesh except to adjust UVs to share an atlas.");
|
||||||
|
static GUIContent gc_Settings = new GUIContent("Use Shared Settings Asset", "Different bakers can share the same settings. If this field is None, then the settings below will be used.");
|
||||||
|
static GUIContent gc_PieRingSpacing = new GUIContent("Ring Spacing", "Pie segments will be divided into rings.");
|
||||||
|
static GUIContent gc_PieCombineAllInCenterRing = new GUIContent("Combine Center Ring Segments Together", "All segments in the centermost ring will be merged into a single segment.");
|
||||||
|
static GUIContent gc_ParentSceneObject = new GUIContent("Parent Scene Object","Must be a scene GameObject. Generated combined meshes will be children of this GameObject.");
|
||||||
|
static GUIContent gc_prefabOptions_outputFolder = new GUIContent("Prefab Output Folder", "Prefabs will be saved to this output folder.");
|
||||||
|
static GUIContent gc_prefabOptions_autoGeneratePrefabs = new GUIContent("Auto Generate Prefabs", "Configure each generated baker to use 'Bake Into Prefab' and generate a prefab in the output folder for the baker.");
|
||||||
|
static GUIContent gc_ButtonGenerateMeshBakers = new GUIContent("Generate Mesh Bakers", "Organize a TextureBakers objects to be combined into groups and generate a MeshBaker child for each group.");
|
||||||
|
static GUIContent gc_ButtonBakeAllChildMeshBakers = new GUIContent("Bake All Child MeshBakers", "Bake All Child MeshBakers of this object");
|
||||||
|
static GUIContent gc_ButtonDeleteAllChildMeshBakers = new GUIContent("Delete All Child Mesh Bakers & Combined Meshes", "Delete All Child Mesh Bakers & Combined Meshes");
|
||||||
|
|
||||||
|
private SerializedObject grouper;
|
||||||
|
private SerializedProperty clusterType, gridOrigin, cellSize, clusterOnLMIndex, numSegments, pieAxis, clusterByLODLevel,
|
||||||
|
clusterDistance, includeCellsWithOnlyOneRenderer, mbSettings, mbSettingsAsset, pieRingSpacing, pieCombineAllInCenterRing,
|
||||||
|
prefabOptions_outputFolder, prefabOptions_autoGeneratePrefabs, parentSceneObject;
|
||||||
|
|
||||||
|
private MB_MeshBakerSettingsEditor meshBakerSettingsMe;
|
||||||
|
private MB_MeshBakerSettingsEditor meshBakerSettingsExternal;
|
||||||
|
|
||||||
|
public void OnEnable()
|
||||||
|
{
|
||||||
|
lastBoundsCheckRefreshTime = 0;
|
||||||
|
this.grouper = serializedObject;
|
||||||
|
|
||||||
|
SerializedProperty d = grouper.FindProperty("data");
|
||||||
|
|
||||||
|
clusterType = grouper.FindProperty("clusterType");
|
||||||
|
includeCellsWithOnlyOneRenderer = d.FindPropertyRelative("includeCellsWithOnlyOneRenderer");
|
||||||
|
gridOrigin = d.FindPropertyRelative("origin");
|
||||||
|
cellSize = d.FindPropertyRelative("cellSize");
|
||||||
|
clusterOnLMIndex = d.FindPropertyRelative("clusterOnLMIndex");
|
||||||
|
clusterByLODLevel = d.FindPropertyRelative("clusterByLODLevel");
|
||||||
|
numSegments = d.FindPropertyRelative("pieNumSegments");
|
||||||
|
pieAxis = d.FindPropertyRelative("pieAxis");
|
||||||
|
clusterDistance = d.FindPropertyRelative("maxDistBetweenClusters");
|
||||||
|
mbSettings = grouper.FindProperty("meshBakerSettings");
|
||||||
|
mbSettingsAsset = grouper.FindProperty("meshBakerSettingsAsset");
|
||||||
|
pieRingSpacing = d.FindPropertyRelative("ringSpacing");
|
||||||
|
pieCombineAllInCenterRing = d.FindPropertyRelative("combineSegmentsInInnermostRing");
|
||||||
|
|
||||||
|
parentSceneObject = grouper.FindProperty("parentSceneObject");
|
||||||
|
prefabOptions_outputFolder = grouper.FindProperty("prefabOptions_outputFolder");
|
||||||
|
prefabOptions_autoGeneratePrefabs = grouper.FindProperty("prefabOptions_autoGeneratePrefabs");
|
||||||
|
|
||||||
|
meshBakerSettingsMe = new MB_MeshBakerSettingsEditor();
|
||||||
|
meshBakerSettingsMe.OnEnable(mbSettings);
|
||||||
|
if (mbSettingsAsset.objectReferenceValue != null)
|
||||||
|
{
|
||||||
|
meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
|
||||||
|
UnityEngine.Object targetObj;
|
||||||
|
string propertyName;
|
||||||
|
((MB3_MeshCombinerSettings)mbSettingsAsset.objectReferenceValue).GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
|
||||||
|
SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
|
||||||
|
meshBakerSettingsExternal.OnEnable(meshBakerSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
if (meshBakerSettingsMe != null) meshBakerSettingsMe.OnDisable();
|
||||||
|
if (meshBakerSettingsExternal != null) meshBakerSettingsExternal.OnDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
grouper.Update();
|
||||||
|
DrawGrouperInspector();
|
||||||
|
if (GUILayout.Button(gc_ButtonGenerateMeshBakers))
|
||||||
|
{
|
||||||
|
for(int tIdx = 0; tIdx < targets.Length; tIdx++)
|
||||||
|
{
|
||||||
|
GenerateMeshBakersEditor(targets[tIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button(gc_ButtonBakeAllChildMeshBakers))
|
||||||
|
{
|
||||||
|
for (int tIdx = 0; tIdx < targets.Length; tIdx++)
|
||||||
|
{
|
||||||
|
_bakeAllChildMeshBakers(targets[tIdx], ref grouper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string buttonTextEnableRenderers = "Disable Renderers On All Child MeshBaker Source Objects";
|
||||||
|
bool enableRenderers = false;
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
|
||||||
|
MB3_MeshBakerCommon bc = tbg.GetComponentInChildren<MB3_MeshBakerCommon>();
|
||||||
|
if (bc != null && bc.GetObjectsToCombine().Count > 0)
|
||||||
|
{
|
||||||
|
GameObject go = bc.GetObjectsToCombine()[0];
|
||||||
|
if (go != null && go.GetComponent<Renderer>() != null && go.GetComponent<Renderer>().enabled == false)
|
||||||
|
{
|
||||||
|
buttonTextEnableRenderers = "Enable Renderers On All Child MeshBaker Source Objects";
|
||||||
|
enableRenderers = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button(buttonTextEnableRenderers))
|
||||||
|
{
|
||||||
|
for (int tIdx = 0; tIdx < targets.Length; tIdx++)
|
||||||
|
{
|
||||||
|
EnableDisableRenderersEditor(targets[tIdx], enableRenderers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button(gc_ButtonDeleteAllChildMeshBakers))
|
||||||
|
{
|
||||||
|
if (EditorUtility.DisplayDialog("Delete Mesh Bakers", "Delete All Child Mesh Bakers?", "OK", "Cancel"))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < targets.Length; i++)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)targets[i];
|
||||||
|
tbg.DeleteAllChildMeshBakers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (DateTime.UtcNow.Ticks - lastBoundsCheckRefreshTime > 10000000)
|
||||||
|
{
|
||||||
|
MB3_TextureBaker tb = ((MB3_MeshBakerGrouper)target).GetComponent<MB3_TextureBaker>();
|
||||||
|
if (tb != null)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
|
||||||
|
List<GameObject> gos = tb.GetObjectsToCombine();
|
||||||
|
Bounds b = new Bounds(Vector3.zero, Vector3.one);
|
||||||
|
if (gos.Count > 0 && gos[0] != null && gos[0].GetComponent<Renderer>() != null)
|
||||||
|
{
|
||||||
|
b = gos[0].GetComponent<Renderer>().bounds;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < gos.Count; i++)
|
||||||
|
{
|
||||||
|
if (gos[i] != null && gos[i].GetComponent<Renderer>() != null)
|
||||||
|
{
|
||||||
|
b.Encapsulate(gos[i].GetComponent<Renderer>().bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbg.sourceObjectBounds = b;
|
||||||
|
lastBoundsCheckRefreshTime = DateTime.UtcNow.Ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grouper.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawGrouperInspector()
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("This component groups meshes that are close together so they can be combined." +
|
||||||
|
" It generates multiple MB3_MeshBaker objects from the list of Objects To Be Combined in the MB3_TextureBaker component." +
|
||||||
|
" Objects that are close together will be grouped together and added to a new child MB3_MeshBaker object.\n\n" +
|
||||||
|
" TIP: Try the new agglomerative cluster type!", MessageType.Info);
|
||||||
|
|
||||||
|
if (targets.Length > 1 && clusterType.intValue == (int)MB3_MeshBakerGrouper.ClusterType.agglomerative)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Multi-Object Editing not supported for Agglomerative cluster type." +
|
||||||
|
" Behaviour will be unpredictable.", MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform pgo = (Transform)EditorGUILayout.ObjectField(gc_ParentSceneObject, parentSceneObject.objectReferenceValue, typeof(Transform), true);
|
||||||
|
if (pgo != null && MB_Utility.IsSceneInstance(pgo.gameObject))
|
||||||
|
{
|
||||||
|
parentSceneObject.objectReferenceValue = pgo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentSceneObject.objectReferenceValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
EditorGUILayout.PropertyField(clusterType, gc_ClusterType);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper.ClusterType newClusterType = (MB3_MeshBakerGrouper.ClusterType)clusterType.intValue;
|
||||||
|
foreach (UnityEngine.Object selObj in targets)
|
||||||
|
{
|
||||||
|
if (selObj is MB3_MeshBakerGrouper)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper selectedGrouper = (MB3_MeshBakerGrouper)selObj;
|
||||||
|
if (selectedGrouper.clusterType != newClusterType
|
||||||
|
|| selectedGrouper.grouper == null
|
||||||
|
|| selectedGrouper.grouper.GetClusterType() != newClusterType)
|
||||||
|
{
|
||||||
|
Undo.RecordObject(selectedGrouper, "Cluster Type Changed");
|
||||||
|
selectedGrouper.CreateGrouper(newClusterType);
|
||||||
|
selectedGrouper.clusterType = newClusterType;
|
||||||
|
EditorUtility.SetDirty(selectedGrouper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawing clusterType specific fields
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
|
||||||
|
|
||||||
|
MB3_TextureBaker tb = tbg.GetComponent<MB3_TextureBaker>();
|
||||||
|
|
||||||
|
// Confusion warning (don't use clusterType.enumValueIndex. It is the index in the list of display names. NOT the enum value)
|
||||||
|
if (clusterType.intValue == (int)MB3_MeshBakerGrouper.ClusterType.grid)
|
||||||
|
{
|
||||||
|
if (!(tbg.grouper is MB3_MeshBakerGrouperGrid))
|
||||||
|
{
|
||||||
|
tbg.CreateGrouper((MB3_MeshBakerGrouper.ClusterType)clusterType.intValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(gridOrigin, gc_GridOrigin);
|
||||||
|
EditorGUILayout.PropertyField(cellSize, gc_CellSize);
|
||||||
|
}
|
||||||
|
else if (clusterType.intValue == (int)MB3_MeshBakerGrouper.ClusterType.pie)
|
||||||
|
{
|
||||||
|
if (!(tbg.grouper is MB3_MeshBakerGrouperPie))
|
||||||
|
{
|
||||||
|
tbg.CreateGrouper((MB3_MeshBakerGrouper.ClusterType)clusterType.intValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(gridOrigin, gc_GridOrigin);
|
||||||
|
EditorGUILayout.PropertyField(numSegments, gc_NumSegements);
|
||||||
|
EditorGUILayout.PropertyField(pieAxis, gc_PieAxis);
|
||||||
|
EditorGUILayout.PropertyField(pieRingSpacing, gc_PieRingSpacing);
|
||||||
|
EditorGUILayout.PropertyField(pieCombineAllInCenterRing, gc_PieCombineAllInCenterRing);
|
||||||
|
}
|
||||||
|
else if (clusterType.intValue == (int)MB3_MeshBakerGrouper.ClusterType.agglomerative)
|
||||||
|
{
|
||||||
|
float dist = clusterDistance.floatValue;
|
||||||
|
float unModifiedDist = dist;
|
||||||
|
float maxDist = 100f;
|
||||||
|
float minDist = .000001f;
|
||||||
|
MB3_MeshBakerGrouperCluster cl = null;
|
||||||
|
if (tbg.grouper is MB3_MeshBakerGrouperCluster)
|
||||||
|
{
|
||||||
|
cl = (MB3_MeshBakerGrouperCluster)tbg.grouper;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tbg.CreateGrouper((MB3_MeshBakerGrouper.ClusterType)clusterType.intValue);
|
||||||
|
cl = (MB3_MeshBakerGrouperCluster)tbg.grouper;
|
||||||
|
}
|
||||||
|
if (tbg.data._lastMaxDistBetweenClusters != tbg.data.maxDistBetweenClusters)
|
||||||
|
{
|
||||||
|
float s, l;
|
||||||
|
((MB3_MeshBakerGrouperCluster)tbg.grouper)._BuildListOfClustersToDraw(null, out s, out l, tbg.data);
|
||||||
|
tbg.data._lastMaxDistBetweenClusters = tbg.data.maxDistBetweenClusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxDist = tbg.data._ObjsExtents;
|
||||||
|
minDist = tbg.data._minDistBetweenClusters;
|
||||||
|
if (dist < minDist || dist > maxDist)
|
||||||
|
{
|
||||||
|
dist = Mathf.Lerp(minDist, maxDist, .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
dist = EditorGUILayout.Slider(gc_ClusterDistance, dist, minDist, maxDist);
|
||||||
|
if (dist != unModifiedDist)
|
||||||
|
{
|
||||||
|
clusterDistance.floatValue = dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
string btnName = "Refresh Clusters";
|
||||||
|
if (tbg.data.cluster == null || tbg.data.cluster.clusters == null || tbg.data.cluster.clusters.Length == 0)
|
||||||
|
{
|
||||||
|
btnName = "Click To Build Clusters";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button(btnName))
|
||||||
|
{
|
||||||
|
if (tbg.grouper is MB3_MeshBakerGrouperCluster)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouperCluster cg = (MB3_MeshBakerGrouperCluster)tbg.grouper;
|
||||||
|
if (tb != null)
|
||||||
|
{
|
||||||
|
cg.BuildClusters(tb.GetObjectsToCombine(), updateProgressBar, tbg.data);
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
Repaint();
|
||||||
|
SceneView.RepaintAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (clusterType.intValue == (int)MB3_MeshBakerGrouper.ClusterType.none)
|
||||||
|
{
|
||||||
|
if (!(tbg.grouper is MB3_MeshBakerGrouperPie))
|
||||||
|
{
|
||||||
|
tbg.CreateGrouper((MB3_MeshBakerGrouper.ClusterType)clusterType.intValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(clusterOnLMIndex, gc_ClusterOnLMIndex);
|
||||||
|
EditorGUILayout.PropertyField(clusterByLODLevel, gc_ClusterByLODLevel);
|
||||||
|
EditorGUILayout.PropertyField(includeCellsWithOnlyOneRenderer, gc_IncludeCellsWithOnlyOneRenderer);
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.LabelField("Prefab Output Settings", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.PropertyField(prefabOptions_autoGeneratePrefabs, gc_prefabOptions_autoGeneratePrefabs);
|
||||||
|
|
||||||
|
{
|
||||||
|
EditorGUI.BeginDisabledGroup(!prefabOptions_autoGeneratePrefabs.boolValue);
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(prefabOptions_outputFolder, gc_prefabOptions_outputFolder);
|
||||||
|
bool pathIsValid;
|
||||||
|
string errorMessage;
|
||||||
|
{
|
||||||
|
string path = prefabOptions_outputFolder.stringValue;
|
||||||
|
prefabOptions_outputFolder.stringValue =
|
||||||
|
MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(path, out errorMessage, out pathIsValid);
|
||||||
|
Debug.Assert(errorMessage != null, "ErrorMessage should never be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Browse"))
|
||||||
|
{
|
||||||
|
string path = EditorUtility.OpenFolderPanel("Browse For Output Folder", "", "");
|
||||||
|
path = MB_BatchPrefabBakerEditorFunctionsCore.ConvertFullPathToProjectRelativePath(path);
|
||||||
|
prefabOptions_outputFolder.stringValue = path;
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (prefabOptions_autoGeneratePrefabs.boolValue &&
|
||||||
|
!pathIsValid)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
|
||||||
|
}
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.LabelField("Mesh Baker Settings", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.HelpBox("These settings will be shared by all created child MeshBaker components.", MessageType.Info);
|
||||||
|
|
||||||
|
UnityEngine.Object oldObjVal = mbSettingsAsset.objectReferenceValue;
|
||||||
|
EditorGUILayout.PropertyField(mbSettingsAsset, gc_Settings);
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
|
||||||
|
|
||||||
|
MB3_TextureBaker tb = tbg.GetComponent<MB3_TextureBaker>();
|
||||||
|
|
||||||
|
bool doingTextureArrays = false;
|
||||||
|
if (tb != null && tb.textureBakeResults != null)
|
||||||
|
doingTextureArrays = tb.textureBakeResults.resultType == MB2_TextureBakeResults.ResultType.textureArray;
|
||||||
|
if (mbSettingsAsset.objectReferenceValue == null)
|
||||||
|
{
|
||||||
|
meshBakerSettingsMe.DrawGUI(tbg.meshBakerSettings, true, doingTextureArrays);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (meshBakerSettingsExternal == null || oldObjVal != mbSettingsAsset.objectReferenceValue)
|
||||||
|
{
|
||||||
|
if (meshBakerSettingsExternal == null)
|
||||||
|
meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
|
||||||
|
UnityEngine.Object targetObj;
|
||||||
|
string propertyName;
|
||||||
|
((MB3_MeshCombinerSettings)mbSettingsAsset.objectReferenceValue).GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
|
||||||
|
SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
|
||||||
|
meshBakerSettingsExternal.OnEnable(meshBakerSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
meshBakerSettingsExternal.DrawGUI(
|
||||||
|
((MB3_MeshCombinerSettings)mbSettingsAsset.objectReferenceValue).data, false, doingTextureArrays);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Organize a TextureBakers objects to be combined into groups and generate a MeshBaker child for each group.
|
||||||
|
/// </summary>
|
||||||
|
public static void GenerateMeshBakersEditor(UnityEngine.Object currTarget)
|
||||||
|
{
|
||||||
|
if (currTarget is MB3_MeshBakerGrouper)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper mbg = (MB3_MeshBakerGrouper)currTarget;
|
||||||
|
{
|
||||||
|
bool proceed = true;
|
||||||
|
if (mbg.prefabOptions_autoGeneratePrefabs)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
string errorMessage;
|
||||||
|
bool pathIsValid;
|
||||||
|
mbg.prefabOptions_outputFolder =
|
||||||
|
MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(
|
||||||
|
mbg.prefabOptions_outputFolder, out errorMessage, out pathIsValid);
|
||||||
|
if (!pathIsValid)
|
||||||
|
{
|
||||||
|
Debug.LogError(errorMessage);
|
||||||
|
Debug.LogError("If " + gc_prefabOptions_autoGeneratePrefabs.text + " is enabled, you must provide an output folder. Prefabs will be saved in this folder.");
|
||||||
|
proceed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proceed)
|
||||||
|
{
|
||||||
|
List<MB3_MeshBakerCommon> newBakers = mbg.GenerateMeshBakers();
|
||||||
|
if (newBakers.Count > 0) DoGeneratePrefabsIfNecessary(mbg, newBakers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Argument must be of type MeshBakerGrouper to use this function");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DoGeneratePrefabsIfNecessary(MB3_MeshBakerGrouper grouper, List<MB3_MeshBakerCommon> newBakers)
|
||||||
|
{
|
||||||
|
if (!grouper.prefabOptions_autoGeneratePrefabs &&
|
||||||
|
!grouper.prefabOptions_mergeOutputIntoSinglePrefab) return;
|
||||||
|
{
|
||||||
|
string errorMessage;
|
||||||
|
bool pathIsValid;
|
||||||
|
grouper.prefabOptions_outputFolder =
|
||||||
|
MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(
|
||||||
|
grouper.prefabOptions_outputFolder, out errorMessage, out pathIsValid);
|
||||||
|
if (!pathIsValid)
|
||||||
|
{
|
||||||
|
Debug.LogError(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grouper.prefabOptions_autoGeneratePrefabs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < newBakers.Count; i++)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerCommon baker = newBakers[i];
|
||||||
|
string path = grouper.prefabOptions_outputFolder;
|
||||||
|
|
||||||
|
// Generate a new prefab name
|
||||||
|
string prefabName = baker.name.Replace("MeshBaker", "CombinedMesh");
|
||||||
|
prefabName = prefabName.Replace(" ", "_");
|
||||||
|
prefabName = prefabName.Replace(",", "_");
|
||||||
|
prefabName = prefabName.Trim(Path.GetInvalidFileNameChars());
|
||||||
|
prefabName = prefabName.Trim(Path.GetInvalidPathChars());
|
||||||
|
|
||||||
|
string pathName = AssetDatabase.GenerateUniqueAssetPath(path + "/" + prefabName + ".prefab");
|
||||||
|
if (pathName == null || pathName.Length == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("Could not generate prefab " + prefabName + " in folder " + path + ". There is something wrong with the path or prefab name.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a new prefab
|
||||||
|
GameObject go = new GameObject(baker.name);
|
||||||
|
GameObject pf = MBVersionEditor.PrefabUtility_CreatePrefab(pathName, go);
|
||||||
|
|
||||||
|
// Configure the baker to bake into the prefab
|
||||||
|
baker.resultPrefab = pf;
|
||||||
|
baker.resultPrefabLeaveInstanceInSceneAfterBake = true;
|
||||||
|
baker.meshCombiner.outputOption = MB2_OutputOptions.bakeIntoPrefab;
|
||||||
|
|
||||||
|
MB_Utility.Destroy(go);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void _bakeAllChildMeshBakers(UnityEngine.Object target, ref SerializedObject grouper)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Transform parent = tbg.parentSceneObject;
|
||||||
|
MB3_MeshBakerCommon[] mBakers = tbg.GetComponentsInChildren<MB3_MeshBakerCommon>();
|
||||||
|
for (int i = 0; i < mBakers.Length; i++)
|
||||||
|
{
|
||||||
|
bool createdDummyMaterialBakeResult;
|
||||||
|
if (parent != null)
|
||||||
|
{
|
||||||
|
mBakers[i].parentSceneObject = parent;
|
||||||
|
}
|
||||||
|
if (grouper.targetObject == tbg)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createdDummyMaterialBakeResult, ref grouper);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createdDummyMaterialBakeResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables/Disables the renderers on the source objects
|
||||||
|
/// </summary>
|
||||||
|
public static void EnableDisableRenderersEditor(UnityEngine.Object target, bool enableRenderers)
|
||||||
|
{
|
||||||
|
MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MB3_MeshBakerCommon[] mBakers = tbg.GetComponentsInChildren<MB3_MeshBakerCommon>();
|
||||||
|
for (int i = 0; i < mBakers.Length; i++)
|
||||||
|
{
|
||||||
|
mBakers[i].EnableDisableSourceObjectRenderers(enableRenderers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool updateProgressBar(string msg, float progress)
|
||||||
|
{
|
||||||
|
//EditorUtility.DisplayProgressBar("Creating Clusters", msg, progress);
|
||||||
|
return EditorUtility.DisplayCancelableProgressBar("Creating Clusters", msg, progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8627c7a515355354798d5990a965619e
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerGrouperEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(MB3_MeshCombinerSettings))]
|
||||||
|
public class MB3_MeshBakerSettingsAssetEditor : Editor
|
||||||
|
{
|
||||||
|
|
||||||
|
private SerializedObject settingsSerializedObj;
|
||||||
|
private SerializedProperty mbSettings;
|
||||||
|
private MB_MeshBakerSettingsEditor meshBakerSettingsEditor;
|
||||||
|
|
||||||
|
public void OnEnable()
|
||||||
|
{
|
||||||
|
settingsSerializedObj = new SerializedObject(target);
|
||||||
|
mbSettings = settingsSerializedObj.FindProperty("data");
|
||||||
|
meshBakerSettingsEditor = new MB_MeshBakerSettingsEditor();
|
||||||
|
meshBakerSettingsEditor.OnEnable(mbSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
MB3_MeshCombinerSettings tbg = (MB3_MeshCombinerSettings)target;
|
||||||
|
settingsSerializedObj.Update();
|
||||||
|
EditorGUILayout.HelpBox("This asset can be shared by many Mesh Bakers and MultiMeshBakers. Drag this " +
|
||||||
|
" asset to the 'Use Shared Settings' field of any Mesh Baker", MessageType.Info);
|
||||||
|
meshBakerSettingsEditor.DrawGUI(tbg.data, true, false);
|
||||||
|
settingsSerializedObj.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b79b3cba502aa134ca22cc156985b07e
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerSettingsAssetEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MB_MeshBakerSettingsEditor
|
||||||
|
{
|
||||||
|
private static GUIContent
|
||||||
|
gc_renderTypeGUIContent = new GUIContent("Renderer", "The type of renderer to add to the combined mesh."),
|
||||||
|
gc_lightmappingOptionGUIContent = new GUIContent("Lightmapping UVs", "preserve current lightmapping: Use this if all source objects are lightmapped and you want to preserve it. All source objects must use the same lightmap.\n\n" +
|
||||||
|
"generate new UV Layout: Use this if you want to bake a lightmap after the combined mesh has been generated\n\n" +
|
||||||
|
"copy UV2 unchanged: Use this if UV2 is being used for something other than lightmaping.\n\n" +
|
||||||
|
"ignore UV2: A UV2 channel will not be generated for the combined mesh\n\n" +
|
||||||
|
"copy UV2 unchanged to separate rects: Use this if your meshes include a custom lightmap that you want to use with the combined mesh.\n\n"),
|
||||||
|
gc_clearBuffersAfterBakeGUIContent = new GUIContent("Clear Buffers After Bake", "Frees memory used by the MeshCombiner. Set to false if you want to update the combined mesh at runtime."),
|
||||||
|
gc_doNormGUIContent = new GUIContent("Include Normals"),
|
||||||
|
gc_doTanGUIContent = new GUIContent("Include Tangents"),
|
||||||
|
gc_doColGUIContent = new GUIContent("Include Colors"),
|
||||||
|
gc_doBlendShapeGUIContent = new GUIContent("Include Blend Shapes"),
|
||||||
|
gc_doUVGUIContent = new GUIContent("Include UV"),
|
||||||
|
gc_doUV3GUIContent = new GUIContent("Include UV3"),
|
||||||
|
gc_doUV4GUIContent = new GUIContent("Include UV4"),
|
||||||
|
|
||||||
|
gc_doUV5GUIContent = new GUIContent("Include UV5"),
|
||||||
|
gc_doUV6GUIContent = new GUIContent("Include UV6"),
|
||||||
|
gc_doUV7GUIContent = new GUIContent("Include UV7"),
|
||||||
|
gc_doUV8GUIContent = new GUIContent("Include UV8"),
|
||||||
|
|
||||||
|
gc_uv2HardAngleGUIContent = new GUIContent(" UV2 Hard Angle", "Angles greater than 'hard angle' in degrees will be split."),
|
||||||
|
gc_uv2PackingMarginUV3GUIContent = new GUIContent(" UV2 Packing Margin", "The margin between islands in the UV layout measured in UV coordinates (0..1) not pixels"),
|
||||||
|
gc_PivotLocationType = new GUIContent("Pivot Location Type", "Centers the verticies of the mesh about the render bounds center and translates the game object. This makes the combined meshes easier to work with. There is a performance and memory allocation cost to this so if you are frequently baking meshes at runtime disable it."),
|
||||||
|
gc_PivotLocation = new GUIContent("Pivot Location"),
|
||||||
|
gc_OptimizeAfterBake = new GUIContent("Optimize After Bake", "This does the same thing that 'Optimize' does on the ModelImporter."),
|
||||||
|
gc_AssignMeshCusomizer = new GUIContent("Assign To Mesh Customizer", "This is a custom script that can be used to alter data just before channels are assigned to the mesh." +
|
||||||
|
" It could be used for example to inject a Texture Array slice index into mesh coordinate (uv.z or colors.a)."),
|
||||||
|
gc_smrNoExtraBonesWhenCombiningMeshRenderers = new GUIContent("No Extra Bones For Mesh Renderers", "If a MeshRenderer is a child of another bone in the hierarchy (e.g. a sword is a child of a hand bone), then the MeshRenderer's vertices " +
|
||||||
|
" will be merged with the parent bone's vertices eliminating the extra bone (the sword becomes part of the hand). This reduces the bone count, but the MeshRenderer can never be moved independently of its parent.\n\n" +
|
||||||
|
"If you want some bones merged and some bones Independent, then move the 'Independent' bones in the hierarchy so that they are not descendants of other bones before baking. They can be re-parented after baking."),
|
||||||
|
gc_smrMergeBlendShapesWithSameNames = new GUIContent("Merge Blend Shapes With Same Names", "Enable this if you are combining multiple skinned meshes on a single rig (mixing and matching different body part variations and clothes) and the body parts have the " +
|
||||||
|
" same blend shape names. The combined mesh will preserve the original blend shape names. All blend shapes with the same name will activate in lockstep\n\n" +
|
||||||
|
"Disable this if you are combining multiple characters into a single combined skinned mesh and want to be able to activate the blend shapes on the different characters independently. " +
|
||||||
|
" the blend shapes will be re-named. Use the MB_BlendShape2CombinedMap component to control which blend shape activate."),
|
||||||
|
gc_meshAPItoUse = new GUIContent("Mesh API",
|
||||||
|
"Unity provides two APIs for baking meshes.\n\n" +
|
||||||
|
" Simple API: This is an older simpler API for meshes. This is the only API available before Unity 2020.2. In most cases it is slower, but is slightly faster for baking skinned meshes and Show-Hide operations.\n\n" +
|
||||||
|
" Native Array API (beta): This is a newer, usually faster API that uses NativeArrays. The Unity version must be 2020.2 or newer to use this. In most cases it is faster, but can be slower when baking skinned meshes. It should become faster in the future as most enhancements will happen with this API."
|
||||||
|
);
|
||||||
|
|
||||||
|
private SerializedProperty doNorm, doTan, doUV, doUV3, doUV4, doUV5, doUV6, doUV7, doUV8, doCol,
|
||||||
|
doBlendShapes, lightmappingOption, renderType, clearBuffersAfterBake,
|
||||||
|
uv2OutputParamsPackingMargin, uv2OutputParamsHardAngle, pivotLocationType,
|
||||||
|
pivotLocation, optimizeAfterBake, assignToMeshCustomizer,
|
||||||
|
meshAPItoUse;
|
||||||
|
private SerializedProperty smrNoExtraBonesWhenCombiningMeshRenderers, smrMergeBlendShapesWithSameNames;
|
||||||
|
private MB_EditorStyles editorStyles = new MB_EditorStyles();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the regular init method that should usually be used
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="meshBakerSettingsData">Should be the MB_IMeshBakerSettingsData implementor</param>
|
||||||
|
public void OnEnable(SerializedProperty meshBakerSettingsData)
|
||||||
|
{
|
||||||
|
_InitCommon(meshBakerSettingsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
editorStyles.DestroyTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _InitCommon(SerializedProperty combiner)
|
||||||
|
{
|
||||||
|
renderType = combiner.FindPropertyRelative("_renderType");
|
||||||
|
lightmappingOption = combiner.FindPropertyRelative("_lightmapOption");
|
||||||
|
doNorm = combiner.FindPropertyRelative("_doNorm");
|
||||||
|
doTan = combiner.FindPropertyRelative("_doTan");
|
||||||
|
doUV = combiner.FindPropertyRelative("_doUV");
|
||||||
|
doUV3 = combiner.FindPropertyRelative("_doUV3");
|
||||||
|
doUV4 = combiner.FindPropertyRelative("_doUV4");
|
||||||
|
doUV5 = combiner.FindPropertyRelative("_doUV5");
|
||||||
|
doUV6 = combiner.FindPropertyRelative("_doUV6");
|
||||||
|
doUV7 = combiner.FindPropertyRelative("_doUV7");
|
||||||
|
doUV8 = combiner.FindPropertyRelative("_doUV8");
|
||||||
|
doCol = combiner.FindPropertyRelative("_doCol");
|
||||||
|
doBlendShapes = combiner.FindPropertyRelative("_doBlendShapes");
|
||||||
|
uv2OutputParamsPackingMargin = combiner.FindPropertyRelative("_uv2UnwrappingParamsPackMargin");
|
||||||
|
uv2OutputParamsHardAngle = combiner.FindPropertyRelative("_uv2UnwrappingParamsHardAngle");
|
||||||
|
pivotLocationType = combiner.FindPropertyRelative("_pivotLocationType");
|
||||||
|
pivotLocation = combiner.FindPropertyRelative("_pivotLocation");
|
||||||
|
optimizeAfterBake = combiner.FindPropertyRelative("_optimizeAfterBake");
|
||||||
|
assignToMeshCustomizer = combiner.FindPropertyRelative("_assignToMeshCustomizer");
|
||||||
|
smrNoExtraBonesWhenCombiningMeshRenderers = combiner.FindPropertyRelative("_smrNoExtraBonesWhenCombiningMeshRenderers");
|
||||||
|
smrMergeBlendShapesWithSameNames = combiner.FindPropertyRelative("_smrMergeBlendShapesWithSameNames");
|
||||||
|
clearBuffersAfterBake = combiner.FindPropertyRelative("_clearBuffersAfterBake");
|
||||||
|
meshAPItoUse = combiner.FindPropertyRelative("_meshAPItoUse");
|
||||||
|
editorStyles.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawGUI(MB_IMeshBakerSettings momm, bool settingsEnabled, bool doingTextureArrays)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
|
||||||
|
GUI.enabled = settingsEnabled;
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(doNorm, gc_doNormGUIContent);
|
||||||
|
EditorGUILayout.PropertyField(doTan, gc_doTanGUIContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(doUV, gc_doUVGUIContent);
|
||||||
|
EditorGUILayout.PropertyField(doUV3, gc_doUV3GUIContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(doUV4, gc_doUV4GUIContent);
|
||||||
|
EditorGUILayout.PropertyField(doUV5, gc_doUV5GUIContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(doUV6, gc_doUV6GUIContent);
|
||||||
|
EditorGUILayout.PropertyField(doUV7, gc_doUV7GUIContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(doUV8, gc_doUV8GUIContent);
|
||||||
|
EditorGUILayout.PropertyField(doCol, gc_doColGUIContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(doBlendShapes, gc_doBlendShapeGUIContent);
|
||||||
|
|
||||||
|
if (momm.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Generating new lightmap UVs can split vertices which can push the number of vertices over the 64k limit.", MessageType.Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(lightmappingOption, gc_lightmappingOptionGUIContent);
|
||||||
|
if (momm.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout ||
|
||||||
|
momm.lightmapOption == MB2_LightmapOptions.copy_UV2_unchanged_to_separate_rects)
|
||||||
|
{
|
||||||
|
if (momm.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(uv2OutputParamsHardAngle, gc_uv2HardAngleGUIContent);
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(uv2OutputParamsPackingMargin, gc_uv2PackingMarginUV3GUIContent);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEngine.Object obj = null;
|
||||||
|
obj = assignToMeshCustomizer.objectReferenceValue;
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(renderType, gc_renderTypeGUIContent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(clearBuffersAfterBake, gc_clearBuffersAfterBakeGUIContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(pivotLocationType, gc_PivotLocationType);
|
||||||
|
// Confusion warning (don't use pivotLocationType.enumValueIndex. It is the index in the list of display names. NOT the enum value)
|
||||||
|
if (pivotLocationType.intValue == (int) MB_MeshPivotLocation.customLocation)
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(pivotLocation, gc_PivotLocation);
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(optimizeAfterBake, gc_OptimizeAfterBake);
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.LabelField("Skinned Mesh Renderer Settings", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.BeginDisabledGroup((MB_RenderType)renderType.intValue != MB_RenderType.skinnedMeshRenderer);
|
||||||
|
EditorGUILayout.PropertyField(smrNoExtraBonesWhenCombiningMeshRenderers, gc_smrNoExtraBonesWhenCombiningMeshRenderers);
|
||||||
|
EditorGUILayout.PropertyField(smrMergeBlendShapesWithSameNames, gc_smrMergeBlendShapesWithSameNames);
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.LabelField("Advanced Settings", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
// Don't use a PropertyField because we may not be able to use the assigned object. It may not implement requried interface.
|
||||||
|
|
||||||
|
if (doingTextureArrays)
|
||||||
|
{
|
||||||
|
bool useNewNativeArrayAPI = meshAPItoUse.intValue == (int) MB_MeshCombineAPIType.betaNativeArrayAPI;
|
||||||
|
string error = null;
|
||||||
|
if (assignToMeshCustomizer.objectReferenceValue == null)
|
||||||
|
{
|
||||||
|
error = "The Textures were baked into Texture Arrays. You probaly need to a customizer here" +
|
||||||
|
" to embed the slice index in the mesh. You can use one of the included customizers or write your own. " +
|
||||||
|
"See the example customizers in MeshBaker/Scripts/AssignToMeshCustomizers.";
|
||||||
|
} else if (useNewNativeArrayAPI && !(assignToMeshCustomizer.objectReferenceValue is IAssignToMeshCustomizer_NativeArrays))
|
||||||
|
{
|
||||||
|
error = "This Mesh Baker is configured to use Unity's new NativeArray API. This AssignToMeshCustomizer works with Unity's " +
|
||||||
|
"old API. You need an AssignToMeshCustomizer that implements IAssignToMeshCustomizer_NativeArrays. " +
|
||||||
|
"See the example customizers in MeshBaker/Scripts/AssignToMeshCustomizers.";
|
||||||
|
} else if (!useNewNativeArrayAPI && !(assignToMeshCustomizer.objectReferenceValue is IAssignToMeshCustomizer_SimpleAPI))
|
||||||
|
{
|
||||||
|
error = "This Mesh Baker is configured to use Unity's old Mesh API. This AssignToMeshCustomizer works with Unity's " +
|
||||||
|
"new NativeArray API. You need an AssignToMeshCustomizer that implements IAssignToMeshCustomizer. " +
|
||||||
|
"See the example customizers in MeshBaker/Scripts/AssignToMeshCustomizers.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(error, MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj = EditorGUILayout.ObjectField(gc_AssignMeshCusomizer, obj, typeof(UnityEngine.Object), true);
|
||||||
|
if (obj == null || !(obj is IAssignToMeshCustomizer))
|
||||||
|
{
|
||||||
|
assignToMeshCustomizer.objectReferenceValue = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assignToMeshCustomizer.objectReferenceValue = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(meshAPItoUse, gc_meshAPItoUse);
|
||||||
|
|
||||||
|
GUI.enabled = true;
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 82ca664c08ee65a42938adb59475f380
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MeshBakerSettingsEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(MB3_MultiMeshBaker))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class MB3_MultiMeshBakerEditor : Editor
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorInternal mbe = new MB3_MeshBakerEditorInternal();
|
||||||
|
[MenuItem(@"GameObject/Create Other/Mesh Baker/TextureBaker and MultiMeshBaker", false, 100)]
|
||||||
|
public static GameObject CreateNewMeshBaker()
|
||||||
|
{
|
||||||
|
MB3_TextureBaker[] mbs = (MB3_TextureBaker[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_TextureBaker));
|
||||||
|
Regex regex = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
int largest = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mbs.Length; i++)
|
||||||
|
{
|
||||||
|
Match match = regex.Match(mbs[i].name);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
int val = Convert.ToInt32(match.Groups[1].Value);
|
||||||
|
if (val >= largest)
|
||||||
|
largest = val + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex == null) ex = null; //Do nothing supress compiler warning
|
||||||
|
}
|
||||||
|
GameObject nmb = new GameObject("TextureBaker (" + largest + ")");
|
||||||
|
nmb.transform.position = Vector3.zero;
|
||||||
|
MB3_TextureBaker tb = nmb.AddComponent<MB3_TextureBaker>();
|
||||||
|
tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
|
||||||
|
MB3_MeshBakerGrouper mbg = nmb.AddComponent<MB3_MeshBakerGrouper>();
|
||||||
|
GameObject meshBaker = new GameObject("MultiMeshBaker");
|
||||||
|
MB3_MultiMeshBaker mmb = meshBaker.AddComponent<MB3_MultiMeshBaker>();
|
||||||
|
mmb.meshCombiner.settingsHolder = mbg;
|
||||||
|
meshBaker.transform.parent = nmb.transform;
|
||||||
|
|
||||||
|
return nmb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
mbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable()
|
||||||
|
{
|
||||||
|
mbe.OnDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
mbe.OnInspectorGUI(serializedObject, (MB3_MeshBakerCommon)target, targets, typeof(MB3_MeshBakerEditorWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e5238fa3cc273c740a7860c0aadcacf2
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_MultiMeshBakerEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
using static DigitalOpus.MB.MBEditor.GameObjectFilterInfo;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public interface IGroupByFilter
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// this name appears in the dropdown list.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The name.</returns>
|
||||||
|
string GetName();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// returns a description of the game object for this filter
|
||||||
|
/// eg. renderType=MeshFilter
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The description.</returns>
|
||||||
|
/// <param name="fi">Fi.</param>
|
||||||
|
string GetDescription(GameObjectFilterInfo fi);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For sorting Similar to IComparer.Compare
|
||||||
|
/// </summary>
|
||||||
|
int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class GameObjectFilterInfo : IComparable
|
||||||
|
{
|
||||||
|
|
||||||
|
public enum TransparentOrOpaque
|
||||||
|
{
|
||||||
|
NotApplicable = -1,
|
||||||
|
Opaque = 0,
|
||||||
|
Cutout = 1,
|
||||||
|
Fade = 2,
|
||||||
|
Transparent = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum URPBlendMode // called SurfaceType in URP
|
||||||
|
{
|
||||||
|
Opaque = 0,
|
||||||
|
Transparent = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HDRPBlendMode // called SurfaceType in HDRP
|
||||||
|
{
|
||||||
|
Opaque = 0,
|
||||||
|
Transparent = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] URPBlendMode_2_StandardBlendMode = new int[]
|
||||||
|
{
|
||||||
|
(int) TransparentOrOpaque.Opaque,
|
||||||
|
(int) TransparentOrOpaque.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
public int[] HDRPBlendMode_2_StandardBlendMode = new int[]
|
||||||
|
{
|
||||||
|
(int) TransparentOrOpaque.Opaque,
|
||||||
|
(int) TransparentOrOpaque.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum MetallicOrSpecular
|
||||||
|
{
|
||||||
|
NotApplicable = -1,
|
||||||
|
Specular = 0,
|
||||||
|
Metallic = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public GameObject go;
|
||||||
|
public string shaderName = "";
|
||||||
|
public Shader[] shaders = null; //distinct set of shaders used
|
||||||
|
|
||||||
|
|
||||||
|
public string materialName = "";
|
||||||
|
public Material[] materials = null; //disinct set of materials used
|
||||||
|
public string standardShaderBlendModesName = "";
|
||||||
|
public string metallicOrSpecularName = "";
|
||||||
|
public TransparentOrOpaque[] transparencies = null;
|
||||||
|
public MetallicOrSpecular[] metallicOrSpeculars = null;
|
||||||
|
public bool outOfBoundsUVs = false;
|
||||||
|
public bool submeshesOverlap = false;
|
||||||
|
public bool alreadyInBakerList = false;
|
||||||
|
public string setOfMaps;
|
||||||
|
public int numMaterials = 1;
|
||||||
|
public int lightmapIndex = -1;
|
||||||
|
public int layerIndex = -1;
|
||||||
|
public int numVerts = 0;
|
||||||
|
public bool isStatic = false;
|
||||||
|
public bool isMeshRenderer = true;
|
||||||
|
public StringBuilder warning = new StringBuilder();
|
||||||
|
public short atlasIndex = 0;
|
||||||
|
|
||||||
|
IGroupByFilter[] filters;
|
||||||
|
|
||||||
|
|
||||||
|
public int CompareTo(System.Object obj)
|
||||||
|
{
|
||||||
|
if (obj is GameObjectFilterInfo)
|
||||||
|
{
|
||||||
|
GameObjectFilterInfo gobj = (GameObjectFilterInfo)obj;
|
||||||
|
int gb;
|
||||||
|
|
||||||
|
for (int i = 0; i < filters.Length; i++)
|
||||||
|
{
|
||||||
|
if (filters[i] != null)
|
||||||
|
{
|
||||||
|
gb = filters[i].Compare(this, gobj);
|
||||||
|
if (gb != 0) return gb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObjectFilterInfo(GameObject g, HashSet<GameObject> objsAlreadyInBakers, IGroupByFilter[] filts)
|
||||||
|
{
|
||||||
|
go = g;
|
||||||
|
Renderer r = MB_Utility.GetRenderer(g);
|
||||||
|
//material = r.sharedMaterial;
|
||||||
|
//if (material != null) shader = material.shader;
|
||||||
|
HashSet<Material> matsSet = new HashSet<Material>();
|
||||||
|
HashSet<Shader> shaderSet = new HashSet<Shader>();
|
||||||
|
if (r is SkinnedMeshRenderer) isMeshRenderer = false;
|
||||||
|
else isMeshRenderer = true;
|
||||||
|
materials = r.sharedMaterials;
|
||||||
|
//shaders = new Shader[materials.Length];
|
||||||
|
for (int i = 0; i < materials.Length; i++)
|
||||||
|
{
|
||||||
|
if (materials[i] != null)
|
||||||
|
{
|
||||||
|
matsSet.Add(materials[i]);
|
||||||
|
shaderSet.Add(materials[i].shader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
materials = new Material[matsSet.Count];
|
||||||
|
matsSet.CopyTo(materials);
|
||||||
|
shaders = new Shader[shaderSet.Count];
|
||||||
|
transparencies = new TransparentOrOpaque[matsSet.Count];
|
||||||
|
metallicOrSpeculars = new MetallicOrSpecular[matsSet.Count];
|
||||||
|
|
||||||
|
shaderSet.CopyTo(shaders);
|
||||||
|
|
||||||
|
Array.Sort(materials, new NameComparer());
|
||||||
|
Array.Sort(shaders, new NameComparer());
|
||||||
|
|
||||||
|
List<string> standardShaderBlendModesNameSet = new List<string>();
|
||||||
|
List<string> metallicSpecularNameSet = new List<string>();
|
||||||
|
for (int i = 0; i < materials.Length; i++)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
if (materials[i].renderQueue > (int)UnityEngine.Rendering.RenderQueue.GeometryLast)
|
||||||
|
{
|
||||||
|
transparencies[i] = TransparentOrOpaque.Transparent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transparencies[i] = TransparentOrOpaque.Opaque;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (materials[i].shader.name.StartsWith("Standard"))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
if (materials[i].HasProperty("_SpecGlossMap") || materials[i].HasProperty("_SpecColor"))
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.Specular;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.Metallic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (materials[i].shader.name.StartsWith("Universal Render Pipeline") && materials[i].HasProperty("_Surface"))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// Check URP blend mode (opaque, transparent)
|
||||||
|
int surfaceMode = (int)materials[i].GetFloat("_Surface");
|
||||||
|
if (surfaceMode < 0 || surfaceMode > (int)URPBlendMode.Transparent)
|
||||||
|
{
|
||||||
|
Debug.LogError("Unsupported surface mode, were more surface modes added to the URP?");
|
||||||
|
surfaceMode = Mathf.Clamp(surfaceMode, (int)URPBlendMode.Opaque, (int)URPBlendMode.Transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check URP workflow (specular, transparent)
|
||||||
|
if (materials[i].HasProperty("_WorkflowMode"))
|
||||||
|
{
|
||||||
|
if (materials[i].GetFloat("_WorkflowMode") == (int)MetallicOrSpecular.Specular)
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.Specular;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.Metallic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (materials[i].HasProperty("_Metallic"))
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.Metallic;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.NotApplicable;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (materials[i].shader.name.StartsWith("HDRP") && materials[i].HasProperty("_SurfaceType"))
|
||||||
|
{
|
||||||
|
int surfaceMode = (int)materials[i].GetFloat("_SurfaceType");
|
||||||
|
if (surfaceMode < 0 || surfaceMode > (int)HDRPBlendMode.Transparent)
|
||||||
|
{
|
||||||
|
Debug.LogError("Unsupported surface mode, were more surface modes added to the HDRP?");
|
||||||
|
surfaceMode = Mathf.Clamp(surfaceMode, (int)HDRPBlendMode.Opaque, (int)HDRPBlendMode.Transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.Metallic; // HDRP is always metallic
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metallicOrSpeculars[i] = MetallicOrSpecular.NotApplicable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!standardShaderBlendModesNameSet.Contains(transparencies[i].ToString()))
|
||||||
|
{
|
||||||
|
standardShaderBlendModesNameSet.Add(transparencies[i].ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!metallicSpecularNameSet.Contains(metallicOrSpeculars[i].ToString()))
|
||||||
|
{
|
||||||
|
metallicSpecularNameSet.Add(metallicOrSpeculars[i].ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
materialName += (materials[i] == null ? "null" : materials[i].name);
|
||||||
|
if (i < materials.Length - 1) materialName += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
standardShaderBlendModesName = "";
|
||||||
|
standardShaderBlendModesNameSet.Sort();
|
||||||
|
foreach (string modeName in standardShaderBlendModesNameSet)
|
||||||
|
{
|
||||||
|
standardShaderBlendModesName += modeName + ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
metallicOrSpecularName = "";
|
||||||
|
metallicSpecularNameSet.Sort();
|
||||||
|
foreach (string permutationName in metallicSpecularNameSet)
|
||||||
|
{
|
||||||
|
metallicOrSpecularName += permutationName + ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < shaders.Length; i++)
|
||||||
|
{
|
||||||
|
shaderName += (shaders[i] == null ? "null" : shaders[i].name);
|
||||||
|
if (i < shaders.Length - 1) shaderName += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
List<string> listOfMaps = new List<string>();
|
||||||
|
|
||||||
|
for (int i = 0; i < materials.Length; i++)
|
||||||
|
{
|
||||||
|
listOfMaps.Clear();
|
||||||
|
List<ShaderTextureProperty> texPropertyNamesList = new List<ShaderTextureProperty>();
|
||||||
|
List<ShaderTextureProperty> customPropNames_Unused = new List<ShaderTextureProperty>();
|
||||||
|
MBVersion.CollectPropertyNames(texPropertyNamesList,
|
||||||
|
MB3_TextureCombinerPipeline.shaderTexPropertyNames,
|
||||||
|
customPropNames_Unused,
|
||||||
|
materials[i],
|
||||||
|
MB2_LogLevel.info);
|
||||||
|
|
||||||
|
string[] propertyNames = texPropertyNamesList.Select(stp => stp.name).ToArray();
|
||||||
|
|
||||||
|
foreach (string propName in propertyNames)
|
||||||
|
{
|
||||||
|
if (listOfMaps.Contains(propName))
|
||||||
|
{
|
||||||
|
// Already added, don't add again
|
||||||
|
}
|
||||||
|
else if ( MB3_TextureCombinerPipeline.shaderTexPropertiesToExclude.Contains(propName))
|
||||||
|
{
|
||||||
|
// Don't add
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (materials[i].HasProperty(propName) && materials[i].GetTexture(propName) != null)
|
||||||
|
{
|
||||||
|
listOfMaps.Add(propName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listOfMaps.Sort();
|
||||||
|
if (listOfMaps.Count == 0)
|
||||||
|
{
|
||||||
|
setOfMaps = "None";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setOfMaps = string.Join(", ", listOfMaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lightmapIndex = r.lightmapIndex;
|
||||||
|
Mesh mesh = MB_Utility.GetMesh(g);
|
||||||
|
numVerts = 0;
|
||||||
|
if (mesh != null)
|
||||||
|
{
|
||||||
|
numVerts = mesh.vertexCount;
|
||||||
|
}
|
||||||
|
isStatic = go.isStatic;
|
||||||
|
numMaterials = materials.Length;
|
||||||
|
warning = new StringBuilder();
|
||||||
|
alreadyInBakerList = objsAlreadyInBakers.Contains(g);
|
||||||
|
outOfBoundsUVs = false;
|
||||||
|
submeshesOverlap = false;
|
||||||
|
filters = filts;
|
||||||
|
layerIndex = g.layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(IGroupByFilter[] groupBy, GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
string desc = "";
|
||||||
|
if (groupBy != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < groupBy.Length; i++)
|
||||||
|
{
|
||||||
|
desc += groupBy[i].GetDescription(fi) + " ";
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "todo";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NameComparer : Comparer<UnityEngine.Object>
|
||||||
|
{
|
||||||
|
public override int Compare(UnityEngine.Object a, UnityEngine.Object b)
|
||||||
|
{
|
||||||
|
return a.name.CompareTo(b.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 435b539c6ab6a4346bc6c56e18046e1b
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_SearchFilters.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(MB3_TextureBaker))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class MB3_TextureBakerEditor : Editor
|
||||||
|
{
|
||||||
|
|
||||||
|
MB3_TextureBakerEditorInternal tbe = new MB3_TextureBakerEditorInternal();
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
tbe.OnEnable(serializedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable()
|
||||||
|
{
|
||||||
|
tbe.OnDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
tbe.DrawGUI(serializedObject, (MB3_TextureBaker)target, targets, typeof(MB3_MeshBakerEditorWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 26f57cf1f0be79d4f995b90509950e0f
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_TextureBakerEditor.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,605 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB3_TextureBakerEditorInternal
|
||||||
|
{
|
||||||
|
public static bool IsCombiningTexture
|
||||||
|
{
|
||||||
|
private set;
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MultiMatSubmeshInfo
|
||||||
|
{
|
||||||
|
public Shader shader;
|
||||||
|
public GameObjectFilterInfo.TransparentOrOpaque stdBlendMode = GameObjectFilterInfo.TransparentOrOpaque.NotApplicable;
|
||||||
|
|
||||||
|
public MultiMatSubmeshInfo(Shader s, Material m)
|
||||||
|
{
|
||||||
|
shader = s;
|
||||||
|
if (m.shader.name.StartsWith("Standard") && m.HasProperty("_Mode"))
|
||||||
|
{
|
||||||
|
stdBlendMode = (GameObjectFilterInfo.TransparentOrOpaque)m.GetFloat("_Mode");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stdBlendMode = GameObjectFilterInfo.TransparentOrOpaque.NotApplicable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
MultiMatSubmeshInfo b = (MultiMatSubmeshInfo)obj;
|
||||||
|
return (stdBlendMode == b.stdBlendMode && shader == b.shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return shader.GetHashCode() ^ (int)stdBlendMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MeshSubmeshMaterial
|
||||||
|
{
|
||||||
|
public Mesh mesh;
|
||||||
|
public Material srcMat;
|
||||||
|
public int submesh;
|
||||||
|
public bool obUVs;
|
||||||
|
public GameObject srcGameObj;
|
||||||
|
|
||||||
|
public MeshSubmeshMaterial(Mesh mesh, Material srcMat, int submesh, bool obUVs, GameObject srcGo)
|
||||||
|
{
|
||||||
|
this.mesh = mesh;
|
||||||
|
this.srcMat = srcMat;
|
||||||
|
this.submesh = submesh;
|
||||||
|
this.obUVs = obUVs;
|
||||||
|
this.srcGameObj = srcGo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
var material = obj as MeshSubmeshMaterial;
|
||||||
|
return material != null &&
|
||||||
|
EqualityComparer<Mesh>.Default.Equals(mesh, material.mesh) &&
|
||||||
|
EqualityComparer<Material>.Default.Equals(srcMat, material.srcMat) &&
|
||||||
|
submesh == material.submesh &&
|
||||||
|
obUVs == material.obUVs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
var hashCode = -1560254091;
|
||||||
|
hashCode = hashCode * -1521134295 + EqualityComparer<Mesh>.Default.GetHashCode(mesh);
|
||||||
|
hashCode = hashCode * -1521134295 + EqualityComparer<Material>.Default.GetHashCode(srcMat);
|
||||||
|
hashCode = hashCode * -1521134295 + submesh.GetHashCode();
|
||||||
|
hashCode = hashCode * -1521134295 + obUVs.GetHashCode();
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add option to exclude skinned mesh renderer and mesh renderer in filter
|
||||||
|
//example scenes for multi material
|
||||||
|
|
||||||
|
internal static GUIContent insertContent = new GUIContent("+", "add a material");
|
||||||
|
internal static GUIContent deleteContent = new GUIContent("-", "delete a material");
|
||||||
|
internal static GUILayoutOption buttonWidth = GUILayout.MaxWidth(20f);
|
||||||
|
public static GUIContent noneContent = new GUIContent("");
|
||||||
|
|
||||||
|
//private SerializedObject textureBaker;
|
||||||
|
internal SerializedProperty logLevel, textureBakeResults, maxTilingBakeSize, maxAtlasSize,
|
||||||
|
doMultiMaterial, doMultiMaterialSplitAtlasesIfTooBig, doMultiMaterialIfOBUVs, considerMeshUVs, resultMaterial, resultMaterials, atlasPadding,
|
||||||
|
resizePowerOfTwoTextures, customShaderProperties, texturePropNamesToIgnore, objsToMesh, texturePackingAlgorithm, layerTexturePackerFastMesh, maxAtlasWidthOverride, maxAtlasHeightOverride, useMaxAtlasWidthOverride, useMaxAtlasHeightOverride,
|
||||||
|
forcePowerOfTwoAtlas, considerNonTextureProperties, sortOrderAxis, resultType,
|
||||||
|
resultMaterialsTexArray, textureArrayOutputFormats;
|
||||||
|
|
||||||
|
internal bool resultMaterialsFoldout = true;
|
||||||
|
internal bool showInstructions = false;
|
||||||
|
internal bool showContainsReport = true;
|
||||||
|
|
||||||
|
private int objsToBeCombined_CurrentPage = 1;
|
||||||
|
private int objsToBecombined_NumPerPage = 50;
|
||||||
|
|
||||||
|
internal MB_EditorStyles editorStyles = new MB_EditorStyles();
|
||||||
|
|
||||||
|
Color buttonColor = new Color(.8f, .8f, 1f, 1f);
|
||||||
|
|
||||||
|
internal static GUIContent
|
||||||
|
createPrefabAndMaterialLabelContent = new GUIContent("Create Empty Assets For Combined Material", "Creates a material asset and a 'MB2_TextureBakeResult' asset. You should set the shader on the material. Mesh Baker uses the Texture properties on the material to decide what atlases need to be created. The MB2_TextureBakeResult asset should be used in the 'Texture Bake Result' field."),
|
||||||
|
logLevelContent = new GUIContent("Log Level"),
|
||||||
|
openToolsWindowLabelContent = new GUIContent("Open Tools For Adding Objects", "Use these tools to find out what can be combined, discover possible problems with meshes, and quickly add objects."),
|
||||||
|
fixOutOfBoundsGUIContent = new GUIContent("Consider Mesh UVs", "Textures copied to the atlas will be clipped to the mesh UV rectangle as well as the texture material tiling. This can have two effects:\n\n" +
|
||||||
|
"1) If the mesh only uses a small rectangle of it's source texture (atlas) then only that small rectangle will be copied to the atlas.\n\n" +
|
||||||
|
"2) If the mesh has uvs outside the 0,1 range (tiling) then this tiling will be copied to the atlas."),
|
||||||
|
resizePowerOfTwoGUIContent = new GUIContent("Resize Power-Of-Two Textures", "Shrinks textures so they have a clear border of width 'Atlas Padding' around them. Improves texture packing efficiency."),
|
||||||
|
customShaderPropertyNamesGUIContent = new GUIContent("Custom Shader Property Names", "Mesh Baker has a list of common texture properties that it looks for in shaders to generate atlases. Custom shaders may have texture properties not on this list. Add them here and Mesh Baker will generate atlases for them."),
|
||||||
|
gc_texturePropNamesToIgnore = new GUIContent("Texture Properties To Ignore", "A list of material texture properties to ignore. Atlases will not be generated for these properties. Some materials have textures that are not positioned on the mesh using UV coordinates (for example cell shader color ramps or LUTs). Usually atlases should not be created for these properties."),
|
||||||
|
combinedMaterialsGUIContent = new GUIContent("Combined Materials", "Use the +/- buttons to add multiple combined materials. You will also need to specify which materials on the source objects map to each combined material."),
|
||||||
|
textureArrayCombinedMaterialFoldoutGUIContent = new GUIContent("Texture Array Combined Materials", "Use the +/- buttons to add texture array materials. You will also need to specify which materials on the source objects map to each texture array slice."),
|
||||||
|
maxTilingBakeSizeGUIContent = new GUIContent("Max Tiling Bake Size", "This is the maximum size tiling textures will be baked to."),
|
||||||
|
maxAtlasSizeGUIContent = new GUIContent("Max Atlas Size", "This is the maximum size of the atlas. If the atlas is larger than this, textures being added will be shrunk."),
|
||||||
|
|
||||||
|
objectsToCombineGUIContent = new GUIContent("Objects To Be Combined", "These can be prefabs or scene objects. They must be game objects with Renderer components, not the parent objects. Materials on these objects will baked into the combined material(s)"),
|
||||||
|
textureBakeResultsGUIContent = new GUIContent("Texture Bake Result", "This asset contains a mapping of materials to UV rectangles in the atlases. It is needed to create combined meshes or adjust meshes so they can use the combined material(s). Create it using 'Create Empty Assets For Combined Material'. Drag it to the 'Texture Bake Result' field to use it."),
|
||||||
|
texturePackingAgorithmGUIContent = new GUIContent("Texture Packer", "Unity's PackTextures: Atlases are always a power of two. Can crash when trying to generate large atlases. \n\n" +
|
||||||
|
"Mesh Baker Texture Packer: Atlases will be most efficient size and shape (not limited to a power of two). More robust for large atlases. \n\n" +
|
||||||
|
"Mesh Baker Texture Packer Fast: Same as Mesh Baker Texture Packer but creates atlases on the graphics card using RenderTextures instead of the CPU. Source textures can be compressed. May not be pixel perfect. \n\n" +
|
||||||
|
"Mesh Baker Texture Packer Horizontal (Experimental): Packs all images vertically to allow horizontal-only UV-tiling.\n\n" +
|
||||||
|
"Mesh Baker Texture Packer Vertical (Experimental): Packs all images horizontally other to allow vertical-only UV-tiling.\n\n" +
|
||||||
|
"Mesh Baker Texture Packer Fast V2 (Experimental): A rewrite of 'Mesh Baker Texture Packer Fast' that is compatible with URP and HDRP and even faster.\n\n"),
|
||||||
|
|
||||||
|
layerTexturePackerFastMeshGUIContent = new GUIContent("Atlas Render Layer", "Bad 'Atlas Render Layer' value. The atlas is rendered using a MeshRenderer in the scene. This MeshRenderer needs to be on a layer that is not used by any other renderers. If there are other renderers on this layer, those renderers could render in front of the atlas, which would ruin it."),
|
||||||
|
configAtlasMultiMatsFromObjsContent = new GUIContent("Build Source To Combined Mapping From \n Objects To Be Combined", "This will group the materials on your source objects by shader and create one source to combined mapping for each shader found. For example if combining trees, then all the materials with the same bark shader will be grouped togther and all the materials with the same leaf material will be grouped together. You can adjust the results afterwards. \n\nIf Consider Mesh UVs is NOT checked, then submeshes with UVs outside 0,0..1,1 will be mapped to their own submesh regardless of shader."),
|
||||||
|
configAtlasTextureSlicesFromObjsContent = new GUIContent("Build Texture Array Slices From \n Objects To Be Combined", "This will group the materials on your source objects by shader and create slices. Objects with out-of-bounds UVs will be put on their own slice. You can adjust the results afterwards."),
|
||||||
|
forcePowerOfTwoAtlasContent = new GUIContent("Force Power-Of-Two Atlas", "Forces atlas x and y dimensions to be powers of two with aspect ratio 1:1,1:2 or 2:1. Unity recommends textures be a power of two for everything but GUI textures."),
|
||||||
|
considerNonTexturePropertiesContent = new GUIContent("Blend Non-Texture Properties", "Will blend non-texture properties such as _Color, _Glossiness with the textures. Objects with different non-texture property values will be copied into different parts of the atlas even if they use the same textures. This feature requires that TextureBlenders " +
|
||||||
|
"exist for the result material shader. It is easy to extend Mesh Baker by writing custom TextureBlenders. Default TextureBlenders exist for: \n" +
|
||||||
|
" - Standard \n" +
|
||||||
|
" - Diffuse \n" +
|
||||||
|
" - Bump Diffuse\n"),
|
||||||
|
gc_SortAlongAxis = new GUIContent("Sort Along Axis", "Transparent materials often require that triangles be rendered far to near. Game Objects will be sorted along this axis. Triangles will be added to the combined mesh in this order."),
|
||||||
|
gc_DoMultiMaterialSplitAtlasesIfTooBig = new GUIContent("Split Atlases If Textures Don't Fit", ""),
|
||||||
|
gc_DoMultiMaterialSplitAtlasesIfOBUVs = new GUIContent("Put Meshes With Out Of Bounds UV On Submesh", ""),
|
||||||
|
gc_overrideMaxAtlasWidth = new GUIContent("Override Max Atlas Width", "Set the maximum width of the atlas to this."),
|
||||||
|
gc_overrideMaxAtlasHeight = new GUIContent("Override Max Atlas Height", "Set the maximum height of the atlas to this."),
|
||||||
|
gc_useMaxAtlasWidthOverride = new GUIContent("Use Max Width Override", "Force the atlas width to not exceed the override value"),
|
||||||
|
gc_useMaxAtlasHeightOverride = new GUIContent("Use Max Height Override", "Force the atlas width to not exceed the override value"),
|
||||||
|
gc_atlasPadding = new GUIContent("Atlas Padding", "Number of pixels to pad around the edge of the atlas.");
|
||||||
|
|
||||||
|
protected string layerTexturePackerFastMeshMessage;
|
||||||
|
|
||||||
|
|
||||||
|
[MenuItem("GameObject/Create Other/Mesh Baker/TextureBaker", false, 100)]
|
||||||
|
public static void CreateNewTextureBaker()
|
||||||
|
{
|
||||||
|
MB3_TextureBaker[] mbs = (MB3_TextureBaker[]) MBVersion.FindSceneObjectsOfType(typeof(MB3_TextureBaker));
|
||||||
|
Regex regex = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
int largest = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mbs.Length; i++)
|
||||||
|
{
|
||||||
|
Match match = regex.Match(mbs[i].name);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
int val = Convert.ToInt32(match.Groups[1].Value);
|
||||||
|
if (val >= largest)
|
||||||
|
largest = val + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex == null) ex = null; //Do nothing supress compiler warning
|
||||||
|
}
|
||||||
|
GameObject nmb = new GameObject("TextureBaker (" + largest + ")");
|
||||||
|
nmb.transform.position = Vector3.zero;
|
||||||
|
nmb.AddComponent<MB3_MeshBakerGrouper>();
|
||||||
|
MB3_TextureBaker tb = nmb.AddComponent<MB3_TextureBaker>();
|
||||||
|
tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _init(SerializedObject textureBaker)
|
||||||
|
{
|
||||||
|
//textureBaker = new SerializedObject(target);
|
||||||
|
logLevel = textureBaker.FindProperty("LOG_LEVEL");
|
||||||
|
doMultiMaterial = textureBaker.FindProperty("_doMultiMaterial");
|
||||||
|
doMultiMaterialSplitAtlasesIfTooBig = textureBaker.FindProperty("_doMultiMaterialSplitAtlasesIfTooBig");
|
||||||
|
doMultiMaterialIfOBUVs = textureBaker.FindProperty("_doMultiMaterialSplitAtlasesIfOBUVs");
|
||||||
|
considerMeshUVs = textureBaker.FindProperty("_fixOutOfBoundsUVs");
|
||||||
|
resultMaterial = textureBaker.FindProperty("_resultMaterial");
|
||||||
|
resultMaterials = textureBaker.FindProperty("resultMaterials");
|
||||||
|
atlasPadding = textureBaker.FindProperty("_atlasPadding");
|
||||||
|
resizePowerOfTwoTextures = textureBaker.FindProperty("_resizePowerOfTwoTextures");
|
||||||
|
customShaderProperties = textureBaker.FindProperty("_customShaderProperties");
|
||||||
|
texturePropNamesToIgnore = textureBaker.FindProperty("_texturePropNamesToIgnore");
|
||||||
|
objsToMesh = textureBaker.FindProperty("objsToMesh");
|
||||||
|
maxTilingBakeSize = textureBaker.FindProperty("_maxTilingBakeSize");
|
||||||
|
maxAtlasSize = textureBaker.FindProperty("_maxAtlasSize");
|
||||||
|
maxAtlasWidthOverride = textureBaker.FindProperty("_maxAtlasWidthOverride");
|
||||||
|
maxAtlasHeightOverride = textureBaker.FindProperty("_maxAtlasHeightOverride");
|
||||||
|
useMaxAtlasWidthOverride = textureBaker.FindProperty("_useMaxAtlasWidthOverride");
|
||||||
|
useMaxAtlasHeightOverride = textureBaker.FindProperty("_useMaxAtlasHeightOverride");
|
||||||
|
textureBakeResults = textureBaker.FindProperty("_textureBakeResults");
|
||||||
|
texturePackingAlgorithm = textureBaker.FindProperty("_packingAlgorithm");
|
||||||
|
layerTexturePackerFastMesh = textureBaker.FindProperty("_layerTexturePackerFastMesh");
|
||||||
|
forcePowerOfTwoAtlas = textureBaker.FindProperty("_meshBakerTexturePackerForcePowerOfTwo");
|
||||||
|
considerNonTextureProperties = textureBaker.FindProperty("_considerNonTextureProperties");
|
||||||
|
sortOrderAxis = textureBaker.FindProperty("sortAxis");
|
||||||
|
resultType = textureBaker.FindProperty("_resultType");
|
||||||
|
resultMaterialsTexArray = textureBaker.FindProperty("resultMaterialsTexArray");
|
||||||
|
textureArrayOutputFormats = textureBaker.FindProperty("textureArrayOutputFormats");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnEnable(SerializedObject textureBaker)
|
||||||
|
{
|
||||||
|
_init(textureBaker);
|
||||||
|
if (editorStyles == null) editorStyles = new MB_EditorStyles();
|
||||||
|
editorStyles.Init();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
editorStyles.DestroyTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawGUI(SerializedObject textureBaker, MB3_TextureBaker momm, UnityEngine.Object[] targets, System.Type editorWindow)
|
||||||
|
{
|
||||||
|
if (textureBaker == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
textureBaker.Update();
|
||||||
|
|
||||||
|
|
||||||
|
showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
|
||||||
|
if (showInstructions)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("1. Add scene objects or prefabs to combine. For best results these should use the same shader as Combined Mesh Material.\n\n" +
|
||||||
|
"2. Create Empty Assets for Combined Mesh Material(s)\n\n" +
|
||||||
|
"3. Check that shader on Combined Mesh Material(s) are correct.\n\n" +
|
||||||
|
"4. Bake materials into Combined Mesh Material(s).\n\n" +
|
||||||
|
"5. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
|
||||||
|
"6. You are now ready to bake combined meshes or batch bake prefabs.", UnityEditor.MessageType.None);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(logLevel, logLevelContent);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
|
||||||
|
// Selected objects
|
||||||
|
EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
|
||||||
|
EditorGUILayout.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
|
||||||
|
if (GUILayout.Button(openToolsWindowLabelContent))
|
||||||
|
{
|
||||||
|
MB3_MeshBakerEditorWindow mmWin = (MB3_MeshBakerEditorWindow) EditorWindow.GetWindow(editorWindow);
|
||||||
|
mmWin.SetTarget((MB3_MeshBakerRoot) momm);
|
||||||
|
}
|
||||||
|
|
||||||
|
object[] objs = MB3_EditorMethods.DropZone("Drag & Drop Renderers or Parents\n" + "HERE\n" +
|
||||||
|
"to add objects to be combined", 300, 50);
|
||||||
|
MB3_EditorMethods.AddDroppedObjects(objs, momm.GetObjectsToCombine());
|
||||||
|
MB_PaginatedList.GenerateObjectsToBeCombinedList(objsToMesh, ref objsToBeCombined_CurrentPage, ref objsToBecombined_NumPerPage);
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Select Objects In Scene"))
|
||||||
|
{
|
||||||
|
List<MB3_TextureBaker> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
List<GameObject> obsToCombine = new List<GameObject>();
|
||||||
|
|
||||||
|
foreach (MB3_TextureBaker baker in selectedBakers) obsToCombine.AddRange(baker.GetObjectsToCombine());
|
||||||
|
Selection.objects = obsToCombine.ToArray();
|
||||||
|
if (momm.GetObjectsToCombine().Count > 0)
|
||||||
|
{
|
||||||
|
SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(gc_SortAlongAxis))
|
||||||
|
{
|
||||||
|
MB3_MeshBakerRoot.ZSortObjects sorter = new MB3_MeshBakerRoot.ZSortObjects();
|
||||||
|
sorter.sortAxis = sortOrderAxis.vector3Value;
|
||||||
|
sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
|
||||||
|
// output
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(resultType);
|
||||||
|
|
||||||
|
if (GUILayout.Button(createPrefabAndMaterialLabelContent))
|
||||||
|
{
|
||||||
|
List<MB3_TextureBaker> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
string newPrefabPath = EditorUtility.SaveFilePanelInProject("Asset name", "", "asset", "Enter a name for the baked texture results");
|
||||||
|
if (newPrefabPath != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < selectedBakers.Count; i++)
|
||||||
|
{
|
||||||
|
CreateCombinedMaterialAssets(selectedBakers[i], newPrefabPath, i == 0 ? true : false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(textureBakeResults, textureBakeResultsGUIContent);
|
||||||
|
if (textureBakeResults.objectReferenceValue != null)
|
||||||
|
{
|
||||||
|
showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
|
||||||
|
if (showContainsReport)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confusion warning (don't use resultType.enumValueIndex. It is the index in the list of display names. NOT the enum value)
|
||||||
|
if (resultType.intValue == (int) MB2_TextureBakeResults.ResultType.textureArray)
|
||||||
|
{
|
||||||
|
MB_TextureBakerConfigureTextureArrays.DrawTextureArrayConfiguration(momm, textureBaker, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(doMultiMaterial, new GUIContent("Multiple Combined Materials"));
|
||||||
|
|
||||||
|
if (momm.doMultiMaterial)
|
||||||
|
{
|
||||||
|
MB_TextureBakerEditorConfigureMultiMaterials.DrawMultipleMaterialsMappings(momm, textureBaker, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(resultMaterial, new GUIContent("Combined Mesh Material"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// settings
|
||||||
|
int labelWidth = 200;
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
|
||||||
|
EditorGUILayout.LabelField("Material Bake Options", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
DrawPropertyFieldWithLabelWidth(atlasPadding, gc_atlasPadding, labelWidth);
|
||||||
|
DrawPropertyFieldWithLabelWidth(maxAtlasSize, maxAtlasSizeGUIContent, labelWidth);
|
||||||
|
DrawPropertyFieldWithLabelWidth(resizePowerOfTwoTextures, resizePowerOfTwoGUIContent, labelWidth);
|
||||||
|
DrawPropertyFieldWithLabelWidth(maxTilingBakeSize, maxTilingBakeSizeGUIContent, labelWidth);
|
||||||
|
EditorGUI.BeginDisabledGroup(momm.doMultiMaterial);
|
||||||
|
DrawPropertyFieldWithLabelWidth(considerMeshUVs, fixOutOfBoundsGUIContent, labelWidth);
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
if (texturePackingAlgorithm.intValue == (int)MB2_PackingAlgorithmEnum.MeshBakerTexturePacker ||
|
||||||
|
texturePackingAlgorithm.intValue == (int)MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Fast ||
|
||||||
|
texturePackingAlgorithm.intValue == (int)MB2_PackingAlgorithmEnum.MeshBakerTexturePaker_Fast_V2_Beta)
|
||||||
|
{
|
||||||
|
DrawPropertyFieldWithLabelWidth(forcePowerOfTwoAtlas, forcePowerOfTwoAtlasContent, labelWidth);
|
||||||
|
}
|
||||||
|
DrawPropertyFieldWithLabelWidth(considerNonTextureProperties, considerNonTexturePropertiesContent, labelWidth);
|
||||||
|
if (texturePackingAlgorithm.intValue == (int)MB2_PackingAlgorithmEnum.UnitysPackTextures)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Unity's texture packer has memory problems and frequently crashes the editor.", MessageType.Warning);
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(texturePackingAlgorithm, texturePackingAgorithmGUIContent);
|
||||||
|
if (MB3_TextureCombinerPipeline.USE_EXPERIMENTAL_HOIZONTALVERTICAL)
|
||||||
|
{
|
||||||
|
// Confusion warning (don't use texturePackingAlgorithm.enumValueIndex. It is the index in the list of display names. NOT the enum value)
|
||||||
|
if (texturePackingAlgorithm.intValue == (int)MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal)
|
||||||
|
{
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(useMaxAtlasWidthOverride, gc_useMaxAtlasWidthOverride);
|
||||||
|
if (!useMaxAtlasWidthOverride.boolValue) EditorGUI.BeginDisabledGroup(true);
|
||||||
|
EditorGUILayout.PropertyField(maxAtlasWidthOverride, gc_overrideMaxAtlasWidth);
|
||||||
|
if (!useMaxAtlasWidthOverride.boolValue) EditorGUI.EndDisabledGroup();
|
||||||
|
}
|
||||||
|
else if (texturePackingAlgorithm.intValue == (int)MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical)
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(useMaxAtlasHeightOverride, gc_useMaxAtlasHeightOverride);
|
||||||
|
if (!useMaxAtlasHeightOverride.boolValue) EditorGUI.BeginDisabledGroup(true);
|
||||||
|
EditorGUILayout.PropertyField(maxAtlasHeightOverride, gc_overrideMaxAtlasHeight);
|
||||||
|
if (!useMaxAtlasHeightOverride.boolValue) EditorGUI.EndDisabledGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.MeshBakerTexturePaker_Fast_V2_Beta)
|
||||||
|
{
|
||||||
|
// layer field
|
||||||
|
int newValueLayerTexturePackerFastMesh = EditorGUILayout.LayerField(layerTexturePackerFastMeshGUIContent, layerTexturePackerFastMesh.intValue);
|
||||||
|
bool isNewValue = newValueLayerTexturePackerFastMesh == layerTexturePackerFastMesh.intValue;
|
||||||
|
layerTexturePackerFastMesh.intValue = newValueLayerTexturePackerFastMesh;
|
||||||
|
if (isNewValue)
|
||||||
|
{
|
||||||
|
Renderer[] rs = (Renderer[]) MBVersion.FindSceneObjectsOfType(typeof(Renderer));
|
||||||
|
int numRenderersOnLayer = 0;
|
||||||
|
for (int i = 0; i < rs.Length; i++)
|
||||||
|
{
|
||||||
|
if (rs[i].gameObject.layer == newValueLayerTexturePackerFastMesh) numRenderersOnLayer++;
|
||||||
|
}
|
||||||
|
|
||||||
|
string layerName = LayerMask.LayerToName(layerTexturePackerFastMesh.intValue);
|
||||||
|
if (layerName != null && layerName.Length > 0 && numRenderersOnLayer == 0)
|
||||||
|
{
|
||||||
|
layerTexturePackerFastMeshMessage = null;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
layerTexturePackerFastMeshMessage = layerTexturePackerFastMeshGUIContent.tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string scriptDefinesErrMessage = ValidatePlayerSettingsDefineSymbols();
|
||||||
|
|
||||||
|
if (layerTexturePackerFastMesh.intValue == -1 ||
|
||||||
|
(layerTexturePackerFastMeshMessage != null && layerTexturePackerFastMeshMessage.Length > 0) ||
|
||||||
|
(scriptDefinesErrMessage != null))
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(layerTexturePackerFastMeshMessage + "\n\n" + scriptDefinesErrMessage, MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(customShaderProperties, customShaderPropertyNamesGUIContent, true);
|
||||||
|
EditorGUILayout.PropertyField(texturePropNamesToIgnore, gc_texturePropNamesToIgnore, true);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
Color oldColor = GUI.backgroundColor;
|
||||||
|
GUI.color = buttonColor;
|
||||||
|
if (GUILayout.Button("Bake Materials Into Combined Material"))
|
||||||
|
{
|
||||||
|
IsCombiningTexture = true;
|
||||||
|
List<MB3_TextureBaker> selectedBakers = _getBakersFromTargets(targets);
|
||||||
|
foreach (MB3_TextureBaker tb in selectedBakers)
|
||||||
|
{
|
||||||
|
tb.CreateAtlases(updateProgressBar, true, new MB3_EditorMethods());
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
if (tb.textureBakeResults != null) EditorUtility.SetDirty(momm.textureBakeResults);
|
||||||
|
}
|
||||||
|
IsCombiningTexture = false;
|
||||||
|
}
|
||||||
|
GUI.backgroundColor = oldColor;
|
||||||
|
textureBaker.ApplyModifiedProperties();
|
||||||
|
if (GUI.changed)
|
||||||
|
{
|
||||||
|
textureBaker.SetIsDifferentCacheDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawPropertyFieldWithLabelWidth(SerializedProperty prop, GUIContent content, int labelWidth)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField(content, GUILayout.Width(labelWidth));
|
||||||
|
EditorGUILayout.PropertyField(prop, noneContent);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateProgressBar(string msg, float progress)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayProgressBar("Combining Meshes", msg, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateCombinedMaterialAssets(MB3_TextureBaker target, string pth, bool allowOverwrite=true)
|
||||||
|
{
|
||||||
|
MB3_TextureBaker mom = (MB3_TextureBaker)target;
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(pth);
|
||||||
|
if (baseName == null || baseName.Length == 0) return;
|
||||||
|
string folderPath = Path.GetDirectoryName(pth) + "/";
|
||||||
|
|
||||||
|
List<string> matNames = new List<string>();
|
||||||
|
if (mom.resultType == MB2_TextureBakeResults.ResultType.textureArray)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mom.resultMaterialsTexArray.Length; i++)
|
||||||
|
{
|
||||||
|
string nm = folderPath + baseName + "-mat" + i + ".mat";
|
||||||
|
if (!allowOverwrite) nm = AssetDatabase.GenerateUniqueAssetPath(nm);
|
||||||
|
matNames.Add(nm);
|
||||||
|
AssetDatabase.CreateAsset(new Material(Shader.Find("Diffuse")), matNames[i]);
|
||||||
|
mom.resultMaterialsTexArray[i].combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matNames[i], typeof(Material));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mom.doMultiMaterial)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mom.resultMaterials.Length; i++)
|
||||||
|
{
|
||||||
|
string nm = folderPath + baseName + "-mat" + i + ".mat";
|
||||||
|
if (!allowOverwrite) nm = AssetDatabase.GenerateUniqueAssetPath(nm);
|
||||||
|
matNames.Add(nm);
|
||||||
|
AssetDatabase.CreateAsset(new Material(Shader.Find("Diffuse")), matNames[i]);
|
||||||
|
mom.resultMaterials[i].combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matNames[i], typeof(Material));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string nm = folderPath + baseName + "-mat.mat";
|
||||||
|
if (!allowOverwrite) nm = AssetDatabase.GenerateUniqueAssetPath(nm);
|
||||||
|
matNames.Add(nm);
|
||||||
|
Material newMat = null;
|
||||||
|
if (mom.GetObjectsToCombine().Count > 0 && mom.GetObjectsToCombine()[0] != null)
|
||||||
|
{
|
||||||
|
Renderer r = mom.GetObjectsToCombine()[0].GetComponent<Renderer>();
|
||||||
|
if (r == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Object " + mom.GetObjectsToCombine()[0] + " does not have a Renderer attached to it.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (r.sharedMaterial != null)
|
||||||
|
{
|
||||||
|
newMat = new Material(r.sharedMaterial);
|
||||||
|
//newMat.shader = r.sharedMaterial.shader;
|
||||||
|
MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, r.sharedMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("If you add objects to be combined before creating the Combined Material Assets, then Mesh Baker will create a result material that is a duplicate of the material on the first object to be combined. This saves time configuring the shader.");
|
||||||
|
}
|
||||||
|
if (newMat == null)
|
||||||
|
{
|
||||||
|
newMat = new Material(Shader.Find("Diffuse"));
|
||||||
|
}
|
||||||
|
AssetDatabase.CreateAsset(newMat, matNames[0]);
|
||||||
|
mom.resultMaterial = (Material)AssetDatabase.LoadAssetAtPath(matNames[0], typeof(Material));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//create the MB2_TextureBakeResults
|
||||||
|
string nmm = pth;
|
||||||
|
if (!allowOverwrite) nmm = AssetDatabase.GenerateUniqueAssetPath(nmm);
|
||||||
|
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<MB2_TextureBakeResults>(), nmm);
|
||||||
|
mom.textureBakeResults = (MB2_TextureBakeResults)AssetDatabase.LoadAssetAtPath(nmm, typeof(MB2_TextureBakeResults));
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MB3_TextureBaker> _getBakersFromTargets(UnityEngine.Object[] targs)
|
||||||
|
{
|
||||||
|
List<MB3_TextureBaker> outList = new List<MB3_TextureBaker>(targs.Length);
|
||||||
|
for (int i = 0; i < targs.Length; i++)
|
||||||
|
{
|
||||||
|
outList.Add((MB3_TextureBaker) targs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ValidatePlayerSettingsDefineSymbols()
|
||||||
|
{
|
||||||
|
// Check that the needed defines exist or are present when they should not be.
|
||||||
|
MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
|
||||||
|
BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
|
||||||
|
string scriptDefines = MBVersionEditor.GetScriptingDefineSymbolsFromTg(targetGroup);
|
||||||
|
|
||||||
|
string s = "";
|
||||||
|
if (pipelineType == MBVersion.PipelineType.HDRP)
|
||||||
|
{
|
||||||
|
if (!scriptDefines.Contains(MBVersion.MB_USING_HDRP))
|
||||||
|
{
|
||||||
|
s += "The GraphicsSettings -> Render Pipeline Asset is configured to use HDRP. Please add 'MB_USING_HDRP' to Player Settings -> Scripting Define Symbols for all the build platforms " +
|
||||||
|
" that you are targeting. If there are compile errors check that the MeshBakerCore.asmdef file has references for:\n\n" +
|
||||||
|
" Unity.RenderPipelines.HighDefinition.Runtime\n" +
|
||||||
|
" Unity.RenderPipelines.HighDefinition.Config.Runtime (Unity 2019.3+)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Type tp = Type.GetType("UnityEngine.Rendering.HighDefinition.HDAdditionalCameraData");
|
||||||
|
if (tp == null)
|
||||||
|
{
|
||||||
|
s += "The class 'HDAdditionalCameraData' cannot be found by the MeshBaker assembly. Ensure that the following assemblies are referenced by the MeshBaker.asmdef file: \n" +
|
||||||
|
" Unity.RenderPipelines.HighDefinition.Runtime\n" +
|
||||||
|
" Unity.RenderPipelines.HighDefinition.Config.Runtime (Unity 2019.3+)\n\n"+
|
||||||
|
"Or download the HDRP version of the package from the asset store.";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (scriptDefines.Contains(MBVersion.MB_USING_HDRP))
|
||||||
|
{
|
||||||
|
s += "Please remove 'MB_USING_HDRP' from Player Settings -> Scripting Define Symbols for the current build platform. If this define is present there may be compile errors because Mesh Baker tries to access classes which only exist in the HDRP API.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.Length > 0)
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3e6251fd17be4a142ab0827940bdba27
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB3_TextureBakerEditorInternal.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,304 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public static class MB_BatchPrefabBakerEditorFunctions
|
||||||
|
{
|
||||||
|
|
||||||
|
public static int EvalVersionPrefabLimit
|
||||||
|
{
|
||||||
|
get { return 5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateEmptyOutputPrefabs(string outputFolder, MB3_BatchPrefabBaker target)
|
||||||
|
{
|
||||||
|
string errorMessage;
|
||||||
|
bool isValidPath;
|
||||||
|
MB3_MeshBakerEditorFunctionsCore.SanitizeAndMakeFullPathRelativeToAssetsFolderAndValidate(outputFolder,
|
||||||
|
out errorMessage, out isValidPath);
|
||||||
|
if (!isValidPath)
|
||||||
|
{
|
||||||
|
Debug.LogError(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<GameObject> srcPrefabs = new HashSet<GameObject>();
|
||||||
|
if (outputFolder.StartsWith("Assets")) outputFolder = MB_BatchPrefabBakerEditorFunctionsCore.ConvertProjectRelativePathToFullPath(outputFolder);
|
||||||
|
int numCreated = 0;
|
||||||
|
int numSkippedSrcNull = 0;
|
||||||
|
int numSkippedSrcDuplicate = 0;
|
||||||
|
int numSkippedAlreadyExisted = 0;
|
||||||
|
MB3_BatchPrefabBaker prefabBaker = (MB3_BatchPrefabBaker)target;
|
||||||
|
for (int i = 0; i < prefabBaker.prefabRows.Length; i++)
|
||||||
|
{
|
||||||
|
if (prefabBaker.prefabRows[i].sourcePrefab != null)
|
||||||
|
{
|
||||||
|
if (srcPrefabs.Contains(prefabBaker.prefabRows[i].sourcePrefab))
|
||||||
|
{
|
||||||
|
Debug.LogError($"Skipping row {i} because the source prefab was a duplicate of a previous row.");
|
||||||
|
numSkippedSrcDuplicate++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srcPrefabs.Add(prefabBaker.prefabRows[i].sourcePrefab);
|
||||||
|
if (prefabBaker.prefabRows[i].resultPrefab == null)
|
||||||
|
{
|
||||||
|
string outName = outputFolder + "/" + prefabBaker.prefabRows[i].sourcePrefab.name + ".prefab";
|
||||||
|
outName = outName.Replace(Application.dataPath, "");
|
||||||
|
outName = "Assets" + outName;
|
||||||
|
outName = AssetDatabase.GenerateUniqueAssetPath(outName);
|
||||||
|
GameObject go = new GameObject(prefabBaker.prefabRows[i].sourcePrefab.name);
|
||||||
|
prefabBaker.prefabRows[i].resultPrefab = MBVersionEditor.PrefabUtility_CreatePrefab(outName, go);
|
||||||
|
GameObject.DestroyImmediate(go);
|
||||||
|
numCreated++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numSkippedAlreadyExisted++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numSkippedSrcNull++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string msg = String.Format("Created {0} prefabs. Skipped {1} because source prefab was null. Skipped {2} because source prefab was a duplicate. Skipped {3} because the result prefab was already assigned", numCreated, numSkippedSrcNull, numSkippedSrcDuplicate, numSkippedAlreadyExisted);
|
||||||
|
if (numSkippedSrcNull > 0 || numSkippedAlreadyExisted > 0)
|
||||||
|
{
|
||||||
|
Debug.LogError(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PopulatePrefabRowsFromTextureBaker(MB3_BatchPrefabBaker prefabBaker)
|
||||||
|
{
|
||||||
|
MB3_TextureBaker texBaker = prefabBaker.GetComponent<MB3_TextureBaker>();
|
||||||
|
List<GameObject> newPrefabs = new List<GameObject>();
|
||||||
|
List<GameObject> gos = texBaker.GetObjectsToCombine();
|
||||||
|
for (int i = 0; i < gos.Count; i++)
|
||||||
|
{
|
||||||
|
GameObject go = (GameObject)MBVersionEditor.PrefabUtility_FindPrefabRoot(gos[i]);
|
||||||
|
UnityEngine.Object obj = MBVersionEditor.PrefabUtility_GetCorrespondingObjectFromSource(go);
|
||||||
|
|
||||||
|
if (obj != null && obj is GameObject)
|
||||||
|
{
|
||||||
|
if (!newPrefabs.Contains((GameObject)obj)) newPrefabs.Add((GameObject)obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning(String.Format("Object {0} did not have a prefab", gos[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove prefabs that are already in the list of batch prefab baker's prefabs.
|
||||||
|
{
|
||||||
|
List<GameObject> tmpNewPrefabs = new List<GameObject>();
|
||||||
|
for (int i = 0; i < newPrefabs.Count; i++)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (int j = 0; j < prefabBaker.prefabRows.Length; j++)
|
||||||
|
{
|
||||||
|
if (prefabBaker.prefabRows[j].sourcePrefab == newPrefabs[i])
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
tmpNewPrefabs.Add(newPrefabs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newPrefabs = tmpNewPrefabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MB3_BatchPrefabBaker.MB3_PrefabBakerRow> newRows = new List<MB3_BatchPrefabBaker.MB3_PrefabBakerRow>();
|
||||||
|
if (prefabBaker.prefabRows == null) prefabBaker.prefabRows = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow[0];
|
||||||
|
newRows.AddRange(prefabBaker.prefabRows);
|
||||||
|
for (int i = 0; i < newPrefabs.Count; i++)
|
||||||
|
{
|
||||||
|
MB3_BatchPrefabBaker.MB3_PrefabBakerRow row = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow();
|
||||||
|
row.sourcePrefab = newPrefabs[i];
|
||||||
|
newRows.Add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Undo.RecordObject(prefabBaker, "Populate prefab rows");
|
||||||
|
prefabBaker.prefabRows = newRows.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void BakePrefabs(MB3_BatchPrefabBaker pb, bool doReplaceTargetPrefab)
|
||||||
|
{
|
||||||
|
if (pb.LOG_LEVEL >= MB2_LogLevel.info) Debug.Log("Batch baking prefabs");
|
||||||
|
|
||||||
|
if (MB3_MeshCombiner.EVAL_VERSION)
|
||||||
|
{
|
||||||
|
int numPrefabsLimit = EvalVersionPrefabLimit;
|
||||||
|
if (pb.prefabRows.Length > numPrefabsLimit)
|
||||||
|
{
|
||||||
|
Debug.LogError("The free version of mesh baker is limited to batch baking " + numPrefabsLimit +
|
||||||
|
" prefabs. The full version has no limit on the number of prefabs that can be baked. Delete the extra prefab rows before baking.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Application.isPlaying)
|
||||||
|
{
|
||||||
|
Debug.LogError("The BatchPrefabBaker cannot be run in play mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_MeshBaker mb = pb.GetComponent<MB3_MeshBaker>();
|
||||||
|
mb.UpgradeToCurrentVersionIfNecessary();
|
||||||
|
if (mb == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Prefab baker needs to be attached to a Game Object with a MB3_MeshBaker component.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.textureBakeResults == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Texture Bake Results is not set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numResultMats = mb.textureBakeResults.NumResultMaterials();
|
||||||
|
for (int i = 0; i < numResultMats; i++)
|
||||||
|
{
|
||||||
|
if (mb.textureBakeResults.GetCombinedMaterialForSubmesh(i) == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("The texture bake result had a null result material on submesh " + i + ". Try re-baking textures");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.meshCombiner.outputOption != MB2_OutputOptions.bakeMeshAssetsInPlace)
|
||||||
|
{
|
||||||
|
mb.meshCombiner.outputOption = MB2_OutputOptions.bakeMeshAssetsInPlace;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB2_TextureBakeResults tbr = mb.textureBakeResults;
|
||||||
|
|
||||||
|
HashSet<Mesh> sourceMeshes = new HashSet<Mesh>();
|
||||||
|
HashSet<Mesh> allResultMeshes = new HashSet<Mesh>();
|
||||||
|
|
||||||
|
//validate prefabs
|
||||||
|
for (int i = 0; i < pb.prefabRows.Length; i++)
|
||||||
|
{
|
||||||
|
if (pb.prefabRows[i] == null || pb.prefabRows[i].sourcePrefab == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Source Prefab on row " + i + " is not set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pb.prefabRows[i].resultPrefab == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Result Prefab on row " + i + " is not set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int j = i + 1; j < pb.prefabRows.Length; j++)
|
||||||
|
{
|
||||||
|
if (pb.prefabRows[i].sourcePrefab == pb.prefabRows[j].sourcePrefab)
|
||||||
|
{
|
||||||
|
Debug.LogError("Rows " + i + " and " + j + " contain the same source prefab");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j = 0; j < pb.prefabRows.Length; j++)
|
||||||
|
{
|
||||||
|
if (pb.prefabRows[i].sourcePrefab == pb.prefabRows[j].resultPrefab)
|
||||||
|
{
|
||||||
|
Debug.LogError("Row " + i + " source prefab is the same as row " + j + " result prefab");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MBVersionEditor.PrefabUtility_GetPrefabType(pb.prefabRows[i].sourcePrefab) != MB_PrefabType.modelPrefabAsset &&
|
||||||
|
MBVersionEditor.PrefabUtility_GetPrefabType(pb.prefabRows[i].sourcePrefab) != MB_PrefabType.prefabAsset)
|
||||||
|
{
|
||||||
|
Debug.LogError("Row " + i + " source prefab is not a prefab asset ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MBVersionEditor.PrefabUtility_GetPrefabType(pb.prefabRows[i].resultPrefab) != MB_PrefabType.modelPrefabAsset &&
|
||||||
|
MBVersionEditor.PrefabUtility_GetPrefabType(pb.prefabRows[i].resultPrefab) != MB_PrefabType.prefabAsset)
|
||||||
|
{
|
||||||
|
Debug.LogError("Row " + i + " result prefab is not a prefab asset");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject so = (GameObject)GameObject.Instantiate(pb.prefabRows[i].sourcePrefab);
|
||||||
|
GameObject ro = (GameObject)GameObject.Instantiate(pb.prefabRows[i].resultPrefab);
|
||||||
|
Renderer[] rs = (Renderer[])so.GetComponentsInChildren<Renderer>(true);
|
||||||
|
|
||||||
|
for (int j = 0; j < rs.Length; j++)
|
||||||
|
{
|
||||||
|
if (MB_BatchPrefabBakerEditorFunctionsCore.IsGoodToBake(rs[j], tbr))
|
||||||
|
{
|
||||||
|
sourceMeshes.Add(MB_Utility.GetMesh(rs[j].gameObject));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs = ro.GetComponentsInChildren<Renderer>(true);
|
||||||
|
|
||||||
|
for (int j = 0; j < rs.Length; j++)
|
||||||
|
{
|
||||||
|
Renderer r = rs[j];
|
||||||
|
if (r is MeshRenderer || r is SkinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
Mesh m = MB_Utility.GetMesh(r.gameObject);
|
||||||
|
if (m != null)
|
||||||
|
{
|
||||||
|
allResultMeshes.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject.DestroyImmediate(so); //todo should cache these and have a proper cleanup at end
|
||||||
|
GameObject.DestroyImmediate(ro);
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceMeshes.IntersectWith(allResultMeshes);
|
||||||
|
HashSet<Mesh> sourceMeshesThatAreUsedByResult = sourceMeshes;
|
||||||
|
if (sourceMeshesThatAreUsedByResult.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (Mesh m in sourceMeshesThatAreUsedByResult)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Mesh " + m + " is used by both the source and result prefabs. New meshes will be created.");
|
||||||
|
}
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MB_BatchPrefabBakerEditorFunctionsCore.UnityTransform> unityTransforms = new List<MB_BatchPrefabBakerEditorFunctionsCore.UnityTransform>();
|
||||||
|
// Bake the meshes using the meshBaker component one prefab at a time
|
||||||
|
// Version check
|
||||||
|
for (int prefabIdx = 0; prefabIdx < pb.prefabRows.Length; prefabIdx++)
|
||||||
|
{
|
||||||
|
if (doReplaceTargetPrefab)
|
||||||
|
{
|
||||||
|
MB_BatchPrefabBakerEditorFunctionsCore._ProcessPrefabRowReplaceTargetPrefab(pb.LOG_LEVEL, pb.prefabRows[prefabIdx].sourcePrefab, pb.prefabRows[prefabIdx].resultPrefab, tbr, unityTransforms, (MB3_MeshCombinerSingle) mb.meshCombiner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MB_BatchPrefabBakerEditorFunctionsCore._ProcessPrefabRowOnlyMeshesAndMaterials(pb.LOG_LEVEL, pb.prefabRows[prefabIdx].sourcePrefab, pb.prefabRows[prefabIdx].resultPrefab, tbr, unityTransforms, (MB3_MeshCombinerSingle) mb.meshCombiner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
mb.ClearMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 372fcc119f8877c49b446a03f9603644
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB_BatchPrefabBakerEditorFunctions.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Build.Reporting;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
class MB_BuildPreprocessChecker : IPreprocessBuildWithReport
|
||||||
|
{
|
||||||
|
public int callbackOrder { get { return 0; } }
|
||||||
|
public void OnPreprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
string msg = MB3_TextureBakerEditorInternal.ValidatePlayerSettingsDefineSymbols();
|
||||||
|
if (msg != null) Debug.LogError(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 44eb70764e9827e4588ea4a1c5888b59
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB_BuildPreprocessChecker.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB_ReplacePrefabsInSceneEditorWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private MB_ReplacePrefabsSettings model;
|
||||||
|
private SerializedObject soModel;
|
||||||
|
private SerializedProperty prefabPairs;
|
||||||
|
private SerializedProperty reverseSrcAndTarg;
|
||||||
|
private SerializedProperty enforceSrcAndTargHaveSameStructure;
|
||||||
|
Vector2 scrollViewPos;
|
||||||
|
private string errorMessages;
|
||||||
|
private string infoMessages;
|
||||||
|
|
||||||
|
private GUIContent GUI_replacePefabsInScene = new GUIContent("Replace Prefabs In Scene", "This will find all instances of the source prefabs in the scene and replace them with instances of the target prefabs." +
|
||||||
|
"Will attempt to copy component settings from the source to the target (ignoring references to project assets, those are left alone)." +
|
||||||
|
"Prefabs should have identical hierarchy and components for the copy component settings to work.");
|
||||||
|
private GUIContent GUI_switchSrcAndTarget = new GUIContent("Switch Source and Target Prefabs", "If this is checked then search the scene for target prefabs and replace them with source prefabs.");
|
||||||
|
private GUIContent GUI_enforceSrcAndTargetHaveSameStructure = new GUIContent("Enforce Source And Target Have Same Structure", "If this is checked then prefab instances will only be replaced if they have the same hierarchy and components. \n\n" +
|
||||||
|
"If it is not checked then prefabs can be very different and ONLY THE TRANSFORM, LAYERS, TAGS & STATIC FLAGS ARE COPIED.\n\n" +
|
||||||
|
"WARNING THIS IS A DESTRUCTIVE OPERARTION! BACK UP YOUR SCENE FIRST.");
|
||||||
|
|
||||||
|
[MenuItem("Window/Mesh Baker/Replace Prefabs In Scene")]
|
||||||
|
public static void ShowWindow()
|
||||||
|
{
|
||||||
|
GetWindow<MB_ReplacePrefabsInSceneEditorWindow>(true, "Replace Prefabs In Scene", true).Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowWindow(MB3_BatchPrefabBaker.MB3_PrefabBakerRow[] prefabPairs)
|
||||||
|
{
|
||||||
|
MB_ReplacePrefabsInSceneEditorWindow window = GetWindow<MB_ReplacePrefabsInSceneEditorWindow>(true, "Replace Prefabs In Scene", true);
|
||||||
|
window.Show();
|
||||||
|
MB_ReplacePrefabsSettings.PrefabPair[] pps = new MB_ReplacePrefabsSettings.PrefabPair[prefabPairs.Length];
|
||||||
|
for (int i = 0; i < pps.Length; i++)
|
||||||
|
{
|
||||||
|
pps[i] = new MB_ReplacePrefabsSettings.PrefabPair()
|
||||||
|
{
|
||||||
|
enabled = true,
|
||||||
|
srcPrefab = prefabPairs[i].sourcePrefab,
|
||||||
|
targPrefab = prefabPairs[i].resultPrefab,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
window.model.prefabsToSwitch = pps;
|
||||||
|
window.soModel.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitModel()
|
||||||
|
{
|
||||||
|
soModel = new SerializedObject(model);
|
||||||
|
prefabPairs = soModel.FindProperty("prefabsToSwitch");
|
||||||
|
reverseSrcAndTarg = soModel.FindProperty("reverseSrcAndTarg");
|
||||||
|
enforceSrcAndTargHaveSameStructure = soModel.FindProperty("enforceSrcAndTargHaveSameStructure");
|
||||||
|
infoMessages = "";
|
||||||
|
errorMessages = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
minSize = new Vector2(800f, 290f);
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
model = ScriptableObject.CreateInstance<MB_ReplacePrefabsSettings>();
|
||||||
|
|
||||||
|
// Set the Hide flags so that this windows data not destroyed when entering playmode or a new scene.
|
||||||
|
model.hideFlags = HideFlags.DontSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
MB_ReplacePrefabsSettings newModel = (MB_ReplacePrefabsSettings)EditorGUILayout.ObjectField("Settings", model, typeof(MB_ReplacePrefabsSettings), false);
|
||||||
|
if (newModel != model)
|
||||||
|
{
|
||||||
|
if (newModel != null)
|
||||||
|
{
|
||||||
|
model = newModel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (model == null) model = ScriptableObject.CreateInstance<MB_ReplacePrefabsSettings>();
|
||||||
|
|
||||||
|
// Set the Hide flags so that this windows data not destroyed when entering playmode or a new scene.
|
||||||
|
model.hideFlags = HideFlags.DontSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model != null)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Save Settings", GUILayout.Width(200)))
|
||||||
|
{
|
||||||
|
string path = EditorUtility.SaveFilePanel("Save Settings", Application.dataPath, "ReplacePrefabSettings", "asset");
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
model.hideFlags = HideFlags.None;
|
||||||
|
string relativepath = "Assets" + path.Substring(Application.dataPath.Length);
|
||||||
|
Debug.Log("Saved: " + relativepath);
|
||||||
|
AssetDatabase.CreateAsset(model, relativepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
soModel.Update();
|
||||||
|
if (GUILayout.Button(GUI_replacePefabsInScene))
|
||||||
|
{
|
||||||
|
if (EditorUtility.DisplayDialog("Replace Prefabs In Scene",
|
||||||
|
"Are you sure you want to replace all source prefab instances with the target prefab instances in this scene? \n\n" +
|
||||||
|
"It is highly recommended that you back up your scene before doing this.", "OK", "Cancel"))
|
||||||
|
{
|
||||||
|
ReplacePrefabsInScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float labelWidth = EditorGUIUtility.labelWidth;
|
||||||
|
EditorGUIUtility.labelWidth = 300f;
|
||||||
|
EditorGUILayout.PropertyField(reverseSrcAndTarg, GUI_switchSrcAndTarget);
|
||||||
|
EditorGUILayout.PropertyField(enforceSrcAndTargHaveSameStructure, GUI_enforceSrcAndTargetHaveSameStructure);
|
||||||
|
EditorGUIUtility.labelWidth = labelWidth;
|
||||||
|
if (infoMessages != "" || errorMessages != "")
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox(errorMessages + "\n" + infoMessages, errorMessages == "" ? MessageType.Info : MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollViewPos = EditorGUILayout.BeginScrollView(scrollViewPos);
|
||||||
|
EditorGUILayout.PropertyField(prefabPairs, true);
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
soModel.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReplacePrefabsInScene()
|
||||||
|
{
|
||||||
|
MB_ReplacePrefabsInScene rp = new MB_ReplacePrefabsInScene();
|
||||||
|
rp.replaceEnforceStructure = model.enforceSrcAndTargHaveSameStructure;
|
||||||
|
int numReplaced = 0;
|
||||||
|
int numErrors = 0;
|
||||||
|
errorMessages = "";
|
||||||
|
infoMessages = "";
|
||||||
|
EditorUtility.DisplayProgressBar("Replace Prefabs In Scene", "Replace Prefabs In Scene", 0);
|
||||||
|
for (int i = 0; i < model.prefabsToSwitch.Length; i++)
|
||||||
|
{
|
||||||
|
MB_ReplacePrefabsSettings.PrefabPair pp = model.prefabsToSwitch[i];
|
||||||
|
pp.objsWithErrors.Clear();
|
||||||
|
if (pp.enabled)
|
||||||
|
{
|
||||||
|
GameObject src, targ;
|
||||||
|
if (model.reverseSrcAndTarg)
|
||||||
|
{
|
||||||
|
src = pp.targPrefab;
|
||||||
|
targ = pp.srcPrefab;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src = pp.srcPrefab;
|
||||||
|
targ = pp.targPrefab;
|
||||||
|
}
|
||||||
|
|
||||||
|
numReplaced += rp.ReplacePrefabInstancesInScene(src, targ, pp.objsWithErrors);
|
||||||
|
numErrors += pp.objsWithErrors.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.DisplayProgressBar("Replace Prefabs In Scene", "Replace In Scene: " + pp.srcPrefab, (float)i / (float)model.prefabsToSwitch.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
|
||||||
|
Debug.Log("Total prefab instances replaced: " + numReplaced);
|
||||||
|
infoMessages = "Total prefab instances replaced: " + numReplaced;
|
||||||
|
if (numErrors > 0)
|
||||||
|
{
|
||||||
|
errorMessages = "There were errors replacing some of the prefabs in the scene. See console for details.";
|
||||||
|
}
|
||||||
|
|
||||||
|
soModel.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 568dea53a514f9a4fa3a4483bad6a0b6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB_ReplacePrefabsInSceneEditorWindow.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[System.Serializable]
|
||||||
|
public class MB_ReplacePrefabsSettings : ScriptableObject
|
||||||
|
{
|
||||||
|
[System.Serializable]
|
||||||
|
public class PrefabPair
|
||||||
|
{
|
||||||
|
public bool enabled = true;
|
||||||
|
public GameObject srcPrefab;
|
||||||
|
public GameObject targPrefab;
|
||||||
|
public List<MB_ReplacePrefabsInScene.Error> objsWithErrors = new List<MB_ReplacePrefabsInScene.Error>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrefabPair[] prefabsToSwitch = new PrefabPair[0];
|
||||||
|
|
||||||
|
public bool reverseSrcAndTarg;
|
||||||
|
|
||||||
|
public bool enforceSrcAndTargHaveSameStructure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f2e44f04becd89f469c0431787b827bb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB_ReplacePrefabsSettings.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,567 @@
|
|||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MB_TextureBakerEditorConfigureMultiMaterials
|
||||||
|
{
|
||||||
|
private static GUIContent gc_moveOneMappingUp = new GUIContent("\u2191", "move this material up to previous mapping."),
|
||||||
|
gc_moveOneMappingDown = new GUIContent("\u2193", "move this material down to next mapping."),
|
||||||
|
gc_newCombinedMaterial = new GUIContent("new", "Create a new combined material for this mapping.");
|
||||||
|
|
||||||
|
private static GUIContent[] gc_SourceMatOptions = new GUIContent[]
|
||||||
|
{
|
||||||
|
new GUIContent("...", " Source material actions. "),
|
||||||
|
new GUIContent("move up to previous submesh", "move this material up to previous submesh."),
|
||||||
|
new GUIContent("move down to next submesh", "move this material down to next submesh."),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static GUIContent[] gc_MappingOptions = new GUIContent[]
|
||||||
|
{
|
||||||
|
new GUIContent("...", " Result material actions. "),
|
||||||
|
new GUIContent("move submesh up", "Move this submesh up."),
|
||||||
|
new GUIContent("move submesh down", "Move this submesh down."),
|
||||||
|
new GUIContent("delete submesh", "Delete this submesh."),
|
||||||
|
new GUIContent("insert new submesh", "Insert a new submesh after this submesh."),
|
||||||
|
new GUIContent("create combined material", "Create a combined material for this submesh."),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static GUIContent sourceMaterialsLabel = new GUIContent(
|
||||||
|
"Source Materials",
|
||||||
|
"This list of source materials will be combined into a combined-material for this submesh."
|
||||||
|
);
|
||||||
|
|
||||||
|
public static void DrawMapping(MB3_TextureBaker momm, MB3_TextureBakerEditorInternal tbEditor, int rowNum)
|
||||||
|
{
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
if (rowNum % 2 == 1)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(tbEditor.editorStyles.multipleMaterialBackgroundStyle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(tbEditor.editorStyles.multipleMaterialBackgroundStyleDarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
string s = "";
|
||||||
|
if (rowNum < momm.resultMaterials.Length && momm.resultMaterials[rowNum] != null && momm.resultMaterials[rowNum].combinedMaterial != null) s = momm.resultMaterials[rowNum].combinedMaterial.shader.ToString();
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("---------- submesh:" + rowNum + " " + s, EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
int myAction = 0;
|
||||||
|
myAction = EditorGUILayout.Popup(myAction, gc_MappingOptions, GUILayout.MaxWidth(60f));
|
||||||
|
if (myAction != 0)
|
||||||
|
{
|
||||||
|
if (myAction == 1) // Move submesh up
|
||||||
|
{
|
||||||
|
if (rowNum > 0)
|
||||||
|
{
|
||||||
|
tbEditor.resultMaterials.MoveArrayElement(rowNum, rowNum - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myAction == 2) // Move submesh down
|
||||||
|
{
|
||||||
|
if (rowNum < tbEditor.resultMaterials.arraySize - 1)
|
||||||
|
{
|
||||||
|
tbEditor.resultMaterials.MoveArrayElement(rowNum, rowNum + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myAction == 3) // Delete submesh
|
||||||
|
{
|
||||||
|
tbEditor.resultMaterials.DeleteArrayElementAtIndex(rowNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myAction == 4) // Insert new submesh
|
||||||
|
{
|
||||||
|
tbEditor.resultMaterials.InsertArrayElementAtIndex(rowNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myAction == 5) // Create combined material
|
||||||
|
{
|
||||||
|
_CreateCombinedMaterialForSubmesh(momm, tbEditor, rowNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
if (rowNum < tbEditor.resultMaterials.arraySize)
|
||||||
|
{
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
SerializedProperty resMat = tbEditor.resultMaterials.GetArrayElementAtIndex(rowNum);
|
||||||
|
SerializedProperty combinedMatProp = resMat.FindPropertyRelative("combinedMaterial");
|
||||||
|
EditorGUILayout.PropertyField(combinedMatProp);
|
||||||
|
EditorGUILayout.PropertyField(resMat.FindPropertyRelative("considerMeshUVs"));
|
||||||
|
DrawMappingSourceMaterials(resMat, tbEditor, rowNum);
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _CreateCombinedMaterialForSubmesh(MB3_TextureBaker momm, MB3_TextureBakerEditorInternal tbEditor, int rowNum)
|
||||||
|
{
|
||||||
|
string newMatPath = EditorUtility.SaveFilePanelInProject("Asset name", "", "mat", "Enter a name for the baked material");
|
||||||
|
if (newMatPath != null && newMatPath.Length > 4)
|
||||||
|
{
|
||||||
|
Material newMat = null;
|
||||||
|
{
|
||||||
|
if (momm.resultMaterials[rowNum].sourceMaterials.Count > 0)
|
||||||
|
{
|
||||||
|
Material sourceMat = momm.resultMaterials[rowNum].sourceMaterials[0];
|
||||||
|
if (sourceMat != null)
|
||||||
|
{
|
||||||
|
newMat = new Material(sourceMat);
|
||||||
|
MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, sourceMat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newMat == null)
|
||||||
|
{
|
||||||
|
newMat = new Material(Shader.Find("Diffuse"));
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.CreateAsset(newMat, newMatPath);
|
||||||
|
var assetRef = (Material)AssetDatabase.LoadAssetAtPath(newMatPath, typeof(Material));
|
||||||
|
SerializedProperty resMat = tbEditor.resultMaterials.GetArrayElementAtIndex(rowNum);
|
||||||
|
SerializedProperty combinedMatProp = resMat.FindPropertyRelative("combinedMaterial");
|
||||||
|
combinedMatProp.objectReferenceValue = assetRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawMappingSourceMaterials(SerializedProperty resMat, MB3_TextureBakerEditorInternal tbEditor, int rowNum)
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField(sourceMaterialsLabel);
|
||||||
|
SerializedProperty sourceMats = resMat.FindPropertyRelative("sourceMaterials");
|
||||||
|
bool showListSize = true;
|
||||||
|
EditorGUI.indentLevel += 1;
|
||||||
|
|
||||||
|
sourceMats.isExpanded = true;
|
||||||
|
if (sourceMats.isExpanded)
|
||||||
|
{
|
||||||
|
if (showListSize)
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(sourceMats.FindPropertyRelative("Array.size"));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < sourceMats.arraySize; i++)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PropertyField(sourceMats.GetArrayElementAtIndex(i));
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
{
|
||||||
|
int myAction = 0;
|
||||||
|
myAction = EditorGUILayout.Popup(myAction, gc_SourceMatOptions, GUILayout.MaxWidth(60f));
|
||||||
|
if (myAction != 0)
|
||||||
|
{
|
||||||
|
if (myAction == 1) // move source mat up one mapping
|
||||||
|
{
|
||||||
|
if (rowNum > 0)
|
||||||
|
{
|
||||||
|
SerializedProperty resMatUp = tbEditor.resultMaterials.GetArrayElementAtIndex(rowNum - 1);
|
||||||
|
SerializedProperty sourceMatsUp = resMatUp.FindPropertyRelative("sourceMaterials");
|
||||||
|
int idx = sourceMatsUp.arraySize;
|
||||||
|
sourceMatsUp.InsertArrayElementAtIndex(idx);
|
||||||
|
sourceMatsUp.GetArrayElementAtIndex(idx).objectReferenceValue = sourceMats.GetArrayElementAtIndex(i).objectReferenceValue;
|
||||||
|
sourceMats.DeleteArrayElementAtIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myAction == 2) // move source mat down one mapping
|
||||||
|
{
|
||||||
|
if (rowNum < tbEditor.resultMaterials.arraySize - 1)
|
||||||
|
{
|
||||||
|
SerializedProperty resMatDown = tbEditor.resultMaterials.GetArrayElementAtIndex(rowNum + 1);
|
||||||
|
SerializedProperty sourceMatsDown = resMatDown.FindPropertyRelative("sourceMaterials");
|
||||||
|
|
||||||
|
sourceMatsDown.InsertArrayElementAtIndex(0);
|
||||||
|
sourceMatsDown.GetArrayElementAtIndex(0).objectReferenceValue = sourceMats.GetArrayElementAtIndex(i).objectReferenceValue;
|
||||||
|
sourceMats.DeleteArrayElementAtIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawMultipleMaterialsMappings(MB3_TextureBaker momm, SerializedObject textureBaker, MB3_TextureBakerEditorInternal tbEditor)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(tbEditor.editorStyles.multipleMaterialBackgroundStyle);
|
||||||
|
EditorGUILayout.LabelField("Source Material To Combined Mapping", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
float oldLabelWidth = EditorGUIUtility.labelWidth;
|
||||||
|
EditorGUIUtility.labelWidth = 300;
|
||||||
|
EditorGUILayout.PropertyField(tbEditor.doMultiMaterialIfOBUVs, MB3_TextureBakerEditorInternal.gc_DoMultiMaterialSplitAtlasesIfOBUVs);
|
||||||
|
EditorGUILayout.PropertyField(tbEditor.doMultiMaterialSplitAtlasesIfTooBig, MB3_TextureBakerEditorInternal.gc_DoMultiMaterialSplitAtlasesIfTooBig);
|
||||||
|
EditorGUIUtility.labelWidth = oldLabelWidth;
|
||||||
|
|
||||||
|
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.configAtlasMultiMatsFromObjsContent))
|
||||||
|
{
|
||||||
|
MB_TextureBakerEditorConfigureMultiMaterials.ConfigureMutiMaterialsFromObjsToCombine(momm, tbEditor.resultMaterials, textureBaker);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
tbEditor.resultMaterialsFoldout = EditorGUILayout.Foldout(tbEditor.resultMaterialsFoldout, MB3_TextureBakerEditorInternal.combinedMaterialsGUIContent);
|
||||||
|
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.insertContent, EditorStyles.miniButtonLeft, MB3_TextureBakerEditorInternal.buttonWidth))
|
||||||
|
{
|
||||||
|
if (tbEditor.resultMaterials.arraySize == 0)
|
||||||
|
{
|
||||||
|
momm.resultMaterials = new MB_MultiMaterial[1];
|
||||||
|
momm.resultMaterials[0] = new MB_MultiMaterial();
|
||||||
|
momm.resultMaterials[0].considerMeshUVs = momm.fixOutOfBoundsUVs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int idx = tbEditor.resultMaterials.arraySize - 1;
|
||||||
|
tbEditor.resultMaterials.InsertArrayElementAtIndex(idx);
|
||||||
|
tbEditor.resultMaterials.GetArrayElementAtIndex(idx + 1).FindPropertyRelative("considerMeshUVs").boolValue = momm.fixOutOfBoundsUVs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.deleteContent, EditorStyles.miniButtonRight, MB3_TextureBakerEditorInternal.buttonWidth)
|
||||||
|
&& tbEditor.resultMaterials.arraySize > 0)
|
||||||
|
{
|
||||||
|
tbEditor.resultMaterials.DeleteArrayElementAtIndex(tbEditor.resultMaterials.arraySize - 1);
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
if (tbEditor.resultMaterialsFoldout)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < tbEditor.resultMaterials.arraySize; i++)
|
||||||
|
{
|
||||||
|
DrawMapping(momm, tbEditor, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work */
|
||||||
|
public static void ConfigureMutiMaterialsFromObjsToCombine2(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
|
||||||
|
{
|
||||||
|
if (mom.GetObjectsToCombine().Count == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("You need to add some objects to combine before building the multi material list.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resultMaterials.arraySize > 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mom.textureBakeResults == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Texture Bake Result asset must be set before using this operation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//validate that the objects to be combined are valid
|
||||||
|
for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
|
||||||
|
{
|
||||||
|
GameObject go = mom.GetObjectsToCombine()[i];
|
||||||
|
if (go == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Null object in list of objects to combine at position " + i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Renderer r = go.GetComponent<Renderer>();
|
||||||
|
if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
|
||||||
|
{
|
||||||
|
Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (r.sharedMaterial == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IGroupByFilter[] filters = new IGroupByFilter[3];
|
||||||
|
filters[0] = new GroupByOutOfBoundsUVs();
|
||||||
|
filters[1] = new GroupByShader();
|
||||||
|
filters[2] = new MB3_GroupByTransparency();
|
||||||
|
|
||||||
|
List<GameObjectFilterInfo> gameObjects = new List<GameObjectFilterInfo>();
|
||||||
|
HashSet<GameObject> objectsAlreadyIncludedInBakers = new HashSet<GameObject>();
|
||||||
|
for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
|
||||||
|
{
|
||||||
|
GameObjectFilterInfo goaw = new GameObjectFilterInfo(mom.GetObjectsToCombine()[i], objectsAlreadyIncludedInBakers, filters);
|
||||||
|
if (goaw.materials.Length > 0) //don't consider renderers with no materials
|
||||||
|
{
|
||||||
|
gameObjects.Add(goaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//analyse meshes
|
||||||
|
Dictionary<int, MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = new Dictionary<int, MB_Utility.MeshAnalysisResult>();
|
||||||
|
int totalVerts = 0;
|
||||||
|
for (int i = 0; i < gameObjects.Count; i++)
|
||||||
|
{
|
||||||
|
//string rpt = String.Format("Processing {0} [{1} of {2}]", gameObjects[i].go.name, i, gameObjects.Count);
|
||||||
|
//EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " A", .6f);
|
||||||
|
Mesh mm = MB_Utility.GetMesh(gameObjects[i].go);
|
||||||
|
int nVerts = 0;
|
||||||
|
if (mm != null)
|
||||||
|
{
|
||||||
|
nVerts += mm.vertexCount;
|
||||||
|
MB_Utility.MeshAnalysisResult mar;
|
||||||
|
if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar))
|
||||||
|
{
|
||||||
|
|
||||||
|
//EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f);
|
||||||
|
MB_Utility.hasOutOfBoundsUVs(mm, ref mar);
|
||||||
|
//Rect dummy = mar.uvRect;
|
||||||
|
MB_Utility.doSubmeshesShareVertsOrTris(mm, ref mar);
|
||||||
|
meshAnalysisResultCache.Add(mm.GetInstanceID(), mar);
|
||||||
|
}
|
||||||
|
if (mar.hasOutOfBoundsUVs)
|
||||||
|
{
|
||||||
|
int w = (int)mar.uvRect.width;
|
||||||
|
int h = (int)mar.uvRect.height;
|
||||||
|
gameObjects[i].outOfBoundsUVs = true;
|
||||||
|
gameObjects[i].warning.AppendLine(" [WARNING: has uvs outside the range (0,1) tex is tiled " + w + "x" + h + " times]");
|
||||||
|
}
|
||||||
|
if (mar.hasOverlappingSubmeshVerts)
|
||||||
|
{
|
||||||
|
gameObjects[i].submeshesOverlap = true;
|
||||||
|
gameObjects[i].warning.AppendLine(" [WARNING: Submeshes share verts or triangles. 'Multiple Combined Materials' feature may not work.]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalVerts += nVerts;
|
||||||
|
//EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Validate OBuvs Multi Material", .6f);
|
||||||
|
Renderer mr = gameObjects[i].go.GetComponent<Renderer>();
|
||||||
|
if (!MB_Utility.AreAllSharedMaterialsDistinct(mr.sharedMaterials))
|
||||||
|
{
|
||||||
|
gameObjects[i].warning.AppendLine(" [WARNING: Object uses same material on multiple submeshes. This may produce poor results when used with multiple materials or Consider Mesh UVs.]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GameObjectFilterInfo> objsNotAddedToBaker = new List<GameObjectFilterInfo>();
|
||||||
|
|
||||||
|
Dictionary<GameObjectFilterInfo, List<List<GameObjectFilterInfo>>> gs2bakeGroupMap = MB3_MeshBakerEditorWindowAnalyseSceneTab.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize);
|
||||||
|
|
||||||
|
mom.resultMaterials = new MB_MultiMaterial[gs2bakeGroupMap.Keys.Count];
|
||||||
|
string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults);
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(pth);
|
||||||
|
string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
|
||||||
|
int k = 0;
|
||||||
|
foreach (GameObjectFilterInfo m in gs2bakeGroupMap.Keys)
|
||||||
|
{
|
||||||
|
MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
|
||||||
|
mm.sourceMaterials = new List<Material>();
|
||||||
|
mm.sourceMaterials.Add(m.materials[0]);
|
||||||
|
string matName = folderPath + baseName + "-mat" + k + ".mat";
|
||||||
|
Material newMat = new Material(Shader.Find("Diffuse"));
|
||||||
|
MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]);
|
||||||
|
AssetDatabase.CreateAsset(newMat, matName);
|
||||||
|
mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//posibilities
|
||||||
|
// using fixOutOfBoundsUVs or not
|
||||||
|
//
|
||||||
|
public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
|
||||||
|
{
|
||||||
|
if (mom.GetObjectsToCombine().Count == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("You need to add some objects to combine before building the multi material list.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resultMaterials.arraySize > 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mom.textureBakeResults == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Texture Bake Result asset must be set before using this operation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List<List<Material>>> shader2Material_map = new Dictionary<MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List<List<Material>>>();
|
||||||
|
Dictionary<Material, Mesh> obUVobject2mesh_map = new Dictionary<Material, Mesh>();
|
||||||
|
|
||||||
|
//validate that the objects to be combined are valid
|
||||||
|
for (int goIdx = 0; goIdx < mom.GetObjectsToCombine().Count; goIdx++)
|
||||||
|
{
|
||||||
|
GameObject go = mom.GetObjectsToCombine()[goIdx];
|
||||||
|
if (go == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Null object in list of objects to combine at position " + goIdx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Renderer r = go.GetComponent<Renderer>();
|
||||||
|
if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
|
||||||
|
{
|
||||||
|
Debug.LogError("GameObject at position " + goIdx + " in list of objects to combine did not have a renderer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int matIdx = 0; matIdx < r.sharedMaterials.Length; matIdx++)
|
||||||
|
{
|
||||||
|
if (r.sharedMaterials[matIdx] == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("GameObject " + go + " at position " + goIdx + " in list of objects to combine has one or more null materials");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
|
||||||
|
if (mom.doMultiMaterialSplitAtlasesIfOBUVs)
|
||||||
|
{
|
||||||
|
for (int goIdx = 0; goIdx < mom.GetObjectsToCombine().Count; goIdx++)
|
||||||
|
{
|
||||||
|
GameObject go = mom.GetObjectsToCombine()[goIdx];
|
||||||
|
Mesh m = MB_Utility.GetMesh(go);
|
||||||
|
MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
|
||||||
|
Renderer r = go.GetComponent<Renderer>();
|
||||||
|
for (int matIdx = 0; matIdx < r.sharedMaterials.Length; matIdx++)
|
||||||
|
{
|
||||||
|
if (MB_Utility.hasOutOfBoundsUVs(m, ref dummyMar, matIdx))
|
||||||
|
{
|
||||||
|
if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[matIdx]))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Object " + go + " submesh " + matIdx + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the Consider Mesh UVs feature which will bake the tiling");
|
||||||
|
obUVobject2mesh_map.Add(r.sharedMaterials[matIdx], m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//second pass put other materials without OB uvs in a shader to material map
|
||||||
|
for (int goIdx = 0; goIdx < mom.GetObjectsToCombine().Count; goIdx++)
|
||||||
|
{
|
||||||
|
Renderer r = mom.GetObjectsToCombine()[goIdx].GetComponent<Renderer>();
|
||||||
|
for (int matIdx = 0; matIdx < r.sharedMaterials.Length; matIdx++)
|
||||||
|
{
|
||||||
|
if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[matIdx]))
|
||||||
|
{ //if not already added
|
||||||
|
if (r.sharedMaterials[matIdx] == null) continue;
|
||||||
|
List<List<Material>> binsOfMatsThatUseShader = null;
|
||||||
|
MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo newKey = new MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo(r.sharedMaterials[matIdx].shader, r.sharedMaterials[matIdx]);
|
||||||
|
if (!shader2Material_map.TryGetValue(newKey, out binsOfMatsThatUseShader))
|
||||||
|
{
|
||||||
|
binsOfMatsThatUseShader = new List<List<Material>>();
|
||||||
|
binsOfMatsThatUseShader.Add(new List<Material>());
|
||||||
|
shader2Material_map.Add(newKey, binsOfMatsThatUseShader);
|
||||||
|
}
|
||||||
|
if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[matIdx])) binsOfMatsThatUseShader[0].Add(r.sharedMaterials[matIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numResMats = shader2Material_map.Count;
|
||||||
|
//third pass for each shader grouping check how big the atlas would be and group into bins that would fit in an atlas
|
||||||
|
if (mom.doMultiMaterialSplitAtlasesIfTooBig)
|
||||||
|
{
|
||||||
|
if (mom.packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numResMats = 0;
|
||||||
|
foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo sh in shader2Material_map.Keys)
|
||||||
|
{
|
||||||
|
List<List<Material>> binsOfMatsThatUseShader = shader2Material_map[sh];
|
||||||
|
List<Material> allMatsThatUserShader = binsOfMatsThatUseShader[0];//at this point everything is in the same list
|
||||||
|
binsOfMatsThatUseShader.RemoveAt(0);
|
||||||
|
MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
|
||||||
|
combiner.saveAtlasesAsAssets = false;
|
||||||
|
if (allMatsThatUserShader.Count > 1) combiner.fixOutOfBoundsUVs = mom.fixOutOfBoundsUVs;
|
||||||
|
else combiner.fixOutOfBoundsUVs = false;
|
||||||
|
|
||||||
|
// Do the texture pack
|
||||||
|
List<AtlasPackingResult> packingResults = new List<AtlasPackingResult>();
|
||||||
|
Material tempMat = new Material(sh.shader);
|
||||||
|
MB_AtlasesAndRects atlasesAndRects = new MB_AtlasesAndRects();
|
||||||
|
combiner.CombineTexturesIntoAtlases(null, atlasesAndRects, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, mom.texturePropNamesToIgnore, null, packingResults,
|
||||||
|
onlyPackRects: true, splitAtlasWhenPackingIfTooBig: true);
|
||||||
|
for (int aprIdx = 0; aprIdx < packingResults.Count; aprIdx++)
|
||||||
|
{
|
||||||
|
|
||||||
|
List<MB_MaterialAndUVRect> matsData = (List<MB_MaterialAndUVRect>)packingResults[aprIdx].data;
|
||||||
|
List<Material> mats = new List<Material>();
|
||||||
|
for (int mdIdx = 0; mdIdx < matsData.Count; mdIdx++)
|
||||||
|
{
|
||||||
|
Material mat = matsData[mdIdx].material;
|
||||||
|
if (!mats.Contains(mat))
|
||||||
|
{
|
||||||
|
mats.Add(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binsOfMatsThatUseShader.Add(mats);
|
||||||
|
}
|
||||||
|
numResMats += binsOfMatsThatUseShader.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the result materials
|
||||||
|
if (shader2Material_map.Count == 0 && obUVobject2mesh_map.Count == 0) Debug.LogError("Found no materials in list of objects to combine");
|
||||||
|
mom.resultMaterials = new MB_MultiMaterial[numResMats + obUVobject2mesh_map.Count];
|
||||||
|
string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults);
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(pth);
|
||||||
|
string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
|
||||||
|
int k = 0;
|
||||||
|
foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo sh in shader2Material_map.Keys)
|
||||||
|
{
|
||||||
|
foreach (List<Material> matsThatUse in shader2Material_map[sh])
|
||||||
|
{
|
||||||
|
MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
|
||||||
|
mm.sourceMaterials = matsThatUse;
|
||||||
|
if (mm.sourceMaterials.Count == 1)
|
||||||
|
{
|
||||||
|
mm.considerMeshUVs = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mm.considerMeshUVs = mom.fixOutOfBoundsUVs;
|
||||||
|
}
|
||||||
|
string matName = folderPath + baseName + "-mat" + k + ".mat";
|
||||||
|
Material newMat = new Material(Shader.Find("Diffuse"));
|
||||||
|
if (matsThatUse.Count > 0 && matsThatUse[0] != null)
|
||||||
|
{
|
||||||
|
MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
|
||||||
|
}
|
||||||
|
AssetDatabase.CreateAsset(newMat, matName);
|
||||||
|
mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (Material m in obUVobject2mesh_map.Keys)
|
||||||
|
{
|
||||||
|
MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
|
||||||
|
mm.sourceMaterials = new List<Material>();
|
||||||
|
mm.sourceMaterials.Add(m);
|
||||||
|
mm.considerMeshUVs = false;
|
||||||
|
string matName = folderPath + baseName + "-mat" + k + ".mat";
|
||||||
|
Material newMat = new Material(Shader.Find("Diffuse"));
|
||||||
|
MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m);
|
||||||
|
AssetDatabase.CreateAsset(newMat, matName);
|
||||||
|
mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a61c02ab9beccee4aa8d443c9e2625fe
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB_TextureBakerEditorConfigureMultiMaterials.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,550 @@
|
|||||||
|
//----------------------------------------------
|
||||||
|
// MeshBaker
|
||||||
|
// Copyright © 2011-2012 Ian Deane
|
||||||
|
//----------------------------------------------
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MB_TextureBakerConfigureTextureArrays
|
||||||
|
{
|
||||||
|
private class Slice
|
||||||
|
{
|
||||||
|
public List<MB_MaterialAndUVRect> atlasRects;
|
||||||
|
public AtlasPackingResult packingResult;
|
||||||
|
public int numAtlasRects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GUIContent gc_TextureArrayOutputFormats = new GUIContent(
|
||||||
|
"Texture Array Output Formats",
|
||||||
|
"Texture Arrays do not have a 'TextureImporter' that lets you change the TextureArray format." +
|
||||||
|
"You can provide a list of formats to be generated here. You will probably have one set of formats per platform.");
|
||||||
|
public static void DrawTextureArrayConfiguration(MB3_TextureBaker momm, SerializedObject textureBaker, MB3_TextureBakerEditorInternal editorInternal)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(editorInternal.editorStyles.multipleMaterialBackgroundStyle);
|
||||||
|
EditorGUILayout.LabelField("Texture Array Slice Configuration", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
float oldLabelWidth = EditorGUIUtility.labelWidth;
|
||||||
|
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.configAtlasTextureSlicesFromObjsContent))
|
||||||
|
{
|
||||||
|
ConfigureTextureArraysFromObjsToCombine(momm, editorInternal.resultMaterialsTexArray, textureBaker);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Report texture sizes"))
|
||||||
|
{
|
||||||
|
Debug.Log(ReportTextureSizesAndFormats(momm));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editorInternal.textureArrayOutputFormats.arraySize == 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("You need at least one output format.", MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(editorInternal.textureArrayOutputFormats, gc_TextureArrayOutputFormats, true);
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
editorInternal.resultMaterialsFoldout = EditorGUILayout.Foldout(editorInternal.resultMaterialsFoldout, MB3_TextureBakerEditorInternal.textureArrayCombinedMaterialFoldoutGUIContent);
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.insertContent, EditorStyles.miniButtonLeft, MB3_TextureBakerEditorInternal.buttonWidth))
|
||||||
|
{
|
||||||
|
if (editorInternal.resultMaterialsTexArray.arraySize == 0)
|
||||||
|
{
|
||||||
|
momm.resultMaterialsTexArray = new MB_MultiMaterialTexArray[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int idx = editorInternal.resultMaterialsTexArray.arraySize - 1;
|
||||||
|
editorInternal.resultMaterialsTexArray.InsertArrayElementAtIndex(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.deleteContent, EditorStyles.miniButtonRight, MB3_TextureBakerEditorInternal.buttonWidth)
|
||||||
|
&& editorInternal.resultMaterialsTexArray.arraySize > 0)
|
||||||
|
{
|
||||||
|
editorInternal.resultMaterialsTexArray.DeleteArrayElementAtIndex(editorInternal.resultMaterialsTexArray.arraySize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
|
||||||
|
if (editorInternal.resultMaterialsFoldout)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < editorInternal.resultMaterialsTexArray.arraySize; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
if (i % 2 == 1)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(editorInternal.editorStyles.multipleMaterialBackgroundStyle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(editorInternal.editorStyles.multipleMaterialBackgroundStyleDarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
string s = "";
|
||||||
|
if (i < momm.resultMaterialsTexArray.Length && momm.resultMaterialsTexArray[i] != null && momm.resultMaterialsTexArray[i].combinedMaterial != null) s = momm.resultMaterialsTexArray[i].combinedMaterial.shader.ToString();
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("---------- submesh:" + i + " " + s, EditorStyles.boldLabel);
|
||||||
|
if (GUILayout.Button(MB3_TextureBakerEditorInternal.deleteContent, EditorStyles.miniButtonRight, MB3_TextureBakerEditorInternal.buttonWidth))
|
||||||
|
{
|
||||||
|
editorInternal.resultMaterialsTexArray.DeleteArrayElementAtIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
if (i < editorInternal.resultMaterialsTexArray.arraySize)
|
||||||
|
{
|
||||||
|
EditorGUILayout.Separator();
|
||||||
|
SerializedProperty resMat = editorInternal.resultMaterialsTexArray.GetArrayElementAtIndex(i);
|
||||||
|
EditorGUILayout.PropertyField(resMat.FindPropertyRelative("combinedMaterial"));
|
||||||
|
SerializedProperty slices = resMat.FindPropertyRelative("slices");
|
||||||
|
EditorGUILayout.PropertyField(slices, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ReportTextureSizesAndFormats(MB3_TextureBaker mom)
|
||||||
|
{
|
||||||
|
if (mom.resultType != MB2_TextureBakeResults.ResultType.textureArray)
|
||||||
|
{
|
||||||
|
Debug.LogError("Result Type must be Texture Array.");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int resMatIdx = 0; resMatIdx < mom.resultMaterialsTexArray.Length; resMatIdx++)
|
||||||
|
{
|
||||||
|
MB_MultiMaterialTexArray resMatTexArray = mom.resultMaterialsTexArray[resMatIdx];
|
||||||
|
if (resMatTexArray.combinedMaterial == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Result Material " + resMatIdx + " is null");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
|
// Visit each result material
|
||||||
|
for (int resMatIdx = 0; resMatIdx < mom.resultMaterialsTexArray.Length; resMatIdx++)
|
||||||
|
{
|
||||||
|
MB_MultiMaterialTexArray resMatTexArray = mom.resultMaterialsTexArray[resMatIdx];
|
||||||
|
|
||||||
|
// Do an atlas pack in order to collect all the textures needed by the result material
|
||||||
|
// And group these by material texture property.
|
||||||
|
|
||||||
|
MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
|
||||||
|
combiner.saveAtlasesAsAssets = false;
|
||||||
|
combiner.fixOutOfBoundsUVs = false;
|
||||||
|
List<AtlasPackingResult> packingResults = new List<AtlasPackingResult>();
|
||||||
|
Material tempMat = new Material(resMatTexArray.combinedMaterial.shader);
|
||||||
|
|
||||||
|
List<Material> allSourceMaterials = new List<Material>();
|
||||||
|
for (int sliceIdx = 0; sliceIdx < resMatTexArray.slices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
List<Material> srcMats = new List<Material>();
|
||||||
|
resMatTexArray.slices[sliceIdx].GetAllUsedMaterials(srcMats);
|
||||||
|
for (int srcMatIdx = 0; srcMatIdx < srcMats.Count; srcMatIdx++)
|
||||||
|
{
|
||||||
|
if (srcMats[srcMatIdx] != null && !allSourceMaterials.Contains(srcMats[srcMatIdx]))
|
||||||
|
{
|
||||||
|
allSourceMaterials.Add(srcMats[srcMatIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MB_AtlasesAndRects atlasesAndRects = new MB_AtlasesAndRects();
|
||||||
|
combiner.CombineTexturesIntoAtlases(null, atlasesAndRects, tempMat, mom.GetObjectsToCombine(), allSourceMaterials, mom.texturePropNamesToIgnore, null, packingResults,
|
||||||
|
onlyPackRects:true, splitAtlasWhenPackingIfTooBig:false);
|
||||||
|
|
||||||
|
// Now vist the packing results and collect all the textures
|
||||||
|
Debug.Assert(packingResults.Count == 1);
|
||||||
|
for (int texPropIdx = 0; texPropIdx < atlasesAndRects.texPropertyNames.Length; texPropIdx++)
|
||||||
|
{
|
||||||
|
string propertyName = atlasesAndRects.texPropertyNames[texPropIdx];
|
||||||
|
sb.AppendLine(String.Format("Prop: {0}", propertyName));
|
||||||
|
|
||||||
|
List<MB_MaterialAndUVRect> matsData = (List<MB_MaterialAndUVRect>)packingResults[0].data;
|
||||||
|
HashSet<Material> visitedMats = new HashSet<Material>();
|
||||||
|
for (int matAndGoIdx = 0; matAndGoIdx < matsData.Count; matAndGoIdx++)
|
||||||
|
{
|
||||||
|
Material mat = matsData[matAndGoIdx].material;
|
||||||
|
if (visitedMats.Contains(mat)) continue;
|
||||||
|
visitedMats.Add(mat);
|
||||||
|
if (mat.HasProperty(propertyName))
|
||||||
|
{
|
||||||
|
Texture tex = mat.GetTexture(propertyName);
|
||||||
|
if (tex != null)
|
||||||
|
{
|
||||||
|
string texFormatString = "UnknownFormat";
|
||||||
|
string texWrapMode = "UnknownClampMode";
|
||||||
|
if (tex is Texture2D)
|
||||||
|
{
|
||||||
|
texFormatString = ((Texture2D)tex).format.ToString();
|
||||||
|
texWrapMode = ((Texture2D)tex).wrapMode.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine(String.Format(" {0} x {1} format:{2} wrapMode:{3} {4}", tex.width.ToString().PadLeft(6,' '), tex.height.ToString().PadRight(6,' '), texFormatString.PadRight(20,' '), texWrapMode.PadRight(12,' '), tex.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ConfigureTextureArraysFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterialsTexArrays, SerializedObject textureBaker)
|
||||||
|
{
|
||||||
|
if (mom.GetObjectsToCombine().Count == 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("You need to add some objects to combine before building the texture array result materials.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resultMaterialsTexArrays.arraySize > 0)
|
||||||
|
{
|
||||||
|
Debug.LogError("You already have some texture array result materials configured. You must remove these before doing this operation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mom.textureBakeResults == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Texture Bake Result asset must be set before using this operation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//validate that the objects to be combined are valid
|
||||||
|
for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
|
||||||
|
{
|
||||||
|
GameObject go = mom.GetObjectsToCombine()[i];
|
||||||
|
if (go == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Null object in list of objects to combine at position " + i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MB_Utility.GetMesh(go) == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Could not get mesh for object in list of objects to combine at position " + i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer r = go.GetComponent<Renderer>();
|
||||||
|
if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
|
||||||
|
{
|
||||||
|
Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (r.sharedMaterial == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Will sort into "result material"
|
||||||
|
// slices
|
||||||
|
Dictionary<MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List<Slice>> shader2ResultMat_map = new Dictionary<MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List<Slice>>();
|
||||||
|
|
||||||
|
// first pass split by shader and analyse meshes.
|
||||||
|
List<GameObject> objsToCombine = mom.GetObjectsToCombine();
|
||||||
|
for (int meshIdx = 0; meshIdx < objsToCombine.Count; meshIdx++)
|
||||||
|
{
|
||||||
|
GameObject srcGo = objsToCombine[meshIdx];
|
||||||
|
Mesh mesh = MB_Utility.GetMesh(srcGo);
|
||||||
|
Renderer r = MB_Utility.GetRenderer(srcGo);
|
||||||
|
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("1st Pass 'Split By Shader' Processing Mesh: "+ mesh +" Num submeshes: " + r.sharedMaterials.Length);
|
||||||
|
for (int submeshIdx = 0; submeshIdx < r.sharedMaterials.Length; submeshIdx++)
|
||||||
|
{
|
||||||
|
if (r.sharedMaterials[submeshIdx] == null) continue;
|
||||||
|
|
||||||
|
MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo newKey = new MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo(r.sharedMaterials[submeshIdx].shader, r.sharedMaterials[submeshIdx]);
|
||||||
|
// Initially we fill the list of srcMaterials with garbage MB_MaterialAndUVRects. Will get proper ones when we atlas pack.
|
||||||
|
MB_MaterialAndUVRect submeshMaterial = new MB_MaterialAndUVRect(
|
||||||
|
r.sharedMaterials[submeshIdx],
|
||||||
|
new Rect(0, 0, 0, 0), // garbage value
|
||||||
|
false, //garbage value
|
||||||
|
new Rect(0, 0, 0, 0), // garbage value
|
||||||
|
new Rect(0, 0, 0, 0), // garbage value
|
||||||
|
new Rect(0, 0, 1, 1), // garbage value
|
||||||
|
MB_TextureTilingTreatment.unknown, // garbage value
|
||||||
|
r.name);
|
||||||
|
submeshMaterial.objectsThatUse = new List<GameObject>();
|
||||||
|
submeshMaterial.objectsThatUse.Add(r.gameObject);
|
||||||
|
if (!shader2ResultMat_map.ContainsKey(newKey))
|
||||||
|
{
|
||||||
|
// this is a new shader create a new result material
|
||||||
|
Slice srcMaterials = new Slice
|
||||||
|
{
|
||||||
|
atlasRects = new List<MB_MaterialAndUVRect>(),
|
||||||
|
numAtlasRects = 1,
|
||||||
|
|
||||||
|
};
|
||||||
|
srcMaterials.atlasRects.Add(submeshMaterial);
|
||||||
|
List<Slice> binsOfMatsThatUseShader = new List<Slice>();
|
||||||
|
binsOfMatsThatUseShader.Add(srcMaterials);
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(" Adding Source Material: " + submeshMaterial.material);
|
||||||
|
shader2ResultMat_map.Add(newKey, binsOfMatsThatUseShader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there is a result material that uses this shader. Add this source material
|
||||||
|
Slice srcMaterials = shader2ResultMat_map[newKey][0]; // There should only be one list of source materials
|
||||||
|
if (srcMaterials.atlasRects.Find(x => x.material == submeshMaterial.material) == null)
|
||||||
|
{
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(" Adding Source Material: " + submeshMaterial.material);
|
||||||
|
srcMaterials.atlasRects.Add(submeshMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int resMatCount = 0;
|
||||||
|
foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo resultMat in shader2ResultMat_map.Keys)
|
||||||
|
{
|
||||||
|
// at this point there there should be only one slice with all the source materials
|
||||||
|
resMatCount++;
|
||||||
|
|
||||||
|
// For each result material, all source materials are in the first slice.
|
||||||
|
// We will now split these using a texture packer. Each "atlas" generated by the packer will be a slice.
|
||||||
|
{
|
||||||
|
// All source materials should be in the first slice at this point.
|
||||||
|
List<Slice> slices = shader2ResultMat_map[resultMat];
|
||||||
|
List<Slice> newSlices = new List<Slice>();
|
||||||
|
Slice firstSlice = slices[0];
|
||||||
|
List<Material> allMatsThatUserShader = new List<Material>();
|
||||||
|
List<GameObject> objsThatUseFirstSlice = new List<GameObject>();
|
||||||
|
for (int i = 0; i < firstSlice.atlasRects.Count; i++)
|
||||||
|
{
|
||||||
|
allMatsThatUserShader.Add(firstSlice.atlasRects[i].material);
|
||||||
|
if (!objsThatUseFirstSlice.Contains(firstSlice.atlasRects[i].objectsThatUse[0]))
|
||||||
|
{
|
||||||
|
objsThatUseFirstSlice.Add(firstSlice.atlasRects[i].objectsThatUse[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
|
||||||
|
combiner.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
|
||||||
|
combiner.saveAtlasesAsAssets = false;
|
||||||
|
combiner.fixOutOfBoundsUVs = true;
|
||||||
|
combiner.doMergeDistinctMaterialTexturesThatWouldExceedAtlasSize = true;
|
||||||
|
List<AtlasPackingResult> packingResults = new List<AtlasPackingResult>();
|
||||||
|
Material tempMat = new Material(resultMat.shader);
|
||||||
|
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("======== 2nd pass. Use atlas packer to split the first slice into multiple if it exceeds atlas size. ");
|
||||||
|
combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, mom.texturePropNamesToIgnore, null, packingResults,
|
||||||
|
onlyPackRects:true, splitAtlasWhenPackingIfTooBig:true);
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("======== Completed packing with texture packer. numPackingResults: " + packingResults.Count);
|
||||||
|
newSlices.Clear();
|
||||||
|
|
||||||
|
// The texture packing just split the atlas into multiple atlases. Each atlas will become a "slice".
|
||||||
|
for (int newSliceIdx = 0; newSliceIdx < packingResults.Count; newSliceIdx++)
|
||||||
|
{
|
||||||
|
List<MB_MaterialAndUVRect> sourceMats = new List<MB_MaterialAndUVRect>();
|
||||||
|
List<MB_MaterialAndUVRect> packedMatRects = (List<MB_MaterialAndUVRect>) packingResults[newSliceIdx].data;
|
||||||
|
HashSet<Rect> distinctAtlasRects = new HashSet<Rect>();
|
||||||
|
for (int packedMatRectIdx = 0; packedMatRectIdx < packedMatRects.Count; packedMatRectIdx++)
|
||||||
|
{
|
||||||
|
MB_MaterialAndUVRect muvr = packedMatRects[packedMatRectIdx];
|
||||||
|
distinctAtlasRects.Add(muvr.atlasRect);
|
||||||
|
//{
|
||||||
|
// Rect encapsulatingRect = muvr.GetEncapsulatingRect();
|
||||||
|
// Vector2 sizeInAtlas_px = new Vector2(
|
||||||
|
// packingResults[newSliceIdx].atlasX * encapsulatingRect.width,
|
||||||
|
// packingResults[newSliceIdx].atlasY * encapsulatingRect.height);
|
||||||
|
//}
|
||||||
|
sourceMats.Add(muvr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Slice slice = new Slice()
|
||||||
|
{
|
||||||
|
atlasRects = sourceMats,
|
||||||
|
packingResult = packingResults[newSliceIdx],
|
||||||
|
numAtlasRects = distinctAtlasRects.Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
newSlices.Add(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace first slice with split version.
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("First slice exceeded atlas size splitting it into " + newSlices.Count + " slices");
|
||||||
|
slices.RemoveAt(0);
|
||||||
|
for (int i = 0; i < newSlices.Count; i++)
|
||||||
|
{
|
||||||
|
slices.Insert(i, newSlices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the texture array result materials
|
||||||
|
if (shader2ResultMat_map.Count == 0) Debug.LogError("Found no materials in list of objects to combine");
|
||||||
|
mom.resultMaterialsTexArray = new MB_MultiMaterialTexArray[shader2ResultMat_map.Count];
|
||||||
|
int k = 0;
|
||||||
|
foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo resMatKey in shader2ResultMat_map.Keys)
|
||||||
|
{
|
||||||
|
List<Slice> srcSlices = shader2ResultMat_map[resMatKey];
|
||||||
|
MB_MultiMaterialTexArray mm = mom.resultMaterialsTexArray[k] = new MB_MultiMaterialTexArray();
|
||||||
|
for (int sliceIdx = 0; sliceIdx < srcSlices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
Slice slice = srcSlices[sliceIdx];
|
||||||
|
MB_TexArraySlice resSlice = new MB_TexArraySlice();
|
||||||
|
for (int srcMatIdx = 0; srcMatIdx < slice.atlasRects.Count; srcMatIdx++)
|
||||||
|
{
|
||||||
|
MB_MaterialAndUVRect matAndUVRect = slice.atlasRects[srcMatIdx];
|
||||||
|
List<GameObject> objsThatUse = matAndUVRect.objectsThatUse;
|
||||||
|
for (int objsThatUseIdx = 0; objsThatUseIdx < objsThatUse.Count; objsThatUseIdx++)
|
||||||
|
{
|
||||||
|
GameObject obj = objsThatUse[objsThatUseIdx];
|
||||||
|
if (!resSlice.ContainsMaterialAndMesh(slice.atlasRects[srcMatIdx].material, MB_Utility.GetMesh(obj)))
|
||||||
|
{
|
||||||
|
resSlice.sourceMaterials.Add(
|
||||||
|
new MB_TexArraySliceRendererMatPair()
|
||||||
|
{
|
||||||
|
renderer = obj,
|
||||||
|
sourceMaterial = slice.atlasRects[srcMatIdx].material
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Should we use considerUVs
|
||||||
|
bool doConsiderUVs = false;
|
||||||
|
// If there is more than one atlas rectangle in a slice then use considerUVs
|
||||||
|
if (slice.numAtlasRects > 1)
|
||||||
|
{
|
||||||
|
doConsiderUVs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There is only one source material, could be:
|
||||||
|
// - lots of tiling (don't want consider UVs)
|
||||||
|
// - We are extracting a small part of a large atlas (want considerUVs)
|
||||||
|
if (slice.packingResult.atlasX >= mom.maxAtlasSize ||
|
||||||
|
slice.packingResult.atlasY >= mom.maxAtlasSize)
|
||||||
|
{
|
||||||
|
doConsiderUVs = false; // lots of tiling
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
doConsiderUVs = true; // extracting a small part of an atlas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resSlice.considerMeshUVs = doConsiderUVs;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm.slices.Add(resSlice);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforce integrity. If a material appears in more than one slice then all those slices must be considerUVs=true
|
||||||
|
{
|
||||||
|
// collect all distinct materials
|
||||||
|
HashSet<Material> distinctMats = new HashSet<Material>();
|
||||||
|
Dictionary<Material, int> mat2sliceCount = new Dictionary<Material, int>();
|
||||||
|
for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
for (int sliceMatIdx = 0; sliceMatIdx < mm.slices[sliceIdx].sourceMaterials.Count; sliceMatIdx++)
|
||||||
|
{
|
||||||
|
Material mat = mm.slices[sliceIdx].sourceMaterials[sliceMatIdx].sourceMaterial;
|
||||||
|
distinctMats.Add(mat);
|
||||||
|
mat2sliceCount[mat] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of slices that use each material.
|
||||||
|
foreach (Material mat in distinctMats)
|
||||||
|
{
|
||||||
|
for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
if (mm.slices[sliceIdx].ContainsMaterial(mat))
|
||||||
|
{
|
||||||
|
mat2sliceCount[mat] = mat2sliceCount[mat] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that considerUVs is true for any materials that appear more than once
|
||||||
|
foreach (Material mat in distinctMats)
|
||||||
|
{
|
||||||
|
if (mat2sliceCount[mat] > 1)
|
||||||
|
{
|
||||||
|
for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
if (mm.slices[sliceIdx].ContainsMaterial(mat))
|
||||||
|
{
|
||||||
|
if (mom.LOG_LEVEL >= MB2_LogLevel.debug &&
|
||||||
|
mm.slices[sliceIdx].considerMeshUVs) Debug.Log("There was a material " + mat + " that was used by more than one slice and considerUVs was false. sliceIdx:" + sliceIdx);
|
||||||
|
mm.slices[sliceIdx].considerMeshUVs = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup. remove "Renderer"s from source materials that do not use considerUVs and delete extra
|
||||||
|
{
|
||||||
|
// put any slices with consider UVs first
|
||||||
|
List<MB_TexArraySlice> newSlices = new List<MB_TexArraySlice>();
|
||||||
|
for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
if (mm.slices[sliceIdx].considerMeshUVs == true)
|
||||||
|
{
|
||||||
|
newSlices.Add(mm.slices[sliceIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for any slices without considerUVs, remove "renderer" and truncate
|
||||||
|
for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
|
||||||
|
{
|
||||||
|
MB_TexArraySlice slice = mm.slices[sliceIdx];
|
||||||
|
if (slice.considerMeshUVs == false)
|
||||||
|
{
|
||||||
|
newSlices.Add(slice);
|
||||||
|
HashSet<Material> distinctMats = slice.GetDistinctMaterials();
|
||||||
|
slice.sourceMaterials.Clear();
|
||||||
|
foreach (Material mat in distinctMats)
|
||||||
|
{
|
||||||
|
slice.sourceMaterials.Add(new MB_TexArraySliceRendererMatPair() {sourceMaterial = mat });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mm.slices = newSlices;
|
||||||
|
}
|
||||||
|
|
||||||
|
string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults);
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(pth);
|
||||||
|
string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
|
||||||
|
string matName = folderPath + baseName + "-mat" + k + ".mat";
|
||||||
|
Material existingAsset = AssetDatabase.LoadAssetAtPath<Material>(matName);
|
||||||
|
if (!existingAsset)
|
||||||
|
{
|
||||||
|
Material newMat = new Material(Shader.Find("Standard"));
|
||||||
|
// Don't try to configure the material we need the user to pick a shader that has TextureArrays
|
||||||
|
AssetDatabase.CreateAsset(newMat, matName);
|
||||||
|
}
|
||||||
|
|
||||||
|
mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
|
||||||
|
textureBaker.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8860927141262124c92c04030afa23d5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MB_TextureBakerEditorConfigureTextureArrays.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "MeshBakerEditor",
|
||||||
|
"references": [
|
||||||
|
"MeshBakerLib",
|
||||||
|
"MeshBakerEditorLib",
|
||||||
|
"MeshBakerCore"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dd9493fbefb52fd48926bb1291844728
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/MeshBakerEditor.asmdef
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
public static class MeshBakerPurgeNullObjects
|
||||||
|
{
|
||||||
|
[MenuItem("Tools/Mesh Baker/Purge Null Objects From Selected Baker")]
|
||||||
|
public static void PurgeNullObjectsFromSelectedBaker()
|
||||||
|
{
|
||||||
|
GameObject selected = Selection.activeGameObject;
|
||||||
|
|
||||||
|
if (selected == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Aucun GameObject sélectionné.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component[] components = selected.GetComponents<Component>();
|
||||||
|
|
||||||
|
bool foundList = false;
|
||||||
|
int totalRemoved = 0;
|
||||||
|
|
||||||
|
foreach (Component component in components)
|
||||||
|
{
|
||||||
|
if (component == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SerializedObject so = new SerializedObject(component);
|
||||||
|
|
||||||
|
// Nom utilisé par Mesh Baker pour la liste Objects To Be Combined
|
||||||
|
SerializedProperty objectsList = so.FindProperty("objsToMesh");
|
||||||
|
|
||||||
|
if (objectsList == null || !objectsList.isArray)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foundList = true;
|
||||||
|
|
||||||
|
int removed = 0;
|
||||||
|
|
||||||
|
// Important : on parcourt à l'envers pour supprimer sans décaler les indices restants.
|
||||||
|
for (int i = objectsList.arraySize - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
SerializedProperty element = objectsList.GetArrayElementAtIndex(i);
|
||||||
|
|
||||||
|
if (element.propertyType == SerializedPropertyType.ObjectReference &&
|
||||||
|
element.objectReferenceValue == null)
|
||||||
|
{
|
||||||
|
objectsList.DeleteArrayElementAtIndex(i);
|
||||||
|
removed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removed > 0)
|
||||||
|
{
|
||||||
|
so.ApplyModifiedProperties();
|
||||||
|
EditorUtility.SetDirty(component);
|
||||||
|
totalRemoved += removed;
|
||||||
|
|
||||||
|
Debug.Log($"Mesh Baker : {removed} entrée(s) null supprimée(s) dans {component.GetType().Name}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundList)
|
||||||
|
{
|
||||||
|
Debug.LogError(
|
||||||
|
"Aucune liste 'objsToMesh' trouvée sur l'objet sélectionné. " +
|
||||||
|
"Sélectionne l'objet TextureBaker ou MeshBaker qui contient 'Objects To Be Combined'."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
|
||||||
|
Debug.Log($"Purge terminée. Total supprimé : {totalRemoved} entrée(s) null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c2c6d03c5f9a6b441ae153812251dcad
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e31a342d0f438364a9d439d82aa9a9a0
|
guid: c307e366f91a4284d810409a68c5b7bc
|
||||||
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
[CustomPropertyDrawer(typeof(ShaderTextureProperty))]
|
||||||
|
public class MB3_ShaderTexturePropertyDrawer : PropertyDrawer
|
||||||
|
{
|
||||||
|
public static GUIContent gc_isNormalMap = new GUIContent("isNormalMap", "This atlas texture will be marked as a normal map"),
|
||||||
|
gc_isGammaCorrected = new GUIContent("isGammaCorrected", "This atlas should be gamma corrected (sRGB checked). If not checked then the atlas will be a linear texture");
|
||||||
|
|
||||||
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||||
|
{
|
||||||
|
label = EditorGUI.BeginProperty(position, label, property);
|
||||||
|
|
||||||
|
|
||||||
|
Rect contentPosition = EditorGUI.PrefixLabel(position, label);
|
||||||
|
|
||||||
|
float w = contentPosition.width;
|
||||||
|
|
||||||
|
contentPosition.width = w * 0.4f;
|
||||||
|
EditorGUI.indentLevel = 0;
|
||||||
|
|
||||||
|
EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("name"), GUIContent.none);
|
||||||
|
|
||||||
|
contentPosition.x += contentPosition.width;
|
||||||
|
contentPosition.width = w * 0.3f;
|
||||||
|
EditorGUIUtility.labelWidth = 50f;
|
||||||
|
EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("isNormalMap"), gc_isNormalMap);
|
||||||
|
|
||||||
|
contentPosition.x += contentPosition.width;
|
||||||
|
EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("isGammaCorrected"), gc_isGammaCorrected);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//EditorGUILayout.PropertyField(property.FindPropertyRelative("name"));
|
||||||
|
//EditorGUILayout.PropertyField(property.FindPropertyRelative("isNormalMap"), gc_isNormalMap);
|
||||||
|
//EditorGUILayout.PropertyField(property.FindPropertyRelative("isGammaCorrected"), gc_isGammaCorrected);
|
||||||
|
EditorGUI.EndProperty();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 24ced5fa006456249ac31e87abe5aa5b
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/propertyDrawers/MB3_ShaderTexturePropertyDrawer.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB_ConvertTextureArrayFormatWizard : ScriptableWizard
|
||||||
|
{
|
||||||
|
public Texture2DArray textureArray;
|
||||||
|
public TextureFormat format = TextureFormat.ARGB32;
|
||||||
|
|
||||||
|
[MenuItem("Window/Mesh Baker/TextureArray Format Converter")]
|
||||||
|
static void CreateWizard()
|
||||||
|
{
|
||||||
|
ScriptableWizard.DisplayWizard<MB_ConvertTextureArrayFormatWizard>("Convert Texture Array Format", "Close", "Convert");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnWizardCreate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnWizardUpdate()
|
||||||
|
{
|
||||||
|
helpString = "Please assign a texture array";
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnWizardOtherButton()
|
||||||
|
{
|
||||||
|
helpString = "";
|
||||||
|
if (textureArray == null)
|
||||||
|
{
|
||||||
|
helpString = "Please assign a texture array";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB3_EditorMethods editorMethods = new MB3_EditorMethods();
|
||||||
|
if (!editorMethods.TextureImporterFormatExistsForTextureFormat(format))
|
||||||
|
{
|
||||||
|
helpString = "No ImporterFormat exists for the selected format. Please select a different format.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textureArray.format != TextureFormat.ARGB32 &&
|
||||||
|
textureArray.format != TextureFormat.RGB24)
|
||||||
|
{
|
||||||
|
helpString = "Source TextureArray must be in format ARGB32 or RGB24. This will probably be changed in" +
|
||||||
|
"a future version of Mesh Baker.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2DArray outArray = new Texture2DArray(textureArray.width, textureArray.height, textureArray.depth, format, true);
|
||||||
|
if (editorMethods.ConvertTexture2DArray(textureArray, outArray, format))
|
||||||
|
{
|
||||||
|
string pth = UnityEditor.AssetDatabase.GetAssetPath(textureArray);
|
||||||
|
if (pth == null) pth = "Assets/TextureArray.asset";
|
||||||
|
pth = pth.Replace(".asset", "");
|
||||||
|
pth += format.ToString() + ".asset";
|
||||||
|
UnityEditor.AssetDatabase.CreateAsset(outArray, pth);
|
||||||
|
Debug.Log("Convert success saved asset: " + pth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d355da520c795f543a934da176eb59ca
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/propertyDrawers/MB_ConvertTextureArrayFormatWizard.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class MB_PaginatedList
|
||||||
|
{
|
||||||
|
public static void GenerateObjectsToBeCombinedList(SerializedProperty objsToMesh, ref int currentPage, ref int objectsPerPage)
|
||||||
|
{
|
||||||
|
SerializedProperty arraySizeProp = objsToMesh.FindPropertyRelative("Array.size");
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("Size", GUILayout.Width(EditorGUIUtility.labelWidth));
|
||||||
|
int newSize = EditorGUILayout.DelayedIntField(arraySizeProp.intValue);
|
||||||
|
arraySizeProp.intValue = Mathf.Max(1, newSize);
|
||||||
|
if (newSize <= 0 &&
|
||||||
|
arraySizeProp.intValue == 1)
|
||||||
|
{
|
||||||
|
// This is necessary because the first element in the list gets preserved.
|
||||||
|
// If the user sets the number of elements to 0 or less then we should
|
||||||
|
// make the displayed first element == null
|
||||||
|
SerializedProperty element = objsToMesh.GetArrayElementAtIndex(0);
|
||||||
|
element.objectReferenceValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("Objects per Page", GUILayout.Width(EditorGUIUtility.labelWidth));
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
int newObjectsPerPage = EditorGUILayout.DelayedIntField(objectsPerPage);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
objectsPerPage = Mathf.Clamp(newObjectsPerPage, 10, 500);
|
||||||
|
currentPage = 1;
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
int totalObjects = objsToMesh.arraySize;
|
||||||
|
int totalPages = totalObjects / objectsPerPage;
|
||||||
|
if (totalObjects % objectsPerPage != 0)
|
||||||
|
{
|
||||||
|
totalPages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalPages == 0)
|
||||||
|
{
|
||||||
|
currentPage = 1;
|
||||||
|
}
|
||||||
|
else if (currentPage > totalPages)
|
||||||
|
{
|
||||||
|
currentPage = totalPages;
|
||||||
|
}
|
||||||
|
else if (currentPage < 1)
|
||||||
|
{
|
||||||
|
currentPage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndex = (currentPage - 1) * objectsPerPage;
|
||||||
|
int endIndex = Mathf.Min(startIndex + objectsPerPage, totalObjects);
|
||||||
|
for (int i = startIndex; i < endIndex; i++)
|
||||||
|
{
|
||||||
|
SerializedProperty objProp = objsToMesh.GetArrayElementAtIndex(i);
|
||||||
|
EditorGUILayout.PropertyField(objProp, new GUIContent("Object " + (i + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUI.enabled = currentPage > 1;
|
||||||
|
if (GUILayout.Button("Previous"))
|
||||||
|
{
|
||||||
|
currentPage--;
|
||||||
|
}
|
||||||
|
bool prevGUIEnabled = GUI.enabled;
|
||||||
|
GUI.enabled = true;
|
||||||
|
GUIStyle centeredLabelStyle = new GUIStyle(EditorStyles.label);
|
||||||
|
centeredLabelStyle.alignment = TextAnchor.MiddleCenter;
|
||||||
|
EditorGUILayout.LabelField("Page " + currentPage + " of " + totalPages, centeredLabelStyle);
|
||||||
|
GUI.enabled = prevGUIEnabled;
|
||||||
|
GUI.enabled = currentPage < totalPages;
|
||||||
|
if (GUILayout.Button("Next"))
|
||||||
|
{
|
||||||
|
currentPage++;
|
||||||
|
}
|
||||||
|
GUI.enabled = true;
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0eac7adb5e69eaa45b05407b27e84965
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/propertyDrawers/MB_PaginatedList.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using DigitalOpus.MB.MBEditor;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Draws rows for the PrafabPairs in the Switch Prefabs In Scene Window.
|
||||||
|
/// </summary>
|
||||||
|
[CustomPropertyDrawer(typeof(MB_ReplacePrefabsSettings.PrefabPair))]
|
||||||
|
public class MB_PrefabPairPropertyDrawer : PropertyDrawer
|
||||||
|
{
|
||||||
|
private GUIStyle redFont = new GUIStyle();
|
||||||
|
|
||||||
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||||
|
{
|
||||||
|
EditorGUI.BeginProperty(position, label, property);
|
||||||
|
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
|
||||||
|
int indent = EditorGUI.indentLevel;
|
||||||
|
EditorGUI.indentLevel = 0;
|
||||||
|
|
||||||
|
float xx = position.x;
|
||||||
|
float yy = position.y;
|
||||||
|
float ww = 15f;
|
||||||
|
float hh = position.height;
|
||||||
|
|
||||||
|
Rect enabledRect = new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight);
|
||||||
|
xx += ww;
|
||||||
|
ww = 50;
|
||||||
|
Rect srcLabel = new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight);
|
||||||
|
xx += ww;
|
||||||
|
ww = 200;
|
||||||
|
Rect sourceRect = new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight);
|
||||||
|
xx += ww;
|
||||||
|
ww = 50;
|
||||||
|
Rect targetLabel = new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight);
|
||||||
|
xx += ww;
|
||||||
|
ww = 200;
|
||||||
|
Rect targetRect = new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight);
|
||||||
|
|
||||||
|
EditorGUI.PropertyField(enabledRect, property.FindPropertyRelative("enabled"), GUIContent.none);
|
||||||
|
EditorGUI.LabelField(srcLabel, "Source:");
|
||||||
|
EditorGUI.PropertyField(sourceRect, property.FindPropertyRelative("srcPrefab"), GUIContent.none);
|
||||||
|
EditorGUI.LabelField(targetLabel, "Target:");
|
||||||
|
EditorGUI.PropertyField(targetRect, property.FindPropertyRelative("targPrefab"), GUIContent.none);
|
||||||
|
|
||||||
|
SerializedProperty errorsProp = property.serializedObject.FindProperty(property.propertyPath + ".objsWithErrors");
|
||||||
|
if (errorsProp.arraySize > 0)
|
||||||
|
{
|
||||||
|
redFont.normal.textColor = Color.red;
|
||||||
|
for (int i = 0; i < errorsProp.arraySize; i++)
|
||||||
|
{
|
||||||
|
xx = position.x;
|
||||||
|
yy = position.y + (1 + i) * EditorGUIUtility.singleLineHeight;
|
||||||
|
ww = 100;
|
||||||
|
SerializedProperty errProp = errorsProp.GetArrayElementAtIndex(i);
|
||||||
|
GameObject obj = (GameObject)errProp.FindPropertyRelative("errorObj").objectReferenceValue;
|
||||||
|
string errStr = errProp.FindPropertyRelative("error").stringValue;
|
||||||
|
Rect buttonRect = new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight);
|
||||||
|
if (GUI.Button(buttonRect, "Select"))
|
||||||
|
{
|
||||||
|
if (obj != null) Selection.activeGameObject = obj;
|
||||||
|
}
|
||||||
|
xx += ww;
|
||||||
|
ww = 500;
|
||||||
|
EditorGUI.LabelField(new Rect(xx, yy, ww, EditorGUIUtility.singleLineHeight), errStr, redFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUI.indentLevel = indent;
|
||||||
|
EditorGUI.EndProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||||
|
{
|
||||||
|
SerializedProperty errorsProp = property.serializedObject.FindProperty(property.propertyPath + ".objsWithErrors");
|
||||||
|
return base.GetPropertyHeight(property, label) + errorsProp.arraySize * EditorGUIUtility.singleLineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f8fdae7bfb5aa3a41ab365cd5a8238c8
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/propertyDrawers/MB_PrefabPairPropertyDrawer.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 31b5ad3e3da6e4244bdaa2a76ab994b6
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByAlreadyAdded : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "AlreadyAdded";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "alreadyAdded=" + fi.alreadyInBakerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
int alreadyAddedCompare = 0;
|
||||||
|
if (b.alreadyInBakerList == true && a.alreadyInBakerList == false)
|
||||||
|
{
|
||||||
|
alreadyAddedCompare = -1;
|
||||||
|
}
|
||||||
|
if (b.alreadyInBakerList == false && a.alreadyInBakerList == true)
|
||||||
|
{
|
||||||
|
alreadyAddedCompare = 1;
|
||||||
|
}
|
||||||
|
return alreadyAddedCompare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ac8e94c94918f5245823661062e06239
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByAlreadyAdded.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByEnabledDisabled : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Is Enabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return fi.go.activeInHierarchy ? "Enabled" : "Disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
int compareVal = 0;
|
||||||
|
if (b.go.activeInHierarchy == true && a.go.activeInHierarchy == false)
|
||||||
|
{
|
||||||
|
compareVal = -1;
|
||||||
|
}
|
||||||
|
if (b.go.activeInHierarchy == false && a.go.activeInHierarchy == true)
|
||||||
|
{
|
||||||
|
compareVal = 1;
|
||||||
|
}
|
||||||
|
return compareVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 000b6aa8344585d4fb87fb96b8149202
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByEnabledDisabled.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByHasSameSetsOfMaps : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName() {
|
||||||
|
return "HasSameSetsOfMaps";
|
||||||
|
}
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "HasMaps=" + fi.setOfMaps;
|
||||||
|
}
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return a.setOfMaps.CompareTo(b.setOfMaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 06dd0ff07a3ad5940af7018018361a3f
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByHasSameSetsOfMaps.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MB3_GroupByLayerIndex : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Layer Index";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "layerIndex=" + fi.layerIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return b.layerIndex - a.layerIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ce357bbdee02d3049a5ec6c026da0248
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByLayerIndex.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByLightmapIndex : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Lightmap Index";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "lightmapIndex=" + fi.lightmapIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return b.lightmapIndex - a.lightmapIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8add88348b69079419318c17a4aec61a
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByLightmapIndex.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
public class GroupByMaterial : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Material";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "material=" + fi.materialName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return a.materialName.CompareTo(b.materialName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2ff3bf9d7e4fcb64eba007e5d54d5f6a
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByMaterial.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MB3_GroupByMetallicOrSpecular : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "MetallicOrSpecular";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "metallicOrSpecular=" + fi.metallicOrSpecularName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return a.metallicOrSpecularName.CompareTo(b.metallicOrSpecularName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fb37c235a0a0db442aa27cf27a99faeb
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByMetallicOrSpecular.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByOutOfBoundsUVs : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "OutOfBoundsUVs";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "OutOfBoundsUVs=" + fi.outOfBoundsUVs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(b.outOfBoundsUVs) - Convert.ToInt32(a.outOfBoundsUVs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 29fb03f40f7582c41a09dec611a68e8c
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByOutOfBoundsUVs.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByRenderType : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "RenderType";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return fi.isMeshRenderer ? "MeshRenderer" : "SkinnedMeshRenderer";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
int renderTypeCompare = 0;
|
||||||
|
if (b.isMeshRenderer == true && a.isMeshRenderer == false)
|
||||||
|
{
|
||||||
|
renderTypeCompare = -1;
|
||||||
|
}
|
||||||
|
if (b.isMeshRenderer == false && a.isMeshRenderer == true)
|
||||||
|
{
|
||||||
|
renderTypeCompare = 1;
|
||||||
|
}
|
||||||
|
return renderTypeCompare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ccb4d2ba98c9989449e34934c09ec5ca
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByRenderType.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByShader : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Shader";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "shader=" + fi.shaderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return a.shaderName.CompareTo(b.shaderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5f0f3a86ced986a4aa686551a1c3a4ad
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByShader.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GroupByStatic : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Static";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "isStatic=" + fi.isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
int staticCompare = 0;
|
||||||
|
if (b.isStatic == true && a.isStatic == false)
|
||||||
|
{
|
||||||
|
staticCompare = -1;
|
||||||
|
}
|
||||||
|
if (b.isStatic == false && a.isStatic == true)
|
||||||
|
{
|
||||||
|
staticCompare = 1;
|
||||||
|
}
|
||||||
|
return staticCompare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4e91e5646c425c8428d175ac3fe62800
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByStatic.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DigitalOpus.MB.Core;
|
||||||
|
|
||||||
|
namespace DigitalOpus.MB.MBEditor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MB3_GroupByTransparency : IGroupByFilter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "Transparency";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDescription(GameObjectFilterInfo fi)
|
||||||
|
{
|
||||||
|
return "transparency=" + fi.standardShaderBlendModesName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(GameObjectFilterInfo a, GameObjectFilterInfo b)
|
||||||
|
{
|
||||||
|
return a.standardShaderBlendModesName.CompareTo(b.standardShaderBlendModesName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b9be5ed7795b65d448a3cd700e472f8a
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Editor/searchFilters/MB3_GroupByTransparency.cs
|
||||||
|
uploadId: 797180
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 7d8d3647cc2e7ab4dacc84e4b6102063
|
guid: 3290cf8f3944293438cfe8df22e4af7f
|
||||||
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
Binary file not shown.
@@ -0,0 +1,83 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0f32008f8aab7e54f86387d6790b2c02
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
: Any
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
Exclude Android: 1
|
||||||
|
Exclude Editor: 0
|
||||||
|
Exclude Linux64: 1
|
||||||
|
Exclude OSXUniversal: 1
|
||||||
|
Exclude Win: 1
|
||||||
|
Exclude Win64: 1
|
||||||
|
- first:
|
||||||
|
Android: Android
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: ARMv7
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
OS: AnyOS
|
||||||
|
- first:
|
||||||
|
Standalone: Linux64
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: None
|
||||||
|
- first:
|
||||||
|
Standalone: OSXUniversal
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: None
|
||||||
|
- first:
|
||||||
|
Standalone: Win
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: None
|
||||||
|
- first:
|
||||||
|
Standalone: Win64
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: None
|
||||||
|
- first:
|
||||||
|
Windows Store Apps: WindowsStoreApps
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Libs/MeshBakerEditorLib.dll
|
||||||
|
uploadId: 797180
|
||||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cab42632cbdacc94f9b261da366ec4c4
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
- first:
|
||||||
|
Windows Store Apps: WindowsStoreApps
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
CPU: AnyCPU
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/Libs/MeshBakerLib.dll
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 96adfa24818e71649adf8d4741021058
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
The MeshBakerWorkingFolder is used to store temporary assets created by Mesh Baker during bakes. This file exists so that this folder doesn't confuse source control systems which don't track empty folders.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4bdd3f9a90a7923428f5dedc4d223593
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/MeshBakerWorkingFolder/DONT_DELETE.txt
|
||||||
|
uploadId: 797180
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
MeshBaker is a tool for combining many meshes into one big mesh and creating texture atlases
|
||||||
|
from all the textures used by the source meshes. OBJECTS TO BE COMBINED DO NOT NEED THE SAME
|
||||||
|
MATERIAL OR EVEN THE SAME SHADER. Meshbaker will create empty textures and resize copies of
|
||||||
|
textures if needed to build the atlases. Meshbaker does not touch the source assets
|
||||||
|
(other than setting the read flag on textures). It bakes the source
|
||||||
|
assets into new assets which can be used in your scene for high performance scene loading.
|
||||||
|
|
||||||
|
QUICKSTART
|
||||||
|
|
||||||
|
MeshBaker is best used in the Unity Editor (see below for runtime use)
|
||||||
|
|
||||||
|
Create a new MeshBaker object in your scene under the Game Object menu.
|
||||||
|
Game Object
|
||||||
|
-> Create Other
|
||||||
|
-> Mesh Baker
|
||||||
|
-> MeshBaker
|
||||||
|
Follow the instructions in the inspector.
|
||||||
|
|
||||||
|
See "Manual.pdf" for more information.
|
||||||
|
Latest tutorial videos are found in this youtube list: https://www.youtube.com/playlist?list=PLCzm-udM-shlRUy5f9QHHxqqv-9wP5FBM
|
||||||
|
|
||||||
|
UPGRADING FROM THE EVALUATION VERSION
|
||||||
|
|
||||||
|
To upgrade from the evaluation version, delete the MeshBaker folder from
|
||||||
|
your project and import the full version.
|
||||||
|
|
||||||
|
Note that after doing this you may have "Missing Script" errors on your Combined Material assets.
|
||||||
|
These can be fixed by clicking on the circle with dot in it beside the "Missing Script" text in the
|
||||||
|
inspector and choosing "MB2_TextureBakeResults" from the list of scripts.
|
||||||
|
|
||||||
|
SUPPORT
|
||||||
|
|
||||||
|
Please post to the forums at https://discussions.unity.com/t/mesh-baker-by-digital-opus-released/490738/3694
|
||||||
|
email: contact.digitalopus@gmail.com
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: eb65045eaa0d32a41804f69da7d5eec3
|
||||||
|
AssetOrigin:
|
||||||
|
serializedVersion: 1
|
||||||
|
productId: 31895
|
||||||
|
packageName: Mesh Baker Free
|
||||||
|
packageVersion: 3.40.1
|
||||||
|
assetPath: Assets/MeshBaker/README.txt
|
||||||
|
uploadId: 797180
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user