/// <summary> /// Sorts the Material Remaps by names. /// </summary> /// <param name="syncPrefabImporter"></param> public static void SortRemaps(this SyncPrefabScriptedImporter syncPrefabImporter) { var so = new SerializedObject(syncPrefabImporter); var sourceRemaps = so.FindProperty("m_MaterialRemaps"); var unsortedList = new List <string>(); for (int i = 0; i < sourceRemaps.arraySize; i++) { SerializedProperty item = sourceRemaps.GetArrayElementAtIndex(i); unsortedList.Add(item.FindPropertyRelative("syncMaterialName").stringValue); } var sortedList = new List <string>(unsortedList); sortedList.Sort(); for (int destinationIndex = 0; destinationIndex < sortedList.Count; destinationIndex++) { var sourceIndex = unsortedList.FindIndex(x => x == sortedList[destinationIndex]); sourceRemaps.MoveArrayElement(sourceIndex, destinationIndex); var item = unsortedList[sourceIndex]; unsortedList.RemoveAt(sourceIndex); if (destinationIndex > sourceIndex) { destinationIndex--; } unsortedList.Insert(destinationIndex, item); } so.ApplyModifiedProperties(); syncPrefabImporter.SaveAndReimport(); }
internal static void ResetRemaps(SyncPrefabScriptedImporter importer) { // disabling auto extract for next import var auto = ReflectEditorPreferences.autoExtractMaterialsOnImport; ReflectEditorPreferences.autoExtractMaterialsOnImport = false; importer.ResetRemaps(); ReflectEditorPreferences.autoExtractMaterialsOnImport = auto; }
public static void ExtractMaterial(this SyncPrefabScriptedImporter syncPrefabImporter, string materialName, string targetPath, bool bypassRemappedMaterials = true, bool assignRemaps = false, Action <Material> postExtractAction = null) { // TODO : implement single material extraction if (targetPath.Length != 0) { // getting existing remaps var existingRemaps = new Dictionary <string, Material>(); syncPrefabImporter.GetRemaps(out existingRemaps); // initializing new remaps var extractedRemaps = new Dictionary <string, Material>(); // getting all materials from imported objects var materials = new List <Material>(); syncPrefabImporter.GetImportedMaterials(out materials); // find material index // TODO : sorting materials by remaps order ? var index = materials.FindIndex(m => m.name == materialName); if (bypassRemappedMaterials && existingRemaps.ContainsValue(materials[index])) { return; } // duplicating material to destination var sourceName = materials[index].name; Material mCopy = new Material(materials[index]); postExtractAction?.Invoke(mCopy); AssetDatabase.CreateAsset(mCopy, targetPath); extractedRemaps.Add(sourceName, mCopy); // saving new materials AssetDatabase.SaveAssets(); if (assignRemaps) { var newRemaps = new Dictionary <string, Material>(); // mixing existing and extracted remaps foreach (KeyValuePair <string, Material> kvp in existingRemaps) { if (kvp.Value == null && extractedRemaps.ContainsKey(kvp.Key)) { newRemaps[kvp.Key] = extractedRemaps[kvp.Key]; } else { newRemaps[kvp.Key] = existingRemaps[kvp.Key]; } } syncPrefabImporter.SetRemaps(newRemaps); } } }
/// <summary> /// Extracts Imported Materials and assigns Remaps. /// </summary> /// <param name="syncPrefabImporter"></param> /// <param name="targetPath">Assets relative path to save new materials to.</param> /// <param name="bypassRemappedMaterials">Bypass already remapped materials.</param> /// <param name="assignRemaps">Automatically assign remaps after extraction.</param> /// <param name="postExtractAction">Action to call on extracted material.</param> public static void ExtractMaterials(this SyncPrefabScriptedImporter syncPrefabImporter, string targetPath, bool bypassRemappedMaterials = true, bool assignRemaps = false, Action <Material> postExtractAction = null) { if (targetPath.Length != 0) { // getting existing remaps var existingRemaps = new Dictionary <string, Material>(); syncPrefabImporter.GetRemaps(out existingRemaps); // initializing new remaps var extractedRemaps = new Dictionary <string, Material>(); // getting all materials from imported objects var materials = new List <Material>(); syncPrefabImporter.GetImportedMaterials(out materials); // duplicating materials to destination foreach (Material m in materials) { if (bypassRemappedMaterials && existingRemaps.ContainsValue(m)) { continue; } Material mCopy = new Material(m); postExtractAction?.Invoke(mCopy); AssetDatabase.CreateAsset(mCopy, Path.Combine(targetPath, m.name + ".mat")); extractedRemaps.Add(mCopy.name, mCopy); } // saving new materials AssetDatabase.SaveAssets(); if (assignRemaps) { var newRemaps = new Dictionary <string, Material>(); // mixing existing and extracted remaps foreach (KeyValuePair <string, Material> kvp in existingRemaps) { if (kvp.Value == null && extractedRemaps.ContainsKey(kvp.Key)) { newRemaps[kvp.Key] = extractedRemaps[kvp.Key]; } else { newRemaps[kvp.Key] = existingRemaps[kvp.Key]; } } syncPrefabImporter.SetRemaps(newRemaps); } } }
/// <summary> /// Returns a List of Material Remapping Names /// </summary> /// <param name="syncPrefabImporter"></param> /// <returns>A List of Material Remapping Names</returns> public static List <string> GetRemapNames(this SyncPrefabScriptedImporter syncPrefabImporter) { List <string> names = new List <string>(); var so = new SerializedObject(syncPrefabImporter); var sourceRemaps = so.FindProperty("m_MaterialRemaps"); for (int i = 0; i < sourceRemaps.arraySize; i++) { SerializedProperty item = sourceRemaps.GetArrayElementAtIndex(i); names.Add(item.FindPropertyRelative("syncMaterialName").stringValue); } return(names); }
/// <summary> /// Resets the Material Remaps. /// </summary> /// <param name="syncPrefabImporter"></param> public static void ResetRemaps(this SyncPrefabScriptedImporter syncPrefabImporter) { var so = new SerializedObject(syncPrefabImporter); var sourceRemaps = so.FindProperty("m_MaterialRemaps"); for (int i = 0; i < sourceRemaps.arraySize; i++) { SerializedProperty item = sourceRemaps.GetArrayElementAtIndex(i); item.FindPropertyRelative("remappedMaterial").objectReferenceValue = null; } so.ApplyModifiedProperties(); syncPrefabImporter.SaveAndReimport(); }
/// <summary> /// Provides a Dictionary of Material Remapping Names and Materials /// </summary> /// <param name="syncPrefabImporter"></param> /// <param name="remaps"></param> public static void GetRemaps(this SyncPrefabScriptedImporter syncPrefabImporter, out Dictionary <string, Material> remaps) { // using out to force storing result in calling method and prevent multiple calls to this. remaps = new Dictionary <string, Material>(); var so = new SerializedObject(syncPrefabImporter); var sourceRemaps = so.FindProperty("m_MaterialRemaps"); for (int i = 0; i < sourceRemaps.arraySize; i++) { SerializedProperty item = sourceRemaps.GetArrayElementAtIndex(i); remaps.Add(item.FindPropertyRelative("syncMaterialName").stringValue, (Material)item.FindPropertyRelative("remappedMaterial").objectReferenceValue); } }
/// <summary> /// Returns a List of Remapping Materials /// </summary> /// <param name="syncPrefabImporter"></param> /// <returns>A List of Remapping Materials</returns> public static List <Material> GetRemapMaterials(this SyncPrefabScriptedImporter syncPrefabImporter) { List <Material> materials = new List <Material>(); var so = new SerializedObject(syncPrefabImporter); var sourceRemaps = so.FindProperty("m_MaterialRemaps"); for (int i = 0; i < sourceRemaps.arraySize; i++) { SerializedProperty item = sourceRemaps.GetArrayElementAtIndex(i); materials.Add((Material)item.FindPropertyRelative("remappedMaterial").objectReferenceValue); } return(materials); }
/// <summary> /// Collects all materials from Renderers found in the Imported object's hierarchy. /// </summary> /// <param name="syncPrefabImporter"></param> /// <param name="materials"></param> public static void GetImportedMaterials(this SyncPrefabScriptedImporter syncPrefabImporter, out List <Material> materials) { // using out to force storing result in calling method and prevent multiple calls to this. materials = new List <Material>(); var root = syncPrefabImporter.GetRoot(); foreach (Renderer r in root.GetComponentsInChildren <Renderer>()) { foreach (Material m in r.sharedMaterials) { if (!materials.Contains(m)) { materials.Add(m); } } } }
static void AssignMaterialRemaps(SyncPrefabScriptedImporter importer) { if (importer) { // find all ScriptableObject based remaps if (!AssetDatabase.IsValidFolder("Assets/Reflect")) { return; } List <MaterialMappings> remappers = new List <MaterialMappings>(); foreach (string guid in AssetDatabase.FindAssets("t:MaterialMappings", new string[] { "Assets/Reflect" })) { var remapper = AssetDatabase.LoadAssetAtPath <MaterialMappings>(AssetDatabase.GUIDToAssetPath(guid)); //if (remapper.enabled) remappers.Add(remapper); } // sort remaps by priority (to prioritize conflicting remaps) //remappers.Sort((a, b) => a.priority.CompareTo(b.priority)); // for every material names, loop through remaps to find an override Dictionary <string, Material> remaps; importer.GetRemaps(out remaps); var names = importer.GetRemapNames(); foreach (string name in names) { foreach (MaterialMappings remapper in remappers) { var remapperNames = remapper.materialNames; if (remapperNames.Contains(name) && (remaps[name] == null /* || remapper.overwrite*/)) { //Debug.Log(string.Format("{0} => {1}", name, remapper.materialRemaps[remapperNames.FindIndex(x => x == name)].remappedMaterial)); remaps[name] = remapper[remapperNames.FindIndex(x => x == name)].remappedMaterial; break; } } } // assign override importer.SetRemaps(remaps); } }
/// <summary> /// Assign a Dictionary of Material Remapping Names and Materials to Material Remaps /// </summary> /// <param name="syncPrefabImporter"></param> /// <param name="remaps"></param> public static void SetRemaps(this SyncPrefabScriptedImporter syncPrefabImporter, Dictionary <string, Material> remaps) { var so = new SerializedObject(syncPrefabImporter); var targetRemaps = so.FindProperty("m_MaterialRemaps"); targetRemaps.arraySize = remaps.Count; var list = remaps.Keys.ToList(); //list.Sort(); // FIXME : why does this screw up the importer ? for (int i = 0; i < list.Count; i++) { SerializedProperty item = targetRemaps.GetArrayElementAtIndex(i); item.FindPropertyRelative("syncMaterialName").stringValue = list[i]; item.FindPropertyRelative("remappedMaterial").objectReferenceValue = remaps[list[i]]; } so.ApplyModifiedProperties(); syncPrefabImporter.SaveAndReimport(); }
internal static void ExtractMaterialsFromSyncPrefabImporter(SyncPrefabScriptedImporter importer) { var targetPath = EditorUtility.SaveFolderPanel( "Save Extracted Materials", Application.dataPath, ""); if (targetPath == string.Empty) { return; } // issue error if path is outside of Project's Assets if (!targetPath.StartsWith(Application.dataPath)) { Debug.LogError("Cannot save materials outside of project's assets folder!"); return; } targetPath = "Assets" + targetPath.Substring(Application.dataPath.Length); System.Action <Material> postAction = ReflectEditorPreferences.convertExtractedMaterials ? materialConversions[(int)ReflectEditorPreferences.extractedMaterialsConverionMethod] : null; importer.ExtractMaterials(targetPath, ReflectEditorPreferences.dontExtractRemappedMaterials, ReflectEditorPreferences.autoAssignRemapsOnExtract, postAction); }
internal static void FindMaterialsForSyncPrefabImporter(SyncPrefabScriptedImporter importer) { var targetPath = EditorUtility.OpenFolderPanel( "Pick Materials Location", Application.dataPath, ""); if (targetPath == string.Empty) { return; } // issue error if path is outside of Project's Assets if (!targetPath.StartsWith(Application.dataPath)) { Debug.LogError("Cannot save materials outside of project's assets folder!"); return; } targetPath = "Assets" + targetPath.Substring(Application.dataPath.Length); var materialsGUIDS = AssetDatabase.FindAssets("t:Material", new string[1] { targetPath }); var materials = new Dictionary <string, Material>(); foreach (string guid in materialsGUIDS) { var mat = AssetDatabase.LoadAssetAtPath <Material>(AssetDatabase.GUIDToAssetPath(guid)); if (mat) { materials.Add(mat.name, mat); } } var remaps = new Dictionary <string, Material>(); importer.GetRemaps(out remaps); switch (ReflectEditorPreferences.materialSearchMatchType) { case MaterialMappings.MatchType.A_Equals_B: foreach (KeyValuePair <string, Material> kvp in materials) { if (remaps.ContainsKey(kvp.Key) && remaps[kvp.Key] == null) // TODO : add an option to override existing materials ? { remaps[kvp.Key] = kvp.Value; } } break; default: var remapsNames = remaps.Keys.ToList(); foreach (KeyValuePair <string, Material> kvp_m in materials) { foreach (string r in remapsNames) { if (MaterialsOverride.Match(kvp_m.Key, r, ReflectEditorPreferences.materialSearchMatchType) && remaps[r] == null) { remaps[r] = kvp_m.Value; } } } break; } importer.SetRemaps(remaps); }
internal static void SortRemaps(SyncPrefabScriptedImporter importer) { importer.SortRemaps(); }
internal static void WhiteBoxSyncPrefabImporter(SyncPrefabScriptedImporter importer) { string path = "Assets/Materials/White Box"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } Material whiteBoxMaterial; var whiteBoxMaterialPath = Path.Combine(path, "white.mat"); if (File.Exists(whiteBoxMaterialPath)) { whiteBoxMaterial = AssetDatabase.LoadAssetAtPath <Material>(whiteBoxMaterialPath); } else { whiteBoxMaterial = new Material(Shader.Find("Standard")); // TODO : set material default values whiteBoxMaterial.color = new Color(.9f, .9f, .9f, 1); whiteBoxMaterial.SetFloat("_Glossiness", 0.2f); AssetDatabase.CreateAsset(whiteBoxMaterial, whiteBoxMaterialPath); AssetDatabase.SaveAssets(); } Material glassBoxMaterial; var glassBoxMaterialPath = Path.Combine(path, "glass.mat"); if (File.Exists(glassBoxMaterialPath)) { glassBoxMaterial = AssetDatabase.LoadAssetAtPath <Material>(glassBoxMaterialPath); } else { glassBoxMaterial = new Material(Shader.Find("Standard (Specular setup)")); // TODO : set material default values glassBoxMaterial.color = new Color(0, 0, 0, 0); glassBoxMaterial.SetColor("_SpecColor", new Color(0.32f, 0.4f, 0.4f, 1)); glassBoxMaterial.SetFloat("_Mode", 3.0f); glassBoxMaterial.SetFloat("_Glossiness", 0.9f); AssetDatabase.CreateAsset(glassBoxMaterial, glassBoxMaterialPath); AssetDatabase.SaveAssets(); } var remaps = new Dictionary <string, Material>(); importer.GetRemaps(out remaps); var remapsNames = remaps.Keys.ToList(); foreach (string r in remapsNames) { if (r.ToLower().Contains("glass")) // TODO : use a more accurate method based on material itself ? { remaps[r] = glassBoxMaterial; } else { remaps[r] = whiteBoxMaterial; } } importer.SetRemaps(remaps); }
/// <summary> /// Returns the Imported Object Root Transform. /// </summary> /// <param name="syncPrefabImporter"></param> /// <returns></returns> public static Transform GetRoot(this SyncPrefabScriptedImporter syncPrefabImporter) { return(AssetDatabase.LoadAssetAtPath <Transform>(syncPrefabImporter.assetPath)); }