You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

230 lines
7.2 KiB

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
/// <summary>
/// Editor Class used to search and replace objects with prefabs;
/// </summary>
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("Cancel")) {
}
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);
}
/// <summary>
/// Logic of when the window has been clicked
/// </summary>
/// <param name="mousePos">position of mouse when clicked</param>
/// <returns></returns>
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
/// <summary>
/// Returns an array of listItems of gameobjects in scene which contains a string
/// </summary>
/// <param name="filter">look for gameobjects containing this string</param>
/// <returns></returns>
private static ListItem[] getFilteredList(string filter, StringComparison caseComparer = StringComparison.OrdinalIgnoreCase)
{
List<ListItem> retVal = new List<ListItem>();
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;
}
}