using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System; using System.Linq; /// /// Editor Class used to search and replace objects with prefabs; /// public class MassReplacer : EditorWindow { #region Editor Settings //base settings private string FilterText; private ListItem[] FilteredList; private GameObject CopiedPrefab; //advanced settings private bool doCopyScale = true; private bool doCopyRot = true; private bool isCaseSensitive = false; #endregion Editor Settings #region Private Variables private Vector2 scrollPosition; private string prevFilterText; private bool showAdvancedSettings; #endregion Private Variables #region GUI Functions [MenuItem("Tools/Mass Replace %e")] static void createWindow() { MassReplacer window = (MassReplacer)GetWindow(typeof(MassReplacer), true, "Replace", true); window.ReFilterList(window.FilterText); window.Repaint(); } void OnGUI() { Event e = Event.current; //Base Settings EditorGUILayout.LabelField("Base Settings", EditorStyles.boldLabel); FilterText = EditorGUILayout.TextField((FilterText == null || FilterText == "") ? "Search..." : FilterText); //If textFiled is empty display "Searching..." else display search filter CopiedPrefab = (GameObject)EditorGUILayout.ObjectField(CopiedPrefab, typeof(GameObject), true); //Advanced Settings GUIStyle BoldFold = new GUIStyle(EditorStyles.foldout); BoldFold.font = EditorStyles.boldFont; //create foldoutstyle with bold text showAdvancedSettings = EditorGUILayout.Foldout(showAdvancedSettings, "Advanced Settings", BoldFold); if (showAdvancedSettings) { doCopyScale = EditorGUILayout.Toggle("Copy Scale", doCopyScale); doCopyRot = EditorGUILayout.Toggle("Copy Rotation", doCopyRot); isCaseSensitive = EditorGUILayout.Toggle("Case Sensitive Search", isCaseSensitive); } float advancedSettingHeight = 3 * ((showAdvancedSettings) ? 18 : 0); //Start of List GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); Rect scrollRect = GUILayoutUtility.GetLastRect(); scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Width(position.width), GUILayout.Height(position.height - (108 + advancedSettingHeight) )); scrollRect.height = position.height - (108 + advancedSettingHeight); //Each Item foreach (ListItem listItem in FilteredList) { GUILayout.BeginHorizontal(); listItem.isRepplaceable = GUILayout.Toggle(listItem.isRepplaceable, "", GUILayout.MaxWidth(10)); GUILayout.Label(listItem.gameObject.name); Rect tempRect = GUILayoutUtility.GetLastRect(); tempRect.position -= Vector2.down * (82 + advancedSettingHeight) + scrollPosition; if (tempRect.Overlaps(scrollRect)) listItem.rect = tempRect; GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); //end list //Buttons at bottom of window GUILayout.BeginHorizontal(); GUI.enabled = (CopiedPrefab != null); if (GUILayout.Button("Replace")) { replaceFiltedList(); } GUI.enabled = true; if (GUILayout.Button("Filter To Selected")) { foreach(ListItem item in FilteredList) { item.isRepplaceable = Selection.gameObjects.Contains(item.gameObject); } } GUILayout.EndHorizontal(); // end buttons //Interaction //Check if filter is updated; if (prevFilterText != FilterText) { ReFilterList(FilterText); } //If clicked window check where clicked happened if (e.button == 0 && e.type == EventType.MouseDown) OnWindowClick(e.mousePosition); } /// /// Logic of when the window has been clicked /// /// position of mouse when clicked /// private void OnWindowClick(Vector2 mousePos) { //Loops through each asset to see if one has been clicked on foreach (ListItem listItem in FilteredList) { if (listItem.rect.Contains(mousePos)) { Debug.Log("clicked: " + listItem.gameObject.name); Selection.activeGameObject = listItem.gameObject; break; }//end if }//end foreach } #endregion GUI Functions #region Search Functions #region Helper Functions private void ReFilterList(string filter) { if (filter == null) filter = ""; StringComparison caseComparer = (isCaseSensitive) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; FilteredList = getFilteredList(filter, caseComparer); prevFilterText = filter; Repaint(); } #endregion Helper Fucntions #region Static Functions /// /// Returns an array of listItems of gameobjects in scene which contains a string /// /// look for gameobjects containing this string /// private static ListItem[] getFilteredList(string filter, StringComparison caseComparer = StringComparison.OrdinalIgnoreCase) { List retVal = new List(); object[] obj = FindObjectsOfType(typeof(GameObject)); foreach (object o in obj) { GameObject g = (GameObject)o; if (g.name.Contains(filter, caseComparer)) { ListItem newItem = new ListItem(g); retVal.Add(newItem); } } return retVal.ToArray(); } #endregion Static Functions #endregion Search Functions #region Replace Fucntions private void replaceFiltedList() { foreach (ListItem listItem in FilteredList) { if (!listItem.isRepplaceable || listItem.gameObject.Equals(CopiedPrefab)) continue; GameObject replaceObject = (GameObject)PrefabUtility.InstantiatePrefab(CopiedPrefab); replaceObject.transform.parent = listItem.gameObject.transform.parent; replaceObject.transform.position = listItem.gameObject.transform.position; replaceObject.name = listItem.gameObject.name; if (doCopyRot) replaceObject.transform.rotation = listItem.gameObject.transform.rotation; if (doCopyScale) replaceObject.transform.localScale = listItem.gameObject.transform.localScale; Undo.RegisterCreatedObjectUndo(replaceObject, "Replaced Objects (" + FilterText + ")"); Undo.DestroyObjectImmediate(listItem.gameObject); } ReFilterList(FilterText); } #endregion Replace Fucntions class ListItem { public GameObject gameObject; public bool isRepplaceable; public Rect rect; public ListItem(GameObject gameObject) { this.gameObject = gameObject; isRepplaceable = true; rect = new Rect(); } } } static class MassReplaceOverides { public static bool Contains(this string source, string toCheck, StringComparison comp) { return source != null && toCheck != null && source.IndexOf(toCheck, comp) >= 0; } }