using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using System;
|
|
using System.Linq;
|
|
|
|
/// <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("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);
|
|
|
|
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
}
|