forked from Shardstone/trail-into-darkness
changed directory structure
This commit is contained in:
141
Packages/com.jovian.inspector-tools/Editor/Tools/AutoFindUtil.cs
Normal file
141
Packages/com.jovian.inspector-tools/Editor/Tools/AutoFindUtil.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
#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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bc5f32e6036f5d4e8f5f8f8b145548b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Jovian.InspectorTools {
|
||||
public interface IActionableAttribute {
|
||||
#if UNITY_EDITOR
|
||||
void Trigger(SerializedProperty serializedProperty);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 581cfe2990d4d134d8ff859a2ee1377a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Jovian.InspectorTools {
|
||||
public interface IPropertyCondition {
|
||||
#if UNITY_EDITOR
|
||||
bool DoesPropertyMeetCondition(SerializedProperty property, out string description);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24e7483e9296c494283a1bb2f711c745
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9edfed511fd35584aa76d99f420d8ffb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Jovian.InspectorTools {
|
||||
public enum PlayModeVisibility {
|
||||
Always,
|
||||
EditMode,
|
||||
PlayMode
|
||||
}
|
||||
|
||||
public static class PlayModeVisibilityExtensions {
|
||||
public static bool IsVisible(this PlayModeVisibility visibility) {
|
||||
switch(visibility) {
|
||||
case PlayModeVisibility.EditMode:
|
||||
return Application.isPlaying == false;
|
||||
case PlayModeVisibility.PlayMode:
|
||||
return Application.isPlaying;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eaa053cd33e1de54da40cf9b02c51661
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,152 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace Jovian.InspectorTools.Internal {
|
||||
|
||||
public interface IGUILayoutPropertyField {
|
||||
void GUILayoutPropertyField(SerializedProperty serializedProperty, params GUILayoutOption[] options);
|
||||
void GUILayoutPropertyField(SerializedProperty serializedProperty, bool includeChildren, params GUILayoutOption[] options);
|
||||
void GUILayoutPropertyField(SerializedProperty serializedProperty, GUIContent label, bool includeChildren, params GUILayoutOption[] options);
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(Object), true)] [CanEditMultipleObjects]
|
||||
public class UnityObjectEditor : Editor, IGUILayoutPropertyField {
|
||||
private FoldoutAttributeHandler foldout;
|
||||
private ButtonMethodHandler buttonMethod;
|
||||
private ShowInInspectorAttributeHandler showInInspectorHandler;
|
||||
private float lastShowInInspectorTime;
|
||||
|
||||
|
||||
private static ButtonMethodHandler[] previewButtonMethods;
|
||||
private static Vector2 previewScroll;
|
||||
private Rect previewRect;
|
||||
|
||||
private void OnEnable() {
|
||||
if(target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foldout = new FoldoutAttributeHandler(target, serializedObject, this);
|
||||
buttonMethod = new ButtonMethodHandler(target);
|
||||
showInInspectorHandler = new ShowInInspectorAttributeHandler(target, serializedObject);
|
||||
|
||||
if (previewButtonMethods == null && target is Component component) {
|
||||
previewScroll = Vector2.zero;
|
||||
var objectComponents = component.gameObject.GetComponents<Component>();
|
||||
previewButtonMethods = new ButtonMethodHandler[objectComponents.Length];
|
||||
for (int i = 0; i < objectComponents.Length; i++) {
|
||||
previewButtonMethods[i] = new ButtonMethodHandler(objectComponents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
EditorApplication.update -= OnUpdate;
|
||||
EditorApplication.update += OnUpdate;
|
||||
}
|
||||
|
||||
private void OnDisable() {
|
||||
EditorApplication.update -= OnUpdate;
|
||||
foldout?.OnDisable();
|
||||
|
||||
previewButtonMethods = null;
|
||||
}
|
||||
|
||||
private void OnUpdate() {
|
||||
if(showInInspectorHandler?.HasValues == true) {
|
||||
float newShowInInspectorTime = Time.realtimeSinceStartup % 1f;
|
||||
if(newShowInInspectorTime < lastShowInInspectorTime) {
|
||||
Repaint();
|
||||
}
|
||||
lastShowInInspectorTime = newShowInInspectorTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
if (buttonMethod != null && buttonMethod.HasAnyVisibleMethods()) {
|
||||
buttonMethod?.OnBeforeInspectorGUI();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
if(foldout != null) {
|
||||
foldout.Update();
|
||||
if(!foldout.OverrideInspector) {
|
||||
base.OnInspectorGUI();
|
||||
}
|
||||
else {
|
||||
foldout.OnInspectorGUI();
|
||||
}
|
||||
}
|
||||
|
||||
if(showInInspectorHandler != null) {
|
||||
showInInspectorHandler.Update();
|
||||
if(showInInspectorHandler.HasValues) {
|
||||
showInInspectorHandler.OnInspectorGUI(this);
|
||||
}
|
||||
}
|
||||
|
||||
if(buttonMethod != null && buttonMethod.HasAnyVisibleMethods()){
|
||||
EditorGUILayout.Space();
|
||||
buttonMethod?.OnAfterInspectorGUI();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasAnyVisiblePreviewMethods() {
|
||||
if (previewButtonMethods == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var previewButtonMethod in previewButtonMethods) {
|
||||
if(previewButtonMethod == null) {
|
||||
continue;
|
||||
}
|
||||
if (previewButtonMethod.HasAnyVisibleMethods()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool HasPreviewGUI() => targets != null && targets.Length == 1 && target != null && HasAnyVisiblePreviewMethods();
|
||||
|
||||
public override void OnPreviewGUI(Rect r, GUIStyle background) {
|
||||
// Only Repaint has the true Rect size - so store it whenever we repaint.
|
||||
if (Event.current.type == EventType.Repaint) {
|
||||
previewRect = r;
|
||||
}
|
||||
GUILayout.BeginArea(previewRect);
|
||||
previewScroll = GUILayout.BeginScrollView(previewScroll);
|
||||
|
||||
foreach (var previewButtonMethod in previewButtonMethods) {
|
||||
if (previewButtonMethod.HasAnyVisibleMethods()) {
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(ObjectNames.NicifyVariableName(previewButtonMethod.Target.GetType().Name), EditorStyles.boldLabel);
|
||||
previewButtonMethod.OnBeforeInspectorGUI();
|
||||
previewButtonMethod.OnAfterInspectorGUI();
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
public void GUILayoutPropertyField(SerializedProperty serializedProperty, params GUILayoutOption[] options) {
|
||||
GUILayoutPropertyField(serializedProperty, true, options);
|
||||
}
|
||||
|
||||
public void GUILayoutPropertyField(SerializedProperty serializedProperty, bool includeChildren, params GUILayoutOption[] options) {
|
||||
GUILayoutPropertyField(serializedProperty, new GUIContent(ObjectNames.NicifyVariableName(serializedProperty.name), serializedProperty.tooltip), includeChildren, options);
|
||||
}
|
||||
|
||||
public void GUILayoutPropertyField(SerializedProperty serializedProperty, GUIContent label, bool includeChildren, params GUILayoutOption[] options) {
|
||||
if (serializedProperty.isArray) {
|
||||
ArrayAttributePropertyHandler.DrawArrayProperty(serializedProperty, label, includeChildren, options);
|
||||
}
|
||||
else {
|
||||
EditorGUILayout.PropertyField(serializedProperty, label, includeChildren, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e53afb9413554e64be65650721f4bb12
|
||||
timeCreated: 1576668537
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
namespace Jovian.InspectorTools.Internal {
|
||||
|
||||
public static class RequiredUtil {
|
||||
private const float ICON_X_OFFSET = 15f;
|
||||
private const float ICON_SIZE = 18f;
|
||||
private static Color ErrorColor = new(1f, 0.5f, 0.5f, 1f);
|
||||
private static GUIContent errorIcon;
|
||||
private static GUIStyle errorStyle;
|
||||
|
||||
public static void LayoutRequired(ref Rect position, string tooltip, bool indent = true) {
|
||||
if (indent) {
|
||||
position.x += ICON_SIZE;
|
||||
position.width -= ICON_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawRequired(ref Rect position, string tooltip, bool indent = true) {
|
||||
if(errorIcon == null || errorStyle == null) {
|
||||
errorIcon = new GUIContent(EditorGUIUtility.IconContent("console.erroricon.sml").image);
|
||||
errorStyle = new GUIStyle(GUI.skin.label) {
|
||||
padding = new RectOffset(0, 0, 0, 0),
|
||||
imagePosition = ImagePosition.ImageOnly
|
||||
};
|
||||
}
|
||||
|
||||
errorIcon.tooltip = tooltip;
|
||||
|
||||
Rect errorIconRect = new Rect(position.x - ICON_X_OFFSET, position.y + 1, ICON_SIZE, EditorGUIUtility.singleLineHeight);
|
||||
GUI.Label(errorIconRect, errorIcon, errorStyle);
|
||||
GUI.color = ErrorColor;
|
||||
|
||||
if (indent) {
|
||||
position.x += ICON_SIZE;
|
||||
position.width -= ICON_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64fce657f181acc4f85facc3de64fba7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user