Net.Like.Xue.Tokyo/Assets/Plugins/SerializedCollections/Editor/Scripts/Utility/SCEditorUtility.cs

250 lines
9.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using System.Linq;
using AYellowpaper.SerializedCollections.Editor.Data;
using UnityEngine;
using System.Collections;
namespace AYellowpaper.SerializedCollections.Editor
{
internal static class SCEditorUtility
{
public const string EditorPrefsPrefix = "SC_";
public const bool KeyFlag = true;
public const bool ValueFlag = false;
public static float CalculateHeight(SerializedProperty property, DisplayType displayType)
{
return CalculateHeight(property, displayType == DisplayType.List ? true : false);
}
public static float CalculateHeight(SerializedProperty property, bool drawAsList)
{
if (drawAsList)
{
float height = 0;
foreach (SerializedProperty child in GetChildren(property))
height += EditorGUI.GetPropertyHeight(child, true);
return height;
}
return EditorGUI.GetPropertyHeight(property, true);
}
public static IEnumerable<SerializedProperty> GetChildren(SerializedProperty property, bool recursive = false)
{
if (!property.hasVisibleChildren)
{
yield return property;
yield break;
}
SerializedProperty end = property.GetEndProperty();
property.NextVisible(true);
do
{
yield return property;
} while (property.NextVisible(recursive) && !SerializedProperty.EqualContents(property, end));
}
public static PropertyData GetPropertyData(SerializedProperty property)
{
var data = new PropertyData();
var json = EditorPrefs.GetString(EditorPrefsPrefix + property.propertyPath, null);
if (json != null)
EditorJsonUtility.FromJsonOverwrite(json, data);
return data;
}
public static void SavePropertyData(SerializedProperty property, PropertyData propertyData)
{
var json = EditorJsonUtility.ToJson(propertyData);
EditorPrefs.SetString(EditorPrefsPrefix + property.propertyPath, json);
}
public static bool ShouldShowSearch(int pages)
{
var settings = EditorUserSettings.Get();
return settings.AlwaysShowSearch ? true : pages >= settings.PageCountForSearch;
}
public static bool HasDrawerForType(Type type)
{
Type attributeUtilityType = typeof(SerializedProperty).Assembly.GetType("UnityEditor.ScriptAttributeUtility");
if (attributeUtilityType == null)
return false;
var getDrawerMethod = attributeUtilityType.GetMethod("GetDrawerTypeForType", BindingFlags.Static | BindingFlags.NonPublic);
if (getDrawerMethod == null)
return false;
try
{
if (getDrawerMethod.GetParameters().Length is 2)
{
var value = getDrawerMethod.Invoke(null, new object[] { type,false });
return value!=null;
}
else
{
var value = getDrawerMethod.Invoke(null, new object[] { type });
return value!=null;
}
}
catch (TargetParameterCountException e)
{
//对比参数
var parameters = getDrawerMethod.GetParameters();
Debug.LogWarning(string.Join(", ", parameters.Select(p => $"{p.Name}:{p.ParameterType}").ToArray()));
}
return false;
}
internal static void AddGenericMenuItem(GenericMenu genericMenu, bool isOn, bool isEnabled, GUIContent content, GenericMenu.MenuFunction action)
{
if (isEnabled)
genericMenu.AddItem(content, isOn, action);
else
genericMenu.AddDisabledItem(content);
}
internal static void AddGenericMenuItem(GenericMenu genericMenu, bool isOn, bool isEnabled, GUIContent content, GenericMenu.MenuFunction2 action, object userData)
{
if (isEnabled)
genericMenu.AddItem(content, isOn, action, userData);
else
genericMenu.AddDisabledItem(content);
}
internal static bool TryGetTypeFromProperty(SerializedProperty property, out Type type)
{
try
{
var classType = typeof(EditorGUI).Assembly.GetType("UnityEditor.ScriptAttributeUtility");
var methodInfo = classType.GetMethod("GetFieldInfoFromProperty", BindingFlags.Static | BindingFlags.NonPublic);
var parameters = new object[] { property, null };
methodInfo.Invoke(null, parameters);
type = (Type) parameters[1];
return true;
}
catch
{
type = null;
return false;
}
}
internal static float DoHorizontalScale(Rect rect, float value)
{
var controlId = GUIUtility.GetControlID(FocusType.Passive);
var isMovingMouse = Event.current.type == EventType.MouseDrag;
DoButtonControl(rect, controlId, false, false, GUIContent.none, GUIStyle.none);
if (controlId == GUIUtility.hotControl && isMovingMouse)
{
value += Event.current.delta.x;
GUI.changed = true;
}
EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeHorizontal);
return value;
}
internal static bool DoButtonControl(Rect rect, int id, bool on, bool hover, GUIContent content, GUIStyle style)
{
Event current = Event.current;
switch (current.type)
{
case EventType.MouseDown:
if (HitTest(rect, current.mousePosition))
{
GUIUtility.hotControl = id;
current.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id)
{
GUIUtility.hotControl = 0;
current.Use();
if (HitTest(rect, current.mousePosition))
{
GUI.changed = true;
return !on;
}
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
current.Use();
}
break;
case EventType.KeyDown:
bool flag = current.alt || current.shift || current.command || current.control;
if ((current.keyCode == KeyCode.Space || current.keyCode == KeyCode.Return || current.keyCode == KeyCode.KeypadEnter) && !flag && GUIUtility.keyboardControl == id)
{
current.Use();
GUI.changed = true;
return !on;
}
break;
case EventType.Repaint:
style.Draw(rect, content, id, on, hover);
break;
}
return on;
}
internal static bool HitTest(Rect rect, Vector2 point) => point.x >= rect.xMin && point.x < rect.xMax && point.y >= rect.yMin && point.y < rect.yMax;
public static object GetPropertyValue(SerializedProperty prop, object target)
{
var path = prop.propertyPath.Replace(".Array.data[", "[");
var elements = path.Split('.');
foreach (var element in elements.Take(elements.Length - 1))
{
if (element.Contains("["))
{
var elementName = element.Substring(0, element.IndexOf("["));
var index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
target = GetValue(target, elementName, index);
}
else
{
target = GetValue(target, element);
}
}
return target;
}
public static object GetValue(object source, string name)
{
if (source == null)
return null;
var type = source.GetType();
var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (f == null)
{
var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (p == null)
return null;
return p.GetValue(source, null);
}
return f.GetValue(source);
}
public static object GetValue(object source, string name, int index)
{
var enumerable = GetValue(source, name) as IEnumerable;
var enm = enumerable.GetEnumerator();
while (index-- >= 0)
enm.MoveNext();
return enm.Current;
}
}
}