Files
trail-into-darkness/Packages/com.jovian.inspector-tools/Editor/Tools/AutoFindUtil.cs
2026-04-02 07:22:33 +02:00

142 lines
6.6 KiB
C#

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using Jovian.Utilities;
using Jovian.Utilities.Editor;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Jovian.InspectorTools {
public static class AutoFindUtil {
public static void Search(AutoFindAttribute autoFindAttribute, SerializedProperty property, bool autoAddIfMissing = false) {
Type propertyType = EditorSerializationUtility.GetTypeFromProperty(property);
foreach (Object targetObject in property.serializedObject.targetObjects) {
if (IsScopeGameObject(autoFindAttribute.scope)) {
GameObject targetGameObject = ((Component)targetObject).gameObject;
if (EditorSerializationUtility.IsPropertyAnArrayElement(property)) {
SerializedProperty arrayProperty =
EditorSerializationUtility.GetArrayPropertyWithElementProperty(property);
EditorSerializationUtility.SaveObjectProperties(
targetObject,
arrayProperty.name,
GetComponents(autoFindAttribute.scope, targetGameObject, propertyType,
autoFindAttribute.filter));
}
else {
Component component = GetComponent(autoFindAttribute.scope, targetGameObject, propertyType,
autoFindAttribute.filter);
if (autoAddIfMissing && !component) {
component = Undo.AddComponent(targetGameObject, propertyType);
}
EditorSerializationUtility.SaveObjectProperties(
targetObject,
property.name,
component);
}
}
else if (autoFindAttribute.scope == AutoFindScope.Scene) {
IEnumerable<Component> componentsInHierarchy =
FilterComponents(HierarchyUtility.FindComponentsInHierarchy(propertyType, true),
autoFindAttribute.filter);
if (EditorSerializationUtility.IsPropertyAnArrayElement(property)) {
SerializedProperty arrayProperty =
EditorSerializationUtility.GetArrayPropertyWithElementProperty(property);
EditorSerializationUtility.SaveObjectProperties(
targetObject,
arrayProperty.name,
componentsInHierarchy);
}
else {
EditorSerializationUtility.SaveObjectProperties(
targetObject,
property.name,
componentsInHierarchy.FirstOrDefault());
}
}
else if (autoFindAttribute.scope == AutoFindScope.Project) {
if (EditorSerializationUtility.IsPropertyAnArrayElement(property)) {
SerializedProperty arrayProperty =
EditorSerializationUtility.GetArrayPropertyWithElementProperty(property);
List<Object> assets = autoFindAttribute.isPrefab
? AssetUtility.FindAllPrefabsInProject(propertyType, autoFindAttribute.filter)
: AssetUtility.FindAllAssetsInProject(propertyType, autoFindAttribute.filter);
EditorSerializationUtility.SaveObjectProperties(
targetObject,
arrayProperty.name,
assets
);
}
else {
Object asset = autoFindAttribute.isPrefab
? AssetUtility.FindPrefabInProject(propertyType, autoFindAttribute.filter)
: AssetUtility.FindAssetInProject(propertyType, autoFindAttribute.filter);
EditorSerializationUtility.SaveObjectProperties(
targetObject,
property.name,
asset
);
}
}
}
}
private static bool IsScopeGameObject(AutoFindScope scope) {
switch (scope) {
case AutoFindScope.Self:
case AutoFindScope.SelfAndChildren:
case AutoFindScope.SelfAndParent:
return true;
}
return false;
}
private static Component GetComponent(AutoFindScope scope,
GameObject gameObject,
Type componentType,
string filter = null) {
return GetComponents(scope, gameObject, componentType, filter).FirstOrDefault();
}
private static IEnumerable<Component> GetComponents(AutoFindScope scope,
GameObject gameObject,
Type componentType,
string filter = null) {
switch (scope) {
case AutoFindScope.Self:
List<Component> result = new();
Component component = gameObject.GetComponent(componentType);
if (component != null) {
result.Add(component);
}
return FilterComponents(result, filter);
case AutoFindScope.SelfAndChildren:
return FilterComponents(gameObject.GetComponentsInChildren(componentType, true), filter);
case AutoFindScope.SelfAndParent:
return FilterComponents(gameObject.GetComponentsInParent(componentType, true), filter);
case AutoFindScope.Scene:
case AutoFindScope.Project:
throw new NotSupportedException($"{scope} is not supported with GetComponents");
default:
throw new ArgumentOutOfRangeException(nameof(scope), scope, null);
}
}
private static IEnumerable<Component> FilterComponents(IEnumerable<Component> components, string filter) {
return string.IsNullOrEmpty(filter) ? components : components.Where(c => FilterMatchesName(c.name, filter));
}
private static bool FilterMatchesName(string name, string filter) {
return name.Contains(filter, StringComparison.InvariantCultureIgnoreCase);
}
}
}
#endif