forked from Shardstone/trail-into-darkness
142 lines
6.6 KiB
C#
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 InspectorToolkit {
|
|
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
|