Skip to content

Instantly share code, notes, and snippets.

@LuviKunG
Last active May 19, 2024 15:11
Show Gist options
  • Save LuviKunG/ff397034112b46e1d64a15c3fbb601d8 to your computer and use it in GitHub Desktop.
Save LuviKunG/ff397034112b46e1d64a15c3fbb601d8 to your computer and use it in GitHub Desktop.
Unity editor window that used to pick an object from the asset database such as scriptable objects or prefabs which contains specific component.
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace LuviKunG.Editor
{
using UnityObject = UnityEngine.Object;
/// <summary>
/// An editor window that allows the user to pick an object of a specific type.
/// </summary>
public sealed class ObjectPickerEditorWindow : EditorWindow
{
private const string WINDOW_TITLE = "Pick an object...";
private const string HELPBOX_MESSAGE_ERROR_NO_TYPE = "There are no type to pick.";
private const string HELPBOX_MESSAGE_NO_ASSETS_FOUND = "There are no assets found to pick.";
private static readonly GUIContent s_windowTitle;
private Type type;
private Action<UnityObject> onPick;
private List<UnityObject> assets;
private Vector2 scrollPosition;
static ObjectPickerEditorWindow()
{
s_windowTitle = new GUIContent(WINDOW_TITLE);
}
/// <summary>
/// Show the object picker window.
/// </summary>
/// <typeparam name="T">Type of the object to pick.</typeparam>
/// <param name="onPick">Callback when an object is picked.</param>
/// <returns>The object picker window.</returns>
public static ObjectPickerEditorWindow DisplayPicker<T>(Action<T> onPick) where T : UnityObject
{
ObjectPickerEditorWindow window = CreateInstance<ObjectPickerEditorWindow>();
window.titleContent = s_windowTitle;
window.type = typeof(T);
window.onPick = (obj) => onPick?.Invoke(obj as T);
window.Fetch();
window.ShowAuxWindow();
return window;
}
private void OnGUI()
{
using (var scrollViewScope = new EditorGUILayout.ScrollViewScope(scrollPosition))
{
scrollPosition = scrollViewScope.scrollPosition;
if (type == null)
{
EditorGUILayout.HelpBox(HELPBOX_MESSAGE_ERROR_NO_TYPE, MessageType.Error, true);
}
else if (assets == null || assets.Count == 0)
{
EditorGUILayout.HelpBox(HELPBOX_MESSAGE_NO_ASSETS_FOUND, MessageType.Info, true);
}
else
{
using (new EditorGUILayout.VerticalScope())
{
for (int i = 0; i < assets.Count; i++)
{
UnityObject asset = assets[i];
if (GUILayout.Button(asset.name, EditorStyles.objectField, GUILayout.ExpandWidth(true)))
{
onPick?.Invoke(asset);
Close();
}
}
}
}
}
}
/// <summary>
/// Fetch assets of the specified type to this window.
/// </summary>
private void Fetch()
{
assets = new List<UnityObject>();
if (type.IsSubclassOf(typeof(Component)))
{
string[] assetGuids = AssetDatabase.FindAssets("t:prefab", null);
for (int i = 0; i < assetGuids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(assetGuids[i]);
GameObject gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (gameObject != null)
{
Component component = gameObject.GetComponent(type);
if (component != null)
{
assets.Add(component);
}
}
}
}
else if (type.IsSubclassOf(typeof(ScriptableObject)))
{
string[] assetGuids = AssetDatabase.FindAssets("t:" + type.Name, null);
for (int i = 0; i < assetGuids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(assetGuids[i]);
UnityObject asset = AssetDatabase.LoadAssetAtPath(path, type);
if (asset != null)
{
assets.Add(asset);
}
}
}
else if (type.IsSubclassOf(typeof(UnityObject)))
{
string[] assetGuids = AssetDatabase.FindAssets("t:" + type.Name, null);
for (int i = 0; i < assetGuids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(assetGuids[i]);
UnityObject asset = AssetDatabase.LoadAssetAtPath(path, type);
if (asset != null)
{
assets.Add(asset);
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment