123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR
- using System;
- using System.IO;
- using UnityEditor;
- using UnityEngine;
- using static Animancer.Editor.AnimancerGUI;
- using Object = UnityEngine.Object;
- namespace Animancer.Editor
- {
- /// <summary>[Editor-Only] A custom Inspector for <see cref="StringAsset"/> fields.</summary>
- /// https://kybernetik.com.au/animancer/api/Animancer.Editor/StringAssetDrawer
- [CustomPropertyDrawer(typeof(StringAsset), true)]
- public class StringAssetDrawer : PropertyDrawer
- {
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- => LineHeight;
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override void OnGUI(Rect area, SerializedProperty property, GUIContent label)
- {
- label = EditorGUI.BeginProperty(area, label, property);
- property.objectReferenceValue = DrawGUI(
- area,
- label,
- property,
- out var exitGUI);
- if (exitGUI)
- {
- property.serializedObject.ApplyModifiedProperties();
- GUIUtility.ExitGUI();
- }
- EditorGUI.EndProperty();
- }
- /************************************************************************************************************************/
- private static readonly Func<Object[]> GetCurrentPropertyValues =
- () => _CurrentProperty != null ? Serialization.GetValues<Object>(_CurrentProperty) : null;
- private static SerializedProperty _CurrentProperty;
- /// <summary>Draws the GUI for a <see cref="StringAsset"/>.</summary>
- public static Object DrawGUI(
- Rect area,
- GUIContent label,
- SerializedProperty property,
- out bool exitGUI)
- {
- var showMixedValue = EditorGUI.showMixedValue;
- if (property != null && property.hasMultipleDifferentValues)
- EditorGUI.showMixedValue = true;
- _CurrentProperty = property;
- var value = DrawGUI(
- area,
- label,
- property?.objectReferenceValue,
- property?.serializedObject?.targetObject,
- out exitGUI,
- GetCurrentPropertyValues);
- _CurrentProperty = null;
- EditorGUI.showMixedValue = showMixedValue;
- return value;
- }
- /************************************************************************************************************************/
- private static readonly int ButtonHash = "Button".GetHashCode();
- private static readonly int ObjectFieldHash = "s_ObjectFieldHash".GetHashCode();
- /// <summary>Draws the GUI for a <see cref="StringAsset"/>.</summary>
- public static Object DrawGUI(
- Rect area,
- GUIContent label,
- Object value,
- Object context,
- out bool exitGUI,
- Func<Object[]> getAllValues = null)
- {
- var currentEvent = Event.current;
- if (currentEvent.type == EventType.Repaint &&
- !area.Contains(currentEvent.mousePosition) &&
- !IsDraggingStringAsset())
- {
- GUIUtility.GetControlID(ButtonHash, FocusType.Passive);// Button.
- GUIUtility.GetControlID(ButtonHash, FocusType.Passive);// Button.
- GUIUtility.GetControlID(DragHint, FocusType.Passive, area);// DragAndDrop.
- var iconSize = EditorGUIUtility.GetIconSize();
- var newIconSize = LineHeight * 2 / 3;
- EditorGUIUtility.SetIconSize(new(newIconSize, newIconSize));
- var controlID = GUIUtility.GetControlID(ObjectFieldHash, FocusType.Keyboard, area);// Object.
- var valueArea = EditorGUI.PrefixLabel(area, controlID, label);
- using (var content = PooledGUIContent.Acquire())
- {
- if (value != null)
- {
- content.text = value.name;
- content.image = AnimancerIcons.ScriptableObject;
- }
- else
- {
- content.text = "";
- content.image = AssetPreview.GetMiniTypeThumbnail(typeof(StringAsset));
- }
- EditorStyles.objectField.Draw(valueArea, content, false, false, false, false);
- }
- EditorGUIUtility.SetIconSize(iconSize);
- exitGUI = false;
- return value;
- }
- if (value == null)
- {
- var buttonArea = StealFromRight(ref area, area.height, StandardSpacing);
- var content = AnimancerIcons.AddIcon("Create and save a new String Asset");
- if (GUI.Button(buttonArea, content, NoPaddingButtonStyle))
- {
- exitGUI = true;
- return CreateNewInstance(label.text, context);
- }
- GUIUtility.GetControlID(ButtonHash, FocusType.Passive);
- }
- else
- {
- var clearArea = StealFromRight(ref area, area.height, StandardSpacing);
- var copyArea = StealFromRight(ref area, area.height, StandardSpacing);
- var content = AnimancerIcons.CopyIcon("Copy string to clipboard");
- if (GUI.Button(copyArea, content, NoPaddingButtonStyle))
- GUIUtility.systemCopyBuffer = value.name;
- content = AnimancerIcons.ClearIcon("Clear reference");
- if (GUI.Button(clearArea, content, NoPaddingButtonStyle))
- value = null;
- }
- HandleDragAndDrop(area, currentEvent, value, getAllValues);
- exitGUI = false;
- return EditorGUI.ObjectField(area, label, value, typeof(StringAsset), false);
- }
- /************************************************************************************************************************/
- private static readonly int DragHint = "Drag".GetHashCode();
- private static void HandleDragAndDrop(
- Rect area,
- Event currentEvent,
- Object value,
- Func<Object[]> getAllValues)
- {
- var id = GUIUtility.GetControlID(DragHint, FocusType.Passive, area);
- switch (currentEvent.type)
- {
- // Drag out of object field.
- case EventType.MouseDrag:
- if (GUIUtility.keyboardControl == id + 1 &&
- currentEvent.button == 0 &&
- area.Contains(currentEvent.mousePosition) &&
- value != null)
- {
- var values = getAllValues?.Invoke() ?? new Object[] { value };
- DragAndDrop.PrepareStartDrag();
- DragAndDrop.objectReferences = values;
- DragAndDrop.StartDrag("Objects");
- currentEvent.Use();
- }
- break;
- }
- }
- /// <summary>Is a <see cref="StringAsset"/> currently being dragged?</summary>
- private static bool IsDraggingStringAsset()
- {
- var dragging = DragAndDrop.objectReferences;
- if (dragging.IsNullOrEmpty())
- return false;
- for (int i = 0; i < dragging.Length; i++)
- if (dragging[i] is not StringAsset)
- return false;
- return true;
- }
- /************************************************************************************************************************/
- private const string FolderPathKey = nameof(StringAsset) + ".FolderPath";
- /// <summary>Asks where to save a new <see cref="StringAsset"/>.</summary>
- private static Object CreateNewInstance(string name, Object targetObject)
- {
- var folderPath = GetSaveFolder(targetObject);
- var path = EditorUtility.SaveFilePanelInProject(
- "Create String Asset",
- name,
- "asset",
- "Where yould you like to save the new String Asset?",
- folderPath);
- if (string.IsNullOrEmpty(path))
- return null;
- EditorPrefs.SetString(FolderPathKey, Path.GetDirectoryName(path));
- var instance = ScriptableObject.CreateInstance<StringAsset>();
- AssetDatabase.CreateAsset(instance, path);
- return instance;
- }
- private static string GetSaveFolder(Object targetObject)
- {
- var getActiveFolderPath = typeof(ProjectWindowUtil).GetMethod(
- "GetActiveFolderPath",
- AnimancerReflection.StaticBindings,
- null,
- Type.EmptyTypes,
- null);
- if (getActiveFolderPath != null &&
- getActiveFolderPath.ReturnType == typeof(string))
- {
- var activeFolderPath = getActiveFolderPath.Invoke(null, Array.Empty<object>())?.ToString();
- if (!string.IsNullOrEmpty(activeFolderPath))
- return activeFolderPath;
- }
- var folderPath = AssetDatabase.GetAssetPath(targetObject);
- if (!string.IsNullOrEmpty(folderPath))
- folderPath = Path.GetDirectoryName(folderPath);
- if (string.IsNullOrEmpty(folderPath))
- {
- folderPath = EditorPrefs.GetString(FolderPathKey);
- if (folderPath == null || !folderPath.StartsWith("Assets/"))
- folderPath = "Assets/";
- }
- return folderPath;
- }
- /************************************************************************************************************************/
- }
- }
- #endif
|